i'm building a table with pagination and sorting functionality and i'm missing something on sorting the items from all the pages.
what i want to do is to sort all items from page 1 and page 2 and not only from the current page that i'm on. can you please tell me how should i update my code to achieve that?
and i'm having another issue with the last column. how can i create a link with the href from propURL? at this moment i'm getting [object Object]
here i have a fiddle with my code
https://jsfiddle.net/c2kmruLs/2/
<div class="book-component">
<div class="table-wrapper">
</div>
</div>
var data = {
"headings": [
{
"displayName": "Book",
"columnID": "bookID"
},
{
"displayName": "Author",
"columnID": "authorID"
},
{
"displayName": "Year",
"columnID": "yearID"
},
{
"displayName": "",
"columnID": "urlID"
}
],
"items": [
{
"bookID": "The Great Gatsby",
"authorID": " F Scott Fitzgerald",
"yearID": "1925",
"urlId": {
"name": "View book",
"propURL": "https://google.com"
}
},
{
"bookID": "The Grapes of Wrath",
"authorID": "John Steinbeck",
"yearID": "1939",
"urlId": {
"name": "View book",
"propURL": "https://google.com"
}
},
{
"bookID": "A Wild Sheep Chase",
"authorID": "Haruki Murakami",
"yearID": "1982",
"urlId": {
"name": "View book",
"propURL": "https://google.com"
}
},
{
"bookID": "A Farewell to Arms",
"authorID": "Ernest Hemingway",
"yearID": "1929",
"urlId": {
"name": "View book",
"propURL": "https://google.com"
}
}
]
}
var TABLE = document.createElement('table');
TABLE.setAttribute('class', 'pagination');
TABLE.setAttribute('data-pagecount', '2');
const TABLE_WRAPPER = document.querySelector('.book-component .table-wrapper');
TABLE_WRAPPER.appendChild(TABLE);
for (const field in data) {
var tr = document.createElement('tr');
if(field == "headings"){
for (const child in data.headings) {
var th = document.createElement('th');
th.setAttribute('class', 'sort-cta');
tr.appendChild(th);
th.innerText = data.headings[child].displayName;
TABLE.appendChild(tr);
}
}
else if(field == "items"){
for (const child in data.items) {
var tr = document.createElement('tr');
let item = data.items[child];
for (const row in item) {
var td = document.createElement('td');
tr.appendChild(td);
td.innerText = item[row];
TABLE.appendChild(tr);
}
}
}
}
const SORT_LINK = document.querySelectorAll('.sort-cta');
SORT_LINK.forEach((item) => {
item.addEventListener('click', () => {
sortTable(0);
});
});
function sortTable(n) {
var table,
rows,
switching,
i,
x,
y,
shouldSwitch,
dir,
switchcount = 0;
table = document.querySelector('.pagination');
switching = true;
dir = 'asc';
while (switching) {
switching = false;
rows = table.rows;
for (i = 1; i < rows.length - 1; i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName('TD')[n];
y = rows[i + 1].getElementsByTagName('TD')[n];
if (dir == 'asc') {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
} else if (dir == 'desc') {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
switchcount++;
} else {
if (switchcount == 0 && dir == 'asc') {
dir = 'desc';
switching = true;
}
}
}
}
var perPage = 20;
function genTables() {
var tables = document.querySelectorAll(".pagination");
for (var i = 0; i < tables.length; i++) {
perPage = parseInt(tables[i].dataset.pagecount);
createFooters(tables[i]);
createTableMeta(tables[i]);
loadTable(tables[i]);
}
}
function loadTable(table) {
var startIndex = 0;
if (table.querySelector('th'))
startIndex = 1;
var start = (parseInt(table.dataset.currentpage) * table.dataset.pagecount) + startIndex;
var end = start + parseInt(table.dataset.pagecount);
var rows = table.rows;
for (var x = startIndex; x < rows.length; x++) {
if (x < start || x >= end)
rows[x].classList.add("inactive");
else
rows[x].classList.remove("inactive");
}
}
function createTableMeta(table) {
table.dataset.currentpage = "0";
}
function createFooters(table) {
var hasHeader = false;
if (table.querySelector('th'))
hasHeader = true;
var rows = table.rows.length;
if (hasHeader)
rows = rows - 1;
var numPages = rows / perPage;
var pager = document.createElement("div");
if (numPages % 1 > 0)
numPages = Math.floor(numPages) + 1;
pager.className = "pager";
for (var i = 0; i < numPages ; i++) {
var page = document.createElement("div");
page.innerHTML = i + 1;
page.className = "pager-item";
page.dataset.index = i;
if (i == 0)
page.classList.add("selected");
page.addEventListener('click', function() {
var parent = this.parentNode;
var items = parent.querySelectorAll(".pager-item");
for (var x = 0; x < items.length; x++) {
items[x].classList.remove("selected");
}
this.classList.add('selected');
table.dataset.currentpage = this.dataset.index;
loadTable(table);
});
pager.appendChild(page);
}
table.parentNode.insertBefore(pager, table);
}
window.addEventListener('load', function() {
genTables();
});
For your first question: I'm not sure if that is very useful for the user, because if you sort your second page of the table you will always have the highest value in your first page of your table. And that is something you won't do I guess.
Second question: You see an [obejct object], because you want to show that object directly. You have to loop again to show the value for it.
for (const row in item) {
var td = document.createElement('td');
if (typeof(item[row]) === 'object') {
for (const obj in item[row]) {
tr.appendChild(td);
td.innerHTML = '<a target="_blank" href="' + item[row][obj] + '">' + item[row][obj] + '</a>';
TABLE.appendChild(tr);
TABLE.appendChild(tr);
}
} else {
tr.appendChild(td);
td.innerText = item[row];
TABLE.appendChild(tr);
}
}
See example below:
var data = {
"headings": [
{
"displayName": "Book",
"columnID": "bookID"
},
{
"displayName": "Author",
"columnID": "authorID"
},
{
"displayName": "Year",
"columnID": "yearID"
},
{
"displayName": "",
"columnID": "urlID"
}
],
"items": [
{
"bookID": "The Great Gatsby",
"authorID": " F Scott Fitzgerald",
"yearID": "1925",
"urlId": {
"name": "View book",
"propURL": "https://google.com"
}
},
{
"bookID": "The Grapes of Wrath",
"authorID": "John Steinbeck",
"yearID": "1939",
"urlId": {
"name": "View book",
"propURL": "https://google.com"
}
},
{
"bookID": "A Wild Sheep Chase",
"authorID": "Haruki Murakami",
"yearID": "1982",
"urlId": {
"name": "View book",
"propURL": "https://google.com"
}
},
{
"bookID": "A Farewell to Arms",
"authorID": "Ernest Hemingway",
"yearID": "1929",
"urlId": {
"name": "View book",
"propURL": "https://google.com"
}
}
]
}
var TABLE = document.createElement('table');
TABLE.setAttribute('class', 'pagination');
TABLE.setAttribute('data-pagecount', '2');
const TABLE_WRAPPER = document.querySelector('.book-component .table-wrapper');
TABLE_WRAPPER.appendChild(TABLE);
for (const field in data) {
var tr = document.createElement('tr');
if(field == "headings"){
for (const child in data.headings) {
var th = document.createElement('th');
th.setAttribute('class', 'sort-cta');
tr.appendChild(th);
th.innerText = data.headings[child].displayName;
TABLE.appendChild(tr);
}
}
else if(field == "items"){
for (const child in data.items) {
var tr = document.createElement('tr');
let item = data.items[child];
for (const row in item) {
var td = document.createElement('td');
if (typeof(item[row]) === 'object') {
for (const obj in item[row]) {
tr.appendChild(td);
td.innerHTML = '<a target="_blank" href="' + item[row][obj] + '">' + item[row][obj] + '</a>';
TABLE.appendChild(tr);
}
} else {
tr.appendChild(td);
td.innerText = item[row];
TABLE.appendChild(tr);
}
}
}
}
}
const SORT_LINK = document.querySelectorAll('.sort-cta');
SORT_LINK.forEach((item) => {
item.addEventListener('click', () => {
sortTable(0);
});
});
function sortTable(n) {
var table,
rows,
switching,
i,
x,
y,
shouldSwitch,
dir,
switchcount = 0;
table = document.querySelector('.pagination');
switching = true;
dir = 'asc';
while (switching) {
switching = false;
rows = table.rows;
for (i = 1; i < rows.length - 1; i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName('TD')[n];
y = rows[i + 1].getElementsByTagName('TD')[n];
if (dir == 'asc') {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
} else if (dir == 'desc') {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
switchcount++;
} else {
if (switchcount == 0 && dir == 'asc') {
dir = 'desc';
switching = true;
}
}
}
}
var perPage = 20;
function genTables() {
var tables = document.querySelectorAll(".pagination");
for (var i = 0; i < tables.length; i++) {
perPage = parseInt(tables[i].dataset.pagecount);
createFooters(tables[i]);
createTableMeta(tables[i]);
loadTable(tables[i]);
}
}
// based on current page, only show the elements in that range
function loadTable(table) {
var startIndex = 0;
if (table.querySelector('th'))
startIndex = 1;
var start = (parseInt(table.dataset.currentpage) * table.dataset.pagecount) + startIndex;
var end = start + parseInt(table.dataset.pagecount);
var rows = table.rows;
for (var x = startIndex; x < rows.length; x++) {
if (x < start || x >= end)
rows[x].classList.add("inactive");
else
rows[x].classList.remove("inactive");
}
}
function createTableMeta(table) {
table.dataset.currentpage = "0";
}
function createFooters(table) {
var hasHeader = false;
if (table.querySelector('th'))
hasHeader = true;
var rows = table.rows.length;
if (hasHeader)
rows = rows - 1;
var numPages = rows / perPage;
var pager = document.createElement("div");
// add an extra page, if we're
if (numPages % 1 > 0)
numPages = Math.floor(numPages) + 1;
pager.className = "pager";
for (var i = 0; i < numPages ; i++) {
var page = document.createElement("div");
page.innerHTML = i + 1;
page.className = "pager-item";
page.dataset.index = i;
if (i == 0)
page.classList.add("selected");
page.addEventListener('click', function() {
var parent = this.parentNode;
var items = parent.querySelectorAll(".pager-item");
for (var x = 0; x < items.length; x++) {
items[x].classList.remove("selected");
}
this.classList.add('selected');
table.dataset.currentpage = this.dataset.index;
loadTable(table);
});
pager.appendChild(page);
}
// insert page at the top of the table
table.parentNode.insertBefore(pager, table);
}
window.addEventListener('load', function() {
genTables();
});
tr.inactive {
display: none;
}
.table-wrapper {
display: flex;
flex-direction: column-reverse;
}
.pager {
display: flex;
justify-content: center;
padding: 0;
margin-top: 10px;
font-weight: 800;
}
.pager-item.selected {
outline: none;
border-color: #0077cc;
background: #0077cc;
color: #fff;
cursor: default;
}
<div class="book-component">
<div class="table-wrapper">
</div>
</div>
Related
I'm creating a function that should take the data from an array (results) and put them into specific columns of the table. The array is divided with numbers that identify the column in which the following data should be entered.
Eg:
var results = [1, 'aaaaaa', 'bbb',2, 'ccc', 3, 'dddd', 'eeee', 4, 'fff'];
col 1: 'aaaaaa', 'bbb';
col 2: 'ccc'; etc.
I've tried it in many ways and I can not get it to work.
At the moment the code looks like this. I'm no sure how to do it:
var results = [1, 'aaaaaa','bbb',2, 'ccc', 3, 'dddd', 'eeee', 4, 'fff'];
var k = 0;
function populateTable(table, rows, cells, content) {
if (!table) table = document.createElement('table');
for (var i = 0; i < rows; ++i) {
var row = document.createElement('tr');
for (var j = 0; j < cells; ++j) {
row.appendChild(document.createElement('td'));
if (i > 0 && j == 0) {
row.cells[j].appendChild(document.createTextNode(content + 'PN'));
}
else if (i == 0 && j == 0) {
row.cells[j].appendChild(document.createTextNode(content + 'TYPE'));
}
else if (j > 0 && i == 0) {
row.cells[j].appendChild(document.createTextNode(content + 'LABLE ' + j));
}
else if (j > 0 && i > 0 && results[i] != k) {
row.cells[k].appendChild(document.createTextNode(content + results[i]));
}
}
table.appendChild(row);
k++;
}
return table;
}
function load() {
document.getElementById('tablearea')
.appendChild(populateTable(null, 9, 10, ""));
}
First format the results into something like:
{
1: ['aaaaaa', 'bbb'],
2: ['ccc'],
3: ['dddd', 'eeee'],
4: ['fff']
}
Then generate the table:
const results = [1, 'aaaaaa', 'bbb',2, 'ccc', 3, 'dddd', 'eeee', 4, 'fff', 5, 'ggg', 'hhhh', 'iiii'];
// First format the results
const formattedResults = {};
let columnIndex = 0;
results.forEach(elt => {
if (!isNaN(elt)) {
formattedResults[elt] = [];
columnIndex = elt;
} else {
formattedResults[columnIndex].push(elt);
}
});
// Then generate the table
const table = document.createElement('table');
const columnKeys = Object.keys(formattedResults);
const maxRows = Math.max(...columnKeys.map(key => formattedResults[key].length));
for (let i = 0; i < maxRows; i = i + 1) {
const tr = document.createElement('tr');
columnKeys.forEach(colKey => {
const td = document.createElement('td');
if (formattedResults[colKey][i] !== undefined) {
td.textContent = formattedResults[colKey][i];
tr.appendChild(td);
}
});
table.appendChild(tr);
}
document.getElementById('tableArea').appendChild(table);
<div id="tableArea"></div>
I am currently trying to learn about backtracking Algorithms and have been working on a Sudoku game. I understand the basic working of the algorithm and have written a Sudoku solver using it.
My current problem is related to removing a set amount of numbers from a completed Sudoku grid to create a valid Sudoku with a unique solution.
I have checked similar questions on here but have found no answers.
Here is an example of a solved Sudoku grid:
solvedSudokuGrid =
[["8","6","1","3","4","2","9","5","7"],
["2","5","3","8","7","9","4","6","1"],
["4","9","7","6","5","1","2","3","8"],
["6","7","2","5","1","8","3","9","4"],
["9","1","4","7","2","3","6","8","5"],
["5","3","8","4","9","6","7","1","2"],
["3","4","6","2","8","5","1","7","9"],
["7","8","9","1","3","4","5","2","6"],
["1","2","5","9","6","7","8","4","3"]];
Here is the function to remove a set amount of numbers from the grid:
function removeNrs(grid, nrsToBeRemoved) {
//check if enough numbers have been removed
if (nrsToBeRemoved <= 0) {
return true;
}
//find the next random full cell and set the grid to "" on that cell to remove a number
var nextNr = shuffle(findFullCells(grid))[0];
var row = nextNr[0];
var column = nextNr[1];
var value = grid[row][column];
grid[row][column] = "";
nrsToBeRemoved--;
//check if the sudoku grid has only 1 solution if yes start recursion
if (countAllSolutions(grid) < 2){
if(removeNrs(grid, nrsToBeRemoved)){
return grid;
}
}
//if the sudoku grid has more than 1 possible solution return the grid to the previous state and backtrack
grid[row][column] = value;
return false;
}
Here is the problem: If I enter a low amount of numbers to be removed the function works.
ex:
removeNrs(solvedSudokuGrid, 5); //returns a valid grid
If I enter a higher amount of numbers to be removed the function simply returns false.
ex:
removeNrs(solvedSudokuGrid, 50); //returns false
From the basic debugging that I have tried I can see that the function works as long as it does not have to backtrack. If the function has to backtrack it seems to return all the way to the beginning and finish with the original grid before returning false.
Any help, explenations or things to read are much appreciated.
Edit:
https://jsfiddle.net/mg57u0mv/
Here is the complete code but some of the names of functions and variables have been changed to fit better with the whole code.
function createTable() {
var tbl = document.createElement("table");
var tbdy = document.createElement("tbody");
for (var row = 0; row < 9; row++) {
var tr = document.createElement("tr");
for (var column = 0; column < 9; column++) {
var td = document.createElement("td");
var input = document.createElement("input");
input.type = "text";
input.id = "r"+row+"c"+column;
input.className = "grid-inputs grid-inputs-row-" + row;
//input.placeholder = "[" + row + " , " + column + "]";
//input.placeholder = input.id;
if ((row+1) % 3 === 0) {
td.style.borderBottom = "3px solid black";
}
if ((column+1) % 3 === 0) {
td.style.borderRight = "3px solid black";
}
tr.appendChild(td);
td.appendChild(input);
}
tbdy.appendChild(tr);
}
tbl.appendChild(tbdy);
document.body.appendChild(tbl);
}
function createButton(text, func) {
var button = document.createElement("button");
var t = document.createTextNode(text);
button.onclick = func;
button.appendChild(t);
document.body.appendChild(button);
}
function shuffle(array) {
var counter = array.length;
var temp, index;
while (counter) {
index = Math.floor(Math.random() * counter);
counter--;
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
}
function retrieveGrid() {
var result = [];
var rowContents = [];
for (var row = 0; row < 9; row++) {
for (var column = 0; column < 9; column++) {
rowContents.push(document.getElementsByClassName("grid-inputs-row-"+row)[column].value);
}
result.push(rowContents);
rowContents = [];
}
return result;
}
function printGrid(grid) {
for (var row = 0; row < 9; row++) {
for (var column = 0; column < 9; column++) {
document.getElementsByClassName("grid-inputs-row-"+row)[column].value = grid[row][column];
}
}
}
function checkRowColumnBlock(grid, row, column, value) {
//create row, column and block lists to be checked for doubles
var rowList = grid[row];
var columnList = [];
for (var columnCounter = 0; columnCounter < 9; columnCounter++) {
columnList.push(grid[columnCounter][column]);
}
var blockList = [];
for (var startRow = Math.floor(row/3) * 3, endRow = startRow + 3; startRow < endRow; startRow++) {
for (var startColumn = Math.floor(column/3) * 3, endColumn = startColumn + 3; startColumn < endColumn; startColumn++) {
blockList.push(grid[startRow][startColumn]);
}
}
//check row, column and block list for value
if (rowList.indexOf(value.toString()) === -1 &&
columnList.indexOf(value.toString()) === -1 &&
blockList.indexOf(value.toString()) === -1) {
return true;
} else {
return false;
}
}
function checkGrid(grid) {
for (var row = 0; row < 9; row++) {
for (var column = 0; column < 9; column++) {
if (grid[row][column] !== "") {
var value = grid[row][column];
grid[row][column] = "";
if (!checkRowColumnBlock(grid, row, column, value)) {
console.log("Invalid Grid");
return false;
}
grid[row][column] = value;
}
}
}
console.log("Valid Grid");
return true;
}
function findEmptyCells(grid) {
var result = [];
for (var row = 0; row < 9; row++){
for (var column = 0; column < 9; column++) {
if (grid[row][column] === "") {
result.push([row , column]);
}
}
}
if (result.length == 0) {
result = false;
}
return result;
}
function sortPossibilties(grid) {
var result = [];
var listOfEmptyCells = findEmptyCells(grid);
if (listOfEmptyCells === false) {
return false;
}
var listOfPossibilities = findPossibilitiesForGrid(grid);
var counter = listOfEmptyCells.length;
for (var cell = 0; cell < counter; cell++) {
result.push({"cell": listOfEmptyCells[cell], "possibilities": listOfPossibilities[cell]});
}
result.sort(function (first, second) {
return first.possibilities.length - second.possibilities.length;
});
return result;
}
function findNextEmptyCell(grid) {
var sortedEmptyCells = sortPossibilties(grid);
if (sortedEmptyCells === false) {
return false;
}
return sortedEmptyCells[0];
}
function findFullCells(grid) {
var result = [];
for (var row = 0; row < 9; row++){
for (var column = 0; column < 9; column++) {
if (grid[row][column] !== "") {
result.push([row , column]);
}
}
}
if (result.length == 0) {
result = false;
}
return result;
}
function findRandomFullCell(listOfFullCells) {
if (listOfFullCells === false) {
return false;
}
var result = listOfFullCells[Math.floor(Math.random() * listOfFullCells.length)];
return result;
}
function createEmptyGrid() {
//create grid 9x9 fill with blankspace
var grid = [];
for (var gridCounter = 0; gridCounter < 9; gridCounter++) {
grid.push(new Array(9).fill(""));
}
return grid;
}
function createIncRandomGrid(numberOfRandomCells) {
var grid = createEmptyGrid();
for (var counter = 0; counter < numberOfRandomCells; counter++) {
grid[Math.floor(Math.random() * 9)][Math.floor(Math.random() * 9)] =
Math.floor(Math.random() * 9 + 1).toString();
}
return grid;
}
function createCorRandomGrid(numberOfRandomCells) {
var grid;
do {grid = createIncRandomGrid(numberOfRandomCells);}
while (checkGrid(grid) === false);
return grid;
}
function findPossibilitiesForCell(grid, row, column) {
var possibilities = [];
for (var value = 1; value < 10; value++) {
if (checkRowColumnBlock(grid, row, column, value)) {
possibilities.push(value.toString());
}
}
return possibilities;
}
function findPossibilitiesForGrid(grid) {
var result = [];
var listOfEmptyCells = findEmptyCells(grid);
var amountOfEmptyCells = listOfEmptyCells.length;
for (var cell = 0; cell < amountOfEmptyCells; cell++) {
var row = listOfEmptyCells[cell][0];
var column = listOfEmptyCells[cell][1];
result.push(findPossibilitiesForCell(grid, row, column));
}
return result;
}
function solveSudoku(grid) {
var emptyCell = findNextEmptyCell(grid);
if (emptyCell === false) {
return true;
}
var row = emptyCell.cell[0];
var column = emptyCell.cell[1];
var valueList = shuffle(emptyCell.possibilities);
var valueListLength = valueList.length;
for (var valueIndex = 0; valueIndex < valueListLength; valueIndex++) {
if (checkRowColumnBlock(grid, row, column, valueList[valueIndex])) {
grid[row][column] = valueList[valueIndex].toString();
if (solveSudoku(grid)) {
return grid;
}
grid[row][column] = "";
}
}
return false;
}
function countAllSolutions(grid) {
var nrOfSolutions = 1;
function solveAll(grid) {
var emptyCell = findNextEmptyCell(grid);
if (emptyCell === false || nrOfSolutions > 1) {
return true;
}
var row = emptyCell.cell[0];
var column = emptyCell.cell[1];
var valueList = shuffle(emptyCell.possibilities);
var valueListLength = valueList.length;
for (var valueIndex = 0; valueIndex < valueListLength; valueIndex++) {
if (checkRowColumnBlock(grid, row, column, valueList[valueIndex])) {
grid[row][column] = valueList[valueIndex].toString();
if (solveAll(grid)) {
nrOfSolutions++;
}
grid[row][column] = "";
}
}
return false;
}
solveAll(grid);
return nrOfSolutions-1;
}
function findPossibilitiesForFullCell(grid, row, column) {
var possibilities = [];
var originalValue = grid[row][column];
grid[row][column] = "";
for (var value = 1; value < 10; value++) {
if (checkRowColumnBlock(grid, row, column, value)) {
possibilities.push(value.toString());
}
}
grid[row][column] = originalValue;
return possibilities;
}
function findPossibilitiesForFullGrid(grid) {
var result = [];
var listOfFullCells = findFullCells(grid);
var amountOfFullCells = listOfFullCells.length;
for (var cell = 0; cell < amountOfFullCells; cell++) {
var row = listOfFullCells[cell][0];
var column = listOfFullCells[cell][1];
result.push(findPossibilitiesForFullCell(grid, row, column));
}
return result;
}
function sortFullCells(grid) {
var result = [];
var listOfFullCells = findFullCells(grid);
if (listOfFullCells === false) {
return false;
}
var listOfPossibilities = findPossibilitiesForFullGrid(grid);
var counter = listOfFullCells.length;
for (var cell = 0; cell < counter; cell++) {
result.push({"cell": listOfFullCells[cell], "possibilities": listOfPossibilities[cell]});
}
result.sort(function (first, second) {
return first.possibilities.length - second.possibilities.length;
});
return result;
}
function findNextFullCells(grid) {
var sortedFullCells = sortFullCells(grid);
if (sortedFullCells === false) {
return false;
}
var result = [];
result.push(sortedFullCells[0]);
for (var cell = 1, length = sortedFullCells.length; cell < length; cell++){
if(sortedFullCells[cell].possibilities.length === sortedFullCells[0].possibilities.length) {
result.push(sortedFullCells[cell]);
}
}
return result;
}
function removeCells(grid, cellsToBeRemoved) {
if (cellsToBeRemoved <= 0) {
return grid;
}
var nextCell = shuffle(findFullCells(grid))[0];
var row = nextCell[0];
var column = nextCell[1];
var value = grid[row][column];
grid[row][column] = "";
cellsToBeRemoved--;
if (countAllSolutions(grid) < 2) {
grid = removeCells(grid, cellsToBeRemoved);
return grid;
} else {
grid[row][column] = value;
grid = removeCells(grid, cellsToBeRemoved);
}
return grid;
}
createTable();
createButton("Solve Sudoku", function () {
console.time("Solved");
printGrid(solveSudoku(retrieveGrid()));
console.timeEnd("Solved");
});
createButton("Remove Cells", function () {
console.time("Removed");
printGrid(removeCells(retrieveGrid(),55));
console.timeEnd("Removed");
});
createButton("Count Solutions", function () {
console.time("Counting");
console.log(countAllSolutions(retrieveGrid()));
console.timeEnd("Counting");
});
createButton("Create Random Grid", function () {
printGrid(createIncRandomGrid(100));
});
createButton("Create Correct Random Grid", function () {
printGrid(createCorRandomGrid(17));
});
createButton("Check Grid", function () {
checkGrid(retrieveGrid());
});
createButton("Count Full Cells", function () {
console.log(findFullCells(retrieveGrid()).length);
});
createButton("Count Empty Cells", function () {
console.log(findEmptyCells(retrieveGrid()).length);
});
createButton("Sort Empty Cells", function () {
console.log(sortPossibilties(retrieveGrid()));
});
createButton("Sort Full Cells", function () {
console.log(sortFullCells(retrieveGrid()));
});
createButton("Reset Grid", function () {
printGrid(createEmptyGrid());
});
I haven't actually tested it but I did test a similar function.
Try this at the end, replacing your last eight lines:
if (countAllSolutions(grid) < 2) grid = removeNrs(grid, nrsToBeRemoved);
else grid[row][column] = value;
return grid;
Here's an example of my JSON:
{
"2017-05-06": {
"13": {
"Chris": "2", "Ian": "3"
},
"14": {
"Chris": "4", "Rob": "4"
},
"16": {
"Ian": "3", "Rob": 2
}
}
}
Ideally, I need it to use JS to be able to display it in a table, and with any gaps filled with zeros, the column headers (hours) in sequence, even if they're empty, and total columns and rows.
2017-05-06
13 14 15 16 T
Chris 2 4 0 0 6
Ian 3 0 0 3 6
Rob 0 4 0 2 6
Total 5 8 0 5 18
I've no idea where to start, so would really appreciate any assistance or advice!
You could collect all totals in the given object and collect the rows and columns as well as the missing ones, then iterate rows and columns and build the table with the given data.
var data = { "2017-05-06": { 13: { Chris: "2", Ian: "3" }, 14: { Chris: "4", Rob: "4" }, 16: { Ian: "3", Rob: 2 } } };
Object.keys(data).forEach(function (k) {
var table = document.createElement('table'),
rows = [],
cols = Object.keys(data[k])
.sort(function (a, b) { return a - b; })
.reduce(function (r, a) {
var i = +r[r.length - 1];
while (++i < a) {
r.push(i.toString());
}
r.push(a);
return r;
}, []);
data[k].total = { total: 0 };
cols.forEach(function (l) {
var sub = data[k][l] || {};
Object.keys(sub).forEach(function (m) {
if (rows.indexOf(m) === -1) {
rows.push(m);
}
data[k].total[m] = (data[k].total[m] || 0) + +sub[m];
data[k].total.total += +sub[m];
sub.total = (sub.total || 0) + +sub[m];
});
});
cols.unshift('');
cols.push('total');
rows.unshift('');
rows.push('total')
rows.forEach(function (r) {
var tr = document.createElement('tr');
cols.forEach(function (c) {
var t = document.createElement(r && c ? 'td' : 'th'),
v = r && c ? (data[k][c] || {})[r] || 0 : r || c;
t.appendChild(document.createTextNode(v));
if (v == +v) {
t.style.textAlign = 'right';
}
tr.appendChild(t);
});
table.appendChild(tr);
});
document.body.appendChild(document.createTextNode(k));
document.body.appendChild(document.createElement('br'));
document.body.appendChild(table);
});
I would start by making two arrays, one for the rows and one for the columns, that contain all the row and column titles/keys that you want to display. Then iterate the row array/col array to build a table, if there is data for row+col write it otherwise write zero. Keep total variables summing as you go.
var data = {
"2017-05-06": {
"13": {"Chris": "2", "Ian": "3"},
"14": {"Chris": "4", "Rob": "4"},
"16": {"Ian": "3", "Rob": 2}
}
};
var d = data['2017-05-06'];
var keys = Object.keys(d).sort();
// from the lowest and highest "hours" values, create an array containing everything in between too
var hours = [];
for (var i = keys[0]; i <= keys[keys.length - 1]; i++) {
hours.push(i);
}
// get the unique names
var names = [];
for (var k in d) {
for (var l in d[k]) {
if (names.indexOf(l) === -1) names.push(l);
}
}
var colTotals = {'total':0};
var tbl = "<table><thead><tr><th>Name</th>";
for (var i=0,h; h = hours[i]; i++) {
tbl += "<th>" + h + "</th>";
colTotals[h] = 0;
}
tbl += "<th>Total</th></tr></thead><tbody>";
for (var i=0,n; n = names[i]; i++) {
tbl += "<tr><td>" + n + "</td>";
var total = 0;
for (var j=0,h; h = hours[j]; j++) {
tbl += "<td>";
// if data contains values for this row/col, add to total and table, otherwise put a zero
if (d[h] && d[h][n]) {
total += (d[h][n] - 0);
colTotals[h] += (d[h][n] - 0);
tbl += d[h][n];
} else {
tbl += "0";
}
tbl += "</td>";
}
colTotals['total'] += total;
tbl += "<td>" + total + "</td></tr>";
}
tbl += "<tr><td></td>";
for (var i=0,h; h = hours[i]; i++) {
tbl += "<td>" + colTotals[h] + "</td>";
}
tbl += "<td>" + colTotals['total'] + "</td></tr>";
tbl += "</tbody></table>";
document.getElementById('t').innerHTML = tbl;
<div id='t'></div>
My solution is I take out the min hour and the max hour as the column names, and retrieve the different names as the names of the rows, then loop the rows and columns and add data from the data object to the table, if there is no data, default is 0.
var jsonData = `{
"2017-05-06": {
"13": {
"Chris": "2", "Ian": "3"
},
"14": {
"Chris": "4", "Rob": "4"
},
"16": {
"Ian": "3", "Rob": 2
}
}
}`;
var objData, obj, arrName, arrHour, minHour, maxHour,
table, row, cell, caption;
objData = JSON.parse(jsonData);
obj = objData["2017-05-06"];
arrHour = Object.keys(obj);
minHour = Math.min(...arrHour);
maxHour = Math.max(...arrHour);
arrName = [];
for (let i in obj) {
for (let j in obj[i]) {
if (!arrName.includes(j)) {
arrName.push(j);
}
}
}
table = document.createElement("table");
table.cellPadding = 2;
table.style.fontFamily = "monospace";
table.style.textAlign = "center";
caption = table.createCaption();
caption.innerText = "2017-05-06";
caption.style.textAlign = "left";
row = table.insertRow();
row.insertCell();
for (let i = minHour; i <= maxHour; i++) {
cell = row.insertCell();
cell.innerText = i;
}
cell = row.insertCell();
cell.innerText = "Tt";
for (let i = 0; i < arrName.length; i++) {
let totalRow = 0;
row = table.insertRow();
cell = row.insertCell();
cell.style.textAlign = "left";
cell.innerText = arrName[i];
for (let j = minHour; j <= maxHour; j++) {
cell = row.insertCell();
if (obj[j] !== undefined) {
if (obj[j][arrName[i]] !== undefined) {
cell.innerText = obj[j][arrName[i]];
totalRow += +obj[j][arrName[i]];
}
else {
cell.innerText = 0;
}
}
else {
cell.innerText = 0;
}
}
cell = row.insertCell();
cell.innerText = totalRow;
}
row = table.insertRow();
row.innerText = "Total";
for (let i = 0; i <= maxHour - minHour + 1; i++) {
let totalCol = 0;
cell = row.insertCell();
for (let j = 0; j < arrName.length; j++) {
totalCol += +table.rows[j + 1].cells[i + 1].innerText;
}
cell.innerText = totalCol;
}
document.body.appendChild(table);
What I've done: So I am creating a game of chess in Java Script, and I have an 8 by 8 board (html table) with pieces on the board. I have currently set up some Click Handlers to recognize what board spot the user has clicked on (each td has its own id 0-63, and using this.cellIndex and .rowIndex I can get the coordinates).
Problem: My code so far is working but I'm currently trying to figure out how to save two separate user inputs (one selecting the coordinates of the where the piece currently is, and the second where the user wants the piece to go). My idea was to pass the variable cellContent as a parameter from "selectPiece()" to "movePiece()" so that I could have both variables in the same funciton but I can't seem to get it to work. Any suggestions or other ideas?
My Code:
function addClickHandlers() {
var cells = document.getElementsByTagName("td");
for (var i = 0; i< cells.length; i++) {
cells[i].onclick = function selectPiece() {
var coordinates = document.getElementById("coordinates");
var col = this.cellIndex
var row = this.parentNode.rowIndex;
var thisCell = this.id;
var cellContent = document.getElementById(thisCell).innerHTML;
document.getElementById(this.id).style.backgroundColor = "blue";
var cells = document.getElementsByTagName("td");
for (var i = 0; i< cells.length; i++) {
cells[i].onclick = function movePiece() {
var coordinates = document.getElementById("coordinates");
var col = this.cellIndex
console.log(this.cellIndex);
var row = this.parentNode.rowIndex;
console.log(this.id);
var thisCell = this.id;
var cellContent = document.getElementById(thisCell).innerHTML;
console.log(cellContent);
document.getElementById(this.id).style.backgroundColor = "red";
};
}
var postCoordinates = document.createTextNode("You clicked on coordinates: (" + row + "," + col + ").");
coordinates.appendChild(postCoordinates);
var br = document.createElement("br");
coordinates.appendChild(br);
};
}
}
Snippet
function showBoard() {
var tr;
var td;
var check;
var i = 0;
var j = 0;
var cellId = 0;
var table = document.getElementById("myTable");
for(i = 0; i < 8; i++) {
tr = table.insertRow(i);
for(j = 0; j < 8; j++) {
td = tr.insertCell(j);
if(i%2 == 1)
{
if(j%2 == 1)
{
td.setAttribute("class", "black");
}
else
{
td.setAttribute("class", "white");
}
}
else
{
if(j%2 == 1)
{
td.setAttribute("class", "white");
}
else
{
td.setAttribute("class", "black");
}
}
cellId = (i * 8) + j;
td.setAttribute("id", cellId);
var content = getSquare(i, j);
if (content == "br") {
var blackRook = document.createElement("IMG");
blackRook.setAttribute("src", "chess-piece-black-rook.png");
td.appendChild(blackRook);
}
else if (content == "bk") {
var blackKnight = document.createElement("IMG");
blackKnight.setAttribute("src", "chess-piece-black-knight.png");
td.appendChild(blackKnight);
}
else if (content == "bb") {
var blackBishop = document.createElement("IMG");
blackBishop.setAttribute("src", "chess-piece-black-bishop.png");
td.appendChild(blackBishop);
}
else if (content == "bK") {
var blackKing = document.createElement("IMG");
blackKing.setAttribute("src", "chess-piece-black-king.png");
td.appendChild(blackKing);
}
else if (content == "bQ") {
var blackQueen = document.createElement("IMG");
blackQueen.setAttribute("src", "chess-piece-black-queen.png");
td.appendChild(blackQueen);
}
else if (content == "bp") {
var blackPawn = document.createElement("IMG");
blackPawn.setAttribute("src", "chess-piece-black-pawn.png");
td.appendChild(blackPawn);
}
else if (content == "wr") {
var whiteRook = document.createElement("IMG");
whiteRook.setAttribute("src", "chess-piece-white-rook.png");
td.appendChild(whiteRook);
}
else if (content == "wk") {
var whiteKnight = document.createElement("IMG");
whiteKnight.setAttribute("src", "chess-piece-white-knight.png");
td.appendChild(whiteKnight);
}
else if (content == "wb") {
var whiteBishop = document.createElement("IMG");
whiteBishop.setAttribute("src", "chess-piece-white-bishop.png");
td.appendChild(whiteBishop);
}
else if (content == "wK") {
var whiteKing = document.createElement("IMG");
whiteKing.setAttribute("src", "chess-piece-white-king.png");
td.appendChild(whiteKing);
}
else if (content == "wQ") {
var whiteQueen = document.createElement("IMG");
whiteQueen.setAttribute("src", "chess-piece-white-queen.png");
whiteQueen.setAttribute("id", "botImg");
td.appendChild(whiteQueen);
}
else if (content == "wp") {
var whitePawn = document.createElement("IMG");
whitePawn.setAttribute("src", "chess-piece-white-pawn.png");
td.appendChild(whitePawn);
}
}
}
addClickHandlers();
}
function addClickHandlers() {
var cells = document.getElementsByTagName("td");
for (var i = 0; i< cells.length; i++) {
cells[i].onclick = function selectPiece() {
var coordinates = document.getElementById("coordinates");
var col = this.cellIndex
console.log(this.cellIndex);
var row = this.parentNode.rowIndex;
console.log(this.id);
var thisCell = this.id;
var cellContent = document.getElementById(thisCell).innerHTML;
console.log(cellContent);
document.getElementById(this.id).style.backgroundColor = "blue";
var cells = document.getElementsByTagName("td");
for (var i = 0; i< cells.length; i++) {
cells[i].onclick = function movePiece() {
var coordinates = document.getElementById("coordinates");
var col = this.cellIndex
console.log(this.cellIndex);
var row = this.parentNode.rowIndex;
console.log(this.id);
var thisCell = this.id;
var cellContent = document.getElementById(thisCell).innerHTML;
console.log(cellContent);
document.getElementById(this.id).style.backgroundColor = "red";
};
}
var postCoordinates = document.createTextNode("You clicked on coordinates: (" + row + "," + col + ").");
coordinates.appendChild(postCoordinates);
var br = document.createElement("br");
coordinates.appendChild(br);
};
}
}
//Game state variables
var grid = [[ "br", "bk", "bb", "bK", "bQ", "bb", "bk", "br" ],
[ "bp", "bp", "bp", "bp", "bp", "bp", "bp", "bp" ],
[ " ", " ", " ", " ", " ", " ", " ", " " ],
[ " ", " ", " ", " ", " ", " ", " ", " " ],
[ " ", " ", " ", " ", " ", " ", " ", " " ],
[ " ", " ", " ", " ", " ", " ", " ", " " ],
[ "wp", "wp", "wp", "wp", "wp", "wp", "wp", "wp" ],
[ "wr", "wk", "wb", "wK", "wQ", "wb", "wk", "wr" ]];
var turn = 7;
var capturedWhite = [];
var capturedBlack = ["bp"];
var gameOver = false;
//Game state functions
function getSquare(row, col) {
return grid[row][col];
}
function pawnMove(start, finish)
{
}
table {
background-color: black;
}
td.white {
height: 65px;
width: 65px;
background-color: white;
}
td.black {
height: 65px;
width: 65px;
background-color: black;
hover {
background-color: white;
}
}
img {
height: 45px;
width: 45px;
padding: 10px;
}
td:hover {
background-color: blue;
}
body {background: #cba;}
#botDiv {position: relative; bottom: 0; left: 0; height: 65;}
#botImg {position: relative; bottom: 0; left: 0;}
<!DOCTYPE html>
<html>
<head>
<title>Game Grid</title>
<link rel="stylesheet" href="gameGridStyle.css">
</head>
<body onload="showBoard();">
<div id="botDiv">
</div>
<script src = "genTable.js"></script>
<script src = "model.js"></script>
<script src = "queenBot.js"></script>
<script src = "loadGame.js"></script>
<table id="myTable">
</table>
<p id="coordinates">
</p>
<label>Here is your user data: </label>
<div id="username"></div><br>
<div id="timestamp"></div>
<button id="logoutButton" onclick="logout()">Log-out</button><br><hr>
<div id="loadDataDiv"></div>
<button id="loadGame" onclick="loadData()">Load Game</button><br><hr>
</body>
</html>
I have to populate a table using JSON and Javascript but the data go to next row. Whereas I wish to have data just below the row of column header
Here is my json:
var myList = [{ "Column1": "abc" },
{ "Column2": "25" },
{ "Column3": "xyz" }];
The given code fills the data in this sequence :
column1 column2 column3
abc
25
xyz
But I wish to have it like :
column1 column2 column3
abc 25 xyz
Here is my code:
var myList = [{ "Column1": "abc" },
{ "Column2": "25" },
{ "Column3": "xyz" }];
$(document).ready(function ()
{
buildHtmlTable();
});
function buildHtmlTable()
{
var columns = addAllColumnHeaders(myList); // columns get the name of coluns
alert("test : " + myList);
for (var i = 0 ; i < myList.length ; i++)
{
var row$ = $('<tr/>');
for (var colIndex = 0 ; colIndex < columns.length ; colIndex++)
{
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) { cellValue = ""; }
row$.append($('<td/>').html(cellValue));
}
$("#excelDataTable").append(row$);
}
}
Edit
function addAllColumnHeaders(myList)
{
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0 ; i < myList.length ; i++)
{
var rowHash = myList[i];
for (var key in rowHash)
{
if ($.inArray(key, columnSet) == -1)
{
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
}
}
}
$("#excelDataTable").append(headerTr$);
return columnSet;
}
and
<table id="excelDataTable" class="contentpanel" border="1"></table>
Take var row$ = $('<tr/>'); out of the loop. No need for double loop. Try this:
var myList = [{ "Column1": "abc" },
{ "Column2": "25" },
{ "Column3": "xyz" }];
$(document).ready(function ()
{
buildHtmlTable();
});
function buildHtmlTable()
{
var columns = addAllColumnHeaders(myList); // columns get the name of coluns
//alert("test : " + myList);
var row$ = $('<tr/>');
var colIndex = 0;
for (var i = 0 ; i < myList.length ; i++)
{
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) { cellValue = ""; }
row$.append($('<td/>').html(cellValue));
$("#excelDataTable").append(row$);
colIndex++;
}
}
function addAllColumnHeaders(myList)
{
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0 ; i < myList.length ; i++)
{
var rowHash = myList[i];
for (var key in rowHash)
{
if ($.inArray(key, columnSet) == -1)
{
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
}
}
}
$("#excelDataTable").append(headerTr$);
return columnSet;
}