How to create multidimentional array in html tables - javascript

I created tables in which each cells will change its class between clicked cells.
When I create this table, I would like to get clicked history array.
In the current state,history array is stored in clicked array.
clicked array is like
array=[1,4,6,9]
but My desired result is like
array=[[1,2,3,4],[6,7,8,9]]
or
array=[[1,4],[6,9]]
I mean in each class change,I would like to get parent keys for manipulation.
If you have some opinion, please let me know.
const $days = $("td");
const range = [-1, -1];
let clicked =[];
$(function() {
$("td").click(function() {
if (range[0] > -1 && range[1] > -1) { // RESET
range[0] = -1;
range[1] = -1;
}
if (range[0] > -1 && range[1] < 0) { // SET END
range[1] = $days.index(this);
$days.slice(range[0],range[1]+1).addClass('is-active');
}
if (range[0] < 0 && range[1] < 0) { // SET START
range[0] = $days.index(this);
}
let clickedID=$days.index(this);
clicked.push(clickedID);
console.log("Array of clicked cells",clicked);
});
});
td {
transition-duration: 0.5s;
border: solid black 1px;
cursor: pointer;
}
div {padding: 5px;}
table {border-collapse: collapse;}
.aqua{background-color: aqua;}
td:hover {
background-color:yellow;}
.is-active{
background-color:aqua;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id=calendar></div>
<script>
let html = ''
html += '<table>';
let i = 0;
for (let w = 0; w < 10; w++) {
html += '<tr>';
for (let d = 0; d < 10; d++) {
i = i + 1;
html += '<td>' + '<div>' + i + '</div>' + '</td>'
}
html += '</tr>';
}
html += '</table>'
document.querySelector('#calendar').innerHTML = html;
</script>

Will this help?
let sets = []
clicked.forEach((item,i) => {
if (i===0 || i%2===0) sets.push([])
sets[sets.length-1].push(item)
})
let html = ''
html += '<table>';
let i = 0;
for (let w = 0; w < 10; w++) {
html += '<tr>';
for (let d = 0; d < 10; d++) {
i = i + 1;
html += '<td data-layer=0>' + '<div>' + i + '</div>' + '</td>'
}
html += '</tr>';
}
html += '</table>'
document.querySelector('#calendar').innerHTML = html;
const $days = $("td");
const range = [-1, -1];
let clicked = [];
$(function() {
$("td").click(function() {
if (range[0] > -1 && range[1] > -1) { // RESET
range[0] = -1;
range[1] = -1;
}
if (range[0] > -1 && range[1] < 0) { // SET END
range[1] = $days.index(this);
$days.slice(range[0], range[1] + 1).addClass('is-active');
}
if (range[0] < 0 && range[1] < 0) { // SET START
range[0] = $days.index(this);
}
let clickedID = $days.index(this);
clicked.push(clickedID)
let sets = []
clicked.forEach((item,i) => {
if (i===0 || i%2===0) sets.push([])
sets[sets.length-1].push(item)
})
console.log("Array of clicked cells", sets);
// $(".is-active").each((i,td) => console.log(td.innerText))
});
});
td {
transition-duration: 0.5s;
border: solid black 1px;
cursor: pointer;
}
div {
padding: 5px;
}
table {
border-collapse: collapse;
}
.aqua {
background-color: aqua;
}
td:hover {
background-color: yellow;
}
.is-active {
background-color: aqua;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id=calendar></div>

Related

Forcing a click where i want

Run my snippet code before you read my question and click on some cells, so you can understand my question better!!
I got Player A = vertical and Player B = horizontal, As you can see, Each click gives turns between each player, moving the green background around some cells, how i can force the players only to be able to click the cells that have green behind them?
note: i tried using $(selector).trigger('click'); (JQuery)
var isCol = 0;
var CellPoint = 0;
var board = [];
var P1 = {
points: 0
};
var P2 = {
points: 0
};
for (r = 0; r < 7; r++) {
var line = [];
for (c = 0; c < 7; c++) {
line.push(RandomGenerator(50, 500));
}
board.push(line);
}
function prs(curr, c, r) {
CellPoint = parseInt($(curr).text());
showTable(curr, c, r);
isCol = (isCol + 1) % 2;
clr = isCol ? 'blue' : 'red';
$(curr).text('S');
$('#turn').css("color", clr)
.text(`Player ${(isCol+1)} turn`);
if (CellPoint) {
if (isCol) {
P1.points += CellPoint;
} else {
P2.points += CellPoint;
}
$('#p1').text(`Player 1: ${P1.points}`);
$('#p2').text(`Player 2: ${P2.points}`);
} else {
console.log('selected S');
}
}
function toColor(col, row, chosen_col, chosen_row) {
var ret = false;
switch (isCol) {
case 0:
if (row == chosen_row) {
ret = true;
}
break;
case 1:
if (col == chosen_col) {
ret = true;
}
break;
}
return ret;
}
function showTable(c, chosen_col, chosen_row) {
if(c!==-1){board[chosen_row][chosen_col] = 'S';}
var str = "";
str += "<table border=1>";
for (row = 0; row < 7; row++) {
str += "<tr>";
for (let col = 0; col < 7; col++) {
str += "<td onclick='prs(this, " + col + "," + row + ")'";
if(board[row][col]=='S'){
str += " class=uniqueCell";
} else{
if (toColor(col, row, chosen_col, chosen_row)) {
str += " class='grn' ";} }
str += ">";
if(board[row][col]=='S') {
str += 'S';
} else str += board[row][col];
str += "</td>";
}
str += "</tr>";
}
str += "</table>";
document.getElementById("ff").innerHTML = str;
}
function RandomGenerator(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
showTable(-1);
var getUnique = function() {
var tdElements = document.querySelectorAll('#ff td');
tdElements[
RandomGenerator(0, tdElements.length)
].classList.add('uniqueCell');
// update the text of the cell using the class
document.querySelector('.uniqueCell').textContent = 'S';
};
getUnique();
td {
border: 2px solid black;
width: 10px;
height: 10px;
text-align: center;
}
td:hover {
background-color: lightgreen;
}
.grn {
background-color: green;
color: white;
}
.turn1 {
background-color: green;
color: red;
}
.turn0 {
background-color: green;
color: blue;
}
.uniqueCell {
background-color: tomato;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div><span id='p1' style='color:red;'>Player1: </span> X <span style='color:blue;' id='p2'>Player2: </span></div>
<p id='turn'>Player 1 turn</p>
<div id="ff"></div>
I would suggest to use pointer-events. I have added JavaScript logic as well as modified CSS little bit.
in JavaScript I am checking for class .grn, if its available then allowing click everywhere. But if .grn is available then only td with .grn class will be clickable.
See below JavaScript logic.
if(document.querySelectorAll(".grn").length>0){
document.getElementById("tbl").classList.add("preventclick");
}else{
document.getElementById("tbl").classList.remove("preventclick");
}
See the Snippet below:
var isCol = 0;
var CellPoint = 0;
var board = [];
var P1 = {
points: 0
};
var P2 = {
points: 0
};
for (r = 0; r < 7; r++) {
var line = [];
for (c = 0; c < 7; c++) {
line.push(RandomGenerator(50, 500));
}
board.push(line);
}
function prs(curr, c, r) {
CellPoint = parseInt($(curr).text());
showTable(curr, c, r);
isCol = (isCol + 1) % 2;
clr = isCol ? 'blue' : 'red';
$(curr).text('S');
$('#turn').css("color", clr)
.text(`Player ${(isCol+1)} turn`);
if (CellPoint) {
if (isCol) {
P1.points += CellPoint;
} else {
P2.points += CellPoint;
}
$('#p1').text(`Player 1: ${P1.points}`);
$('#p2').text(`Player 2: ${P2.points}`);
} else {
console.log('selected S');
}
}
function toColor(col, row, chosen_col, chosen_row) {
var ret = false;
switch (isCol) {
case 0:
if (row == chosen_row) {
ret = true;
}
break;
case 1:
if (col == chosen_col) {
ret = true;
}
break;
}
return ret;
}
function showTable(c, chosen_col, chosen_row) {
if(c!==-1){board[chosen_row][chosen_col] = 'S';}
var str = "";
str += "<table id='tbl' border=1>";
for (row = 0; row < 7; row++) {
str += "<tr>";
for (let col = 0; col < 7; col++) {
str += "<td onclick='prs(this, " + col + "," + row + ")'";
if(board[row][col]=='S'){
str += " class=uniqueCell";
} else{
if (toColor(col, row, chosen_col, chosen_row)) {
str += " class='grn' ";
}
}
str += ">";
if(board[row][col]=='S') {
str += 'S';
} else str += board[row][col];
str += "</td>";
}
str += "</tr>";
}
str += "</table>";
document.getElementById("ff").innerHTML = str;
if(document.querySelectorAll(".grn").length>0 || document.querySelectorAll(".uniqueCell").length > 1){
document.getElementById("tbl").classList.add("preventclick");
}
}
function RandomGenerator(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
showTable(-1);
var getUnique = function() {
var tdElements = document.querySelectorAll('#ff td');
tdElements[
RandomGenerator(0, tdElements.length)
].classList.add('uniqueCell');
// update the text of the cell using the class
document.querySelector('.uniqueCell').textContent = 'S';
};
getUnique();
table#tbl.preventclick td{
pointer-events: none;
}
td {
border: 2px solid black;
width: 10px;
height: 10px;
text-align: center;
}
td:hover {
background-color: lightgreen;
}
.grn {
background-color: green;
color: white;
}
table#tbl.preventclick td.grn{
pointer-events: auto;
}
.turn1 {
background-color: green;
color: red;
}
.turn0 {
background-color: green;
color: blue;
}
.uniqueCell {
background-color: tomato;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div><span id='p1' style='color:red;'>Player1: </span> X <span style='color:blue;' id='p2'>Player2: </span></div>
<p id='turn'>Player 1 turn</p>
<div id="ff"></div>
Update:
I have added || document.querySelectorAll(".uniqueCell").length > 1 in if condition document.querySelectorAll(".grn").length>0 to fix issue mentioned in comment : there's little problem, try clicking on all the cells, in some cases, where there is no selectable numbers, i can click on anywhere on the S cells

Creating a Word Find grid

I am attempting to create a grid that contains one letter in each box (like a Word Find puzzle).
I have successfully created a grid that shows w/ the determined number of cols/rows, but when I attempt to put one letter in each box, I get the following ten times in each box instead of a single letter:
[object
Object]
Here is the JavaScript:
$(function() {
var letters = [
'rzeabppssgcddrvddydtjrkei', // 1
'cezcqubhniittonieqerbiuvm', // 2
'jqcjnasionsncvbsrwtabddsu', // 3
'olselesitneagittrjanreinv', // 4
'nqnaisdenmeibvurellsnrioc', // 5
'ydnlevrnyeaidrwifkufmsuis', // 6
'dcccjeeaogsemudbeemefaptn', // 7
'evonsqpdepislsnudnurwjbpo', // 8
'grytiunnafsexattmtclaimoi', // 9
'pnqrhocbiieeinoitacilppat', // 10
];
var letter = [];
function splitRows(arr, arr2) {
for (let i=0; i < arr.length; i++) {
arr[i].split();
for (let j=0; j < arr.length; j++) {
arr2[j] = arr[i][j];
}
}
}
splitRows(letters, letter);
function* gen(arr) {
for(i=0; i < arr.length; i++) {
yield arr[i];
}
}
function generateGrid(rows, cols, arr) {
var grid = "<table>";
for(row = 1; row <= rows; row++) {
grid += "<tr>";
for(col = 1; col <= cols; col++) {
grid += "<td>";
for(let i=0; i < arr.length; i++) {
grid += gen(arr).next(); // not sure if the .next() generator works yet
}
grid += "</td>"; // 'letters' needs to input the next letter in letters each time it is called
}
grid += "</tr>";
}
return grid;
}
$("#tableContainer").append(generateGrid(26, 22, letter));
});
The first function is intended to take rows and split them into singular letters (eventually taking rows as an input, but for testing purposes I have them in an array)
The second function is a generator to insert into the generateGrid() function that is used to generate the next letter in the sequence each time a box is created.
You should convert your string data to a matrix first then you can run the matrix through a table.
The following jQuery plugin clears the table and replaces it with rows and columns based on the data.
Note: I also added in tag name validation, in the case where the element the plugin was being invoked upon was not a <table> element.
var DEBUG_EXPERIMENTAL = false;
initializePlugins(); // Forward Declaration of jQuery plugins
let rawStringData = `
rzeabppssgcddrvddydtjrkei
cezcqubhniittonieqerbiuvm
jqcjnasionsncvbsrwtabddsu
olselesitneagittrjanreinv
nqnaisdenmeibvurellsnrioc
ydnlevrnyeaidrwifkufmsuis
dcccjeeaogsemudbeemefaptn
evonsqpdepislsnudnurwjbpo
grytiunnafsexattmtclaimoi
pnqrhocbiieeinoitacilppat
`;
$('.word-search').buildWordSearch(rawStringData, 'letter');
$('.letter').enableHighliting('highlight');
function initializePlugins() {
(($) => {
$.stringToMatrix = function(str) {
return str.trim().split('\n').map(row => row.trim().split(''));
};
$.fn.buildWordSearch = function(stringData, cellClass) {
this.throwErrorIfNotType('TABLE');
return this.append($('<tbody>')
.append($.stringToMatrix(stringData).map(row => {
return $('<tr>').append(row.map(col => {
return $('<td>').addClass(cellClass).text(col);
}));
})));
};
$.fn.throwErrorIfNotType = function(expectedTagName) {
let actualTagName = this.prop('tagName');
if (actualTagName !== expectedTagName) {
throw Error(`Element '${actualTagName}' is not a '${expectedTagName}'!`);
}
};
$.fn.getCell = function(x, y) {
return this.find(`tr:nth-child(${y + 1}) td:nth-child(${x + 1})`);
};
$.fn.enableHighliting = function(cls) {
return this.each(() => {
this.on({
mouseover: function() {
let $table = $(this).closest('table');
let $row = $(this).closest('tr');
let rowIndex = $row.index();
let colIndex = $(this).index();
let rowCount = $table.find('tbody tr').length;
let colCount = $row.find('td').length;
// Hightlights diagonals.
if (DEBUG_EXPERIMENTAL) {
let limit = rowCount;
let xNeg = colIndex - 1;
let xPos = colIndex + 1;
let yNeg = rowIndex - 1;
let yPos = rowIndex + 1;
while (limit > 0) {
if (xNeg > -1 && yNeg > -1) {
$table.getCell(xNeg, yNeg).addClass(cls);
}
if (xPos < colCount && yNeg > -1) {
$table.getCell(xPos, yNeg).addClass(cls);
}
if (xNeg > -1 && yPos < rowCount) {
$table.getCell(xNeg, yPos).addClass(cls);
}
if (xPos < colCount && yPos < rowCount) {
$table.getCell(xPos, yPos).addClass(cls);
}
xNeg--;
xPos++;
yNeg--;
yPos++;
limit--;
}
}
$row.addClass(cls);
$table.find(`td:nth-child(${colIndex + 1})`).addClass(cls);
},
mouseout: function() {
let $table = $(this).closest('table');
let $row = $(this).closest('tr');
let rowIndex = $row.index();
let colIndex = $(this).index();
let rowCount = $table.find('tbody tr').length;
let colCount = $row.find('td').length;
// Un-hightlights diagonals.
if (DEBUG_EXPERIMENTAL) {
let limit = rowCount;
let xNeg = colIndex - 1;
let xPos = colIndex + 1;
let yNeg = rowIndex - 1;
let yPos = rowIndex + 1;
while (limit > 0) {
if (xNeg > -1 && yNeg > -1) {
$table.getCell(xNeg, yNeg).removeClass(cls);
}
if (xPos < colCount && yNeg > -1) {
$table.getCell(xPos, yNeg).removeClass(cls);
}
if (xNeg > -1 && yPos < rowCount) {
$table.getCell(xNeg, yPos).removeClass(cls);
}
if (xPos < colCount && yPos < rowCount) {
$table.getCell(xPos, yPos).removeClass(cls);
}
xNeg--;
xPos++;
yNeg--;
yPos++;
limit--;
}
}
$row.removeClass(cls);
$table.find(`td:nth-child(${colIndex + 1})`).removeClass(cls);
}
});
});
};
})(jQuery);
}
.word-search {
border: 2px solid #000;
border-collapse: collapse;
}
.word-search td {
width: 1.25em;
height: 1.25em;
line-height: 1.25em;
text-align: center;
}
.highlight {
background: #FFD;
}
.letter.highlight:hover {
background: #FF0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="word-search"></table>

Add multiple colspans that line up in HTML

I'm building a calendar scheduler where I am hoping to add multiple tasks to one employee row. Whenever I try to add multiple tasks to the same time span, the spans no longer line up. Here is an example of how it looks now: . What would be the best practice to add tasks to the same day columns while keeping a task like "Slaughter them" similar?
HTML Script:
<script>
var sysDate = new Date();
var sysDay = new Date();
var sysMonth = new Date();
var dayCount = sysDay.getDay();
var weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
let employee;
let typeofKey;
let empArry = [];
let x = 1;
let y = 0;
let trInc= 0;
var drawTable = '<table id = wholeTable>';
drawTable += "<thead>";
drawTable += "<tr>";
drawTable += "<th style='color:white;'>Employee Name<\/th>";
let today = new Date();
let dd = today.getDate();
let mm = today.getMonth()+1; //January is 0!
let mmN = mm;
let yyyy = today.getFullYear();
let oneWeekAhead = new Date();
let nextWeek = (today.getDate()+10) + 10;
/* If next week falls into the next month, print correctly */
if (nextWeek > 30 && (mmN == 9 || mmN == 4 || mmN == 6 || mmN == 11)) {
mmN++;
nextWeek -= 30;
}
else if (nextWeek > 31 && (mmN == 1 || mmN == 3 || mmN == 5 || mmN == 7 || mmN == 8 || mmN == 10 || mmN == 12)) {
mmN++;
nextWeek -= 31;
}
else if (nextWeek > 28 && mmN == 2) {
mmN++;
nextWeek -= 28;
}
/* Formatting of the dates at the top of the table */
if(dd < 10) {
dd = '0'+ dd;
}
if(nextWeek < 10) {
nextWeek = '0' + nextWeek;
}
if(mmN < 10) {
mmN = '0' + mmN
}
if(mm < 10) {
mm = '0' + mm;
}
let edate = yyyy + mmN + nextWeek;
/* Finds the logged earliest and latest dates */
let startDate1 = yyyy.toString() + mm.toString() + dd.toString();
let startDate = parseInt(startDate1);
let endDate = parseInt(edate);
let startDateN = 20180501;
let endDateN = 20180531;
/* Change the strings of dates to ints for calculation of start and end date of the table */
if( localStorage.length > 0){
for (var key in localStorage) {
typeofKey = (typeof localStorage[key]);
if (typeofKey == 'string' || typeofKey instanceof String ){
emp1 = JSON.parse(localStorage.getItem(key));
if ("Task" in emp1) {
for (let i = 0; i < emp1.Task.length; i++) {
startDateN = parseInt(emp1.Task[i]['Task Start Date'].substr(0,4) + emp1.Task[i]['Task Start Date'].substr(5,2) + emp1.Task[i]['Task Start Date'].substr(8,2));
endDateN = parseInt(emp1.Task[i]['Task End Date'].substr(0,4) + emp1.Task[i]['Task End Date'].substr(5,2) + emp1.Task[i]['Task End Date'].substr(8,2));
if(endDateN > endDate) {
endDate = endDateN;
}
if(startDateN < startDate) {
startDate = startDateN;
}
}
}
}
}
}
let numStr = null;
let numStrDay = null;
let finalDay = null;
let finalDayF = null;
let colCount = 0;
/* Correctly print the months and days at the top of the table */
for (let i = startDate; i <= endDate +1; i++) {
numStr = (i.toString()).substr(4,2);
numStrDay = (i.toString()).substr(6,2);
if(numStr == '09' || numStr == '04' || numStr == '06' || numStr == '11') {
if(numStrDay == '31') {
i += 69;
}
else {
finalDay = i.toString()
finalDayF = (finalDay.substr(0,4)) + "-" + (finalDay.substr(4,2)) + "-" + (finalDay.substr(6,2));
drawTable += "<th class = days id = days" + x + '-' + y + ">" + finalDayF + "</th>";
colCount++;
}
}
else if(numStr == '01' || numStr == '03' || numStr == '05' || numStr == '07' || numStr == '08' || numStr == '10' || numStr == '12') {
if(numStrDay == '32') {
i += 68;
}
else {
finalDay = i.toString()
finalDayF = (finalDay.substr(0,4)) + "-" + (finalDay.substr(4,2)) + "-" + (finalDay.substr(6,2));
drawTable += "<th class = days id = days" + x + '-' + y + ">" + finalDayF + "</th>";
colCount++;
}
}
else if(numStr == '02') {
if(numStrDay == '29') {
i += 71;
}
else {
finalDay = i.toString()
finalDayF = (finalDay.substr(0,4)) + "-" + (finalDay.substr(4,2)) + "-" + (finalDay.substr(6,2));
drawTable += "<th class = days id = days" + x + '-' + y + ">" + finalDayF + "</th>";
colCount++;
}
}
else {
finalDay = i.toString()
finalDayF = (finalDay.substr(0,4)) + "-" + (finalDay.substr(4,2)) + "-" + (finalDay.substr(6,2));
drawTable += "<th class = days id = days" + x + '-' + y + ">" + finalDayF + "</th>";
colCount++;
}
x++;
}
drawTable += "</tr>";
drawTable += "</thead>";
drawTable += '<tbody class="dragscroll">';
//drawTable += "<tr id =" + trInc + ">";
//trInc++;
//counters for the employee and date rows/col
x=0;
y=1;
// counter for the main table
let z =1;
for (var key in localStorage) {
typeofKey = (typeof localStorage[key]);
//cols of the employee names
if(typeofKey == 'string' || typeofKey instanceof String ){
drawTable += "<tr id =" + trInc + ">";
trInc++;
employee = JSON.parse(localStorage.getItem(key));
drawTable += "<td class = employ id =emp" + x + '-' + y + ">" + employee['Employee Name'] + "</td>";
// rows and cols of the main table and date
for (let j = 0; j < colCount; j++) {
drawTable += "<td class =" + z + '-' + y + "></td>";
z++;
}
// set z to one to start the main tables x at 1 for off by one error
z=1;
//reset x for each row
x=0;
drawTable += '</tr>';
y++;
}
}
drawTable += '<tr>';
var noRows = 14 - localStorage.length;
for(; noRows >= 0; noRows--){
drawTable += "<td class = employ id =emp" + x + '-' + y + ">" + "" + "</td>";
// rows and cols of the main table and date
for (let j = 0; j < colCount; j++) {
drawTable += "<td class =" + z + '-' + y + "></td>";
z++;
}
// set z to one to start the main tables x at 1 for off by one error
z=1;
//reset x for each row
x=0;
drawTable += '</tr>';
y++;
}
drawTable += "</tbody>";
drawTable += "</table>";
document.write(drawTable);
</script>
CSS:
table {
/* border: 0.0625em solid black; */
table-layout: fixed;
position: relative;
width: auto;
overflow: hidden;
border-collapse: collapse;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
}
html, body{
height: 100%;
width: 100%;
background: linear-gradient(45deg, #e1e1e1, #f6f6f6);
}
/*thead*/
thead {
position: relative;
display: block; /*seperates the header from the body allowing it to be positioned*/
width: 1535px;
overflow: visible;
/* border: 1px solid black; */
}
td, th {
padding: 0.75em 1.5em;
text-align: left;
}
thead th {
min-width: 140px;
max-width: 140px;
height: 35px;
text-align: center;
}
thead th:nth-child(1) { /*first cell in the header*/
position: relative;
display: float;
min-width: 140px;
background-color: #202020;
}
/*tbody*/
tbody {
position: relative;
display: block; /*seperates the tbody from the header*/
width: 1535px;
height: 475px;
overflow: scroll;
}
tbody td {
background-color: white;
min-width: 140px;
max-width: 140px;
border: 2px solid #474747;
white-space: nowrap;
}
tbody tr td:nth-child(1) { /*the first cell in each tr*/
position: relative;
/*display: block; seperates the first column from the tbody*/
height: 40px;
min-width: 140px;
max-width: 140px;
}
.dragscroll {
overflow-y: hidden;
margin-right: 0;
height: 600px;
}
.days {
background-color: #31bc86;
color: white;
text-align: center;
}
.employ {
background-color: #2ea879;
color: white;
text-align: center;
}
#taskDiv {
position: absolute;
border: 2px solid black;
}
#days, #emp{
background-color: #071833;
color: white;
}
::-webkit-scrollbar {
width: 20px;
}
/* Track */
::-webkit-scrollbar-track {
box-shadow: inset 0 0 5px black;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #071833;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #1caf8f
}
JS:
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
$(document).ready(function(){
let typeofKey;
let empArry = [];
let employee;
let myTable = document.getElementById('wholeTable');
let colFill = false;
let color = null;
//cols of the employee names
for (var i = 0; i < localStorage.length; i++){
empArry.push(localStorage.key(i))
}
// loop through the local storage and pull the data
for(let j = 0; j < empArry.length; j++){
color = getRandomColor();
employee = JSON.parse(localStorage.getItem(empArry[j]));
// If employee has any task
if("Task" in employee){
// while employee has task in his array
for(let taskIndex = 0; taskIndex < employee.Task.length; taskIndex++){
for(let k = 1; k < myTable.rows[0].cells.length; k++) {
if(myTable.rows[0].cells[k].innerHTML == employee.Task[taskIndex]["Task Start Date"]) {
colFill = true;
}
if(colFill == true) {
myTable.rows[j+1].cells[k].innerHTML += '<div style="background-color:' + color + '">' + employee.Task[taskIndex]["Task Name"] + '</br></div>';
}
if(myTable.rows[0].cells[k].innerHTML == employee.Task[taskIndex]["Task End Date"]) {
colFill = false;
}
}
}
}
}
});
JSFiddle: https://jsfiddle.net/py5gzw0b/1/#&togetherjs=eM8xgAd5eV
Set the vertical-align CSS property for those table cells to top;
td {
vertical-align:top;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align
If you need each item to be on its own row [along with all identical tasks] and perfectly aligned there, then you would need to create row 1, and insert only the Slaughter tasks, followed by creating row 2, inserting only the Cry tasks. This would then ensure that they would all correctly line up with one another, although it would take up more space as a result.
Another solution besides creating a row for each task would be to use jQuery to find the "max top of the task" and setting all instances at that top. Since they take the same space it should be doable and more flexible BUT you're in for some css-positioning fun.
To be more specific, you should :
1/ Add an unique identifier to each task : <div id_task="1" style=...
2/ Loop on each instance to find max top value :
maxTop=0;
$('[id_task=1]').each(function(){
newTop=$(this).position().top;
if(newTop>maxTop)maxTop=newTop;
});
3/ Use maxTop to set all id_task=1 to the same top, probably set these divs to relative too : $('[id_task=1]').css({'top':maxTop,'position':'relative');
4/ Enjoy fine-tuning this to close in on your desired goal, it'll take a while ^^
I made the code quickly as an example, there's no guarantee to it.
Take a look at this:
var cols = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
var employees = [
{
Name: 'Jason',
Task:[
{'Task Start Date':'Mon','Task End Date':'Thu','Task Name':'Do nothing'},
{'Task Start Date':'Thu','Task End Date':'Fri','Task Name':'Do a bit'},
{'Task Start Date':'Sat','Task End Date':'Sun','Task Name':'Do everything'}
]
},
{
Name: 'Timmy',
Task:[
{'Task Start Date':'Mon','Task End Date':'Sun','Task Name':'On vacation'},
{'Task Start Date':'Sat','Task End Date':'Sun','Task Name':'Still on vacation'},
]
}
]
function RowCompound(employee,columns){
var tasks = employee.Task
var spans = []
var max_rows = 1
var rowmap = []
var rows = []
function calcSpans(){
for(var i=0;i<tasks.length;i++){
var cspan = null
for(var u=0;u<columns.length;u++){
if(tasks[i]['Task Start Date']==columns[u]){
cspan = {row:0,start:u,task:tasks[i]}
}
if(cspan && tasks[i]['Task End Date']==columns[u]){
cspan.end = u
spans.push(cspan)
cspan = null
}
}
if(cspan){
cspan.end = columns.length-1
spans.push(cspan)
}
}
}
function solveConflicts(){
var conflict = true
while(conflict){
conflict = false
for(var i=0;i<spans.length;i++){
for(var u=i+1;u<spans.length;u++){
if(spans[i].row!=spans[u].row) continue
if(spans[i].start>spans[u].end || spans[i].end<spans[u].start) continue
conflict = true
max_rows = Math.max(max_rows,++spans[u].row + 1)
}
}
}
}
function createRowMap(){
for(var u=0;u<max_rows;u++){
var row = []
for(var i=0;i<columns.length;i++){
var empty = true
for(var k=0;k<spans.length;k++){
if(spans[k].row!=u) continue
if(i==spans[k].start){
empty = false
var span = spans[k].end-spans[k].start+1
row.push({task:spans[k].task,colspan:span,rowspan:1})
i += span-1
break
}
}
if(empty)
row.push({task:null,colspan:1,rowspan:1})
}
rowmap.push(row)
}
}
function buildDom(){
for(var i=0;i<rowmap.length;i++){
var row = document.createElement('tr')
for(var u=0;u<rowmap[i].length;u++){
if(rowmap[i][u].rowspan==0) continue
var cell = document.createElement('td')
cell.colSpan = rowmap[i][u].colspan
cell.rowSpan = rowmap[i][u].rowspan
if(rowmap[i][u].task){
cell.innerHTML = rowmap[i][u].task['Task Name']
cell.className = 'busy'
}
row.appendChild(cell)
}
rows.push(row)
}
var head = document.createElement('td')
head.rowSpan = max_rows
head.innerHTML = employee.Name
rows[0].prepend(head)
}
calcSpans()
solveConflicts()
createRowMap()
buildDom()
return rows
}
// example use
employees.forEach(function (emp){
var result_rows = RowCompound(emp,cols)
for(var i in result_rows){
document.getElementById('table').appendChild(result_rows[i])
}
})
table{
width: 100%;
border-collapse: collapse;
}
table td{
border: solid 1px #ccc;
width: 50px;
}
table td.busy{
background-color: dodgerblue;
color: white;
}
<table id="table">
<thead>
<th>Employee</th>
<th>Mon</th>
<th>Tue</th>
<th>Wed</th>
<th>Thu</th>
<th>Fri</th>
<th>Sat</th>
<th>Sun</th>
</thead>
</table>
What this does is:
Create virtual spans for each task
If the spans overlap, push them one row lower
Create multiple rows utilizing the rowSpan attribute
Append the said rows to the table
You're gonna need to rewrite your code a little for this to work, but i think its the way to go.
Please note, the createRowCompound function requires the columns of the table as array in order to create the layout. See the example use.
Questions?
This is more of a conceptual answer/idea, but I think that you might be able to use the Isotope javascript layout library with the "vertical" layout mode:
https://isotope.metafizzy.co/layout-modes.html
You can disable all kinds of animations, so in that sense, this would be a shortcut to the "css positioning fun" that #Nomis mentions in the answer above. There's also the https://masonry.desandro.com library by the same person - might be worth a look.

Merge two HTML tables using Javascript Objects as data feed?

I am going to have multiple arrays of arrays and I want to make objects from the array and then merge it into one table. I already did that, however I need help using the object to make one larger table?
If a key exists in one object but not the others the value can just be blank for the object the key doesnt exist. I am able to make multiple different tables but how can I merge them to make the table one larger one?
var data =[["default_PROJECT","Allow","Connect","Allow","AddComment","Allow","Write",
"Allow","ViewComments","Allow","ExportData","Allow","ExportImage","Allow","ViewUnderlyingData","Allow","Read","Allow","ShareView","Allow","Filter"],
["Allow","ExportImage","Allow","Write","Allow","ViewComments",
"Allow","ShareView","Allow","Filter","Allow","ExportData","Allow","Connect","Allow",
"Read","Allow","ViewUnderlyingData","Allow","AddComment","Allow","ViewComments","Deny","ExportData","Allow",
"AddComment","Deny","Write","Allow","Read","Deny","ExportXml","Deny","ShareView","Allow","Connect","Allow","ChangeHierarchy","Allow",
"WebAuthoring","Deny","ViewUnderlyingData","Deny","Filter","Deny","ExportImage"]];
var result = [];
for(var i = 0, len = data.length; i < len; i++) {
var list = data[i];
result[i] = { name: list[0] };
for (var j = list.length - 1; j >= 1; j = j - 2) {
var key = list[j];
var value = list[j - 1];
if( result[i][key] !== "Deny" ) {
result[i][key] = value;
}
}
}
console.log(result);
var resultElement = document.getElementById('result1');
var tpl = '';
for(var t = 0, tLen = result.length; t < tLen; t++) {
var item = result[t];
tpl+= '<table align=center style="width:25%;">' +
'<thead>' +
'<tr><td colspan="2">Project: ' + item.name + '</td></tr>' +
'<tr><th>Permission</th><th>Value</th></tr>' +
'</thead>' +
'<tbody>'
;
for(var key in item) {
if(!item.hasOwnProperty(key) || key === 'name') { continue; }
if(item[key] == "Allow"){
tpl += '<tr style="background-color:greenyellow;"><td>'+ key +'</td><td>'+ item[key] +'</td></tr>';
}
else{
tpl += '<tr style="background-color:red;"><td>'+ key +'</td><td>'+ item[key] +'</td></tr>';
}
}
}
resultElement.innerHTML = tpl;
table { text-align: left; width: 100%; margin-bottom: 50px; border-collapse: collapse;}
td, th { width: 50%; border: 1px solid black; line-height: 1; padding:2px 10px;}
[colspan="2"] { color: blue; font-weight: bolder;text-transform: uppercase; text-align: center;}
<div id="result1"></div>
http://jsfiddle.net/h2s17hac/
This merges the two tables.
Fiddle
var data =[["default_PROJECT","Allow","Connect","Allow","AddComment","Allow","Write",
"Allow","ViewComments","Allow","ExportData","Allow","ExportImage","Allow","ViewUnderlyingData","Allow","Read","Allow","ShareView","Allow","Filter"],
["test_PROJECT", "Allow","ExportImage","Allow","Write","Allow","ViewComments",
"Allow","ShareView","Allow","Filter","Allow","ExportData","Allow","Connect","Allow",
"Read","Allow","ViewUnderlyingData","Allow","AddComment","Allow","ViewComments","Deny","ExportData","Allow",
"AddComment","Deny","Write","Allow","Read","Deny","ExportXml","Deny","ShareView","Allow","Connect","Allow","ChangeHierarchy","Allow",
"WebAuthoring","Deny","ViewUnderlyingData","Deny","Filter","Deny","ExportImage"]];
function makeObjects(data){
result = [];
for(var i = 0, len = data.length; i < len; i++) {
var list = data[i];
result[i] = { Name: list[0] };
for (var j = list.length - 1; j >= 1; j = j - 2) {
var key = list[j];
var value = list[j - 1];
if( result[i][key] !== "Deny" ) {
result[i][key] = value;
}
}
}
return result;
}
function sortObject(obj) {
return Object.keys(obj).sort().reduce(function (result, key) {
result[key] = obj[key];
return result;
}, {});
}
function getKeys(data){
var keys = [];
for(i=0; i<data.length; i++){
key = Object.keys(data[i]);
for(j =0; j<key.length; j++){
if(keys.indexOf(key[j]) == -1){
keys.push(key[j]);
}
}
}
return keys;
}
function addMissingKeys(keys, data){
var filtData = [];
for(i=0; i<data.length; i++){
for(j=0; j<keys.length; j++){
if(data[i][keys[j]] == undefined){
data[i][keys[j]] = "";
}
}
}
for(num=0; num<data.length; num++){
filtData.push(sortObject(data[num]));
}
return filtData;
}
var dataa = makeObjects(data);
var keys = getKeys(dataa);
var filtData = addMissingKeys(keys, dataa);
console.log(filtData);
var resultElement = document.getElementById('result1');
var tpl = '<table align=center style="width:75%;">';
for(var t = 0, tLen = filtData.length; t < tLen; t++) {
var item = filtData[t];
tpl+= '<tr><td>' + item.Name + '</td>';
for(var key in item) {
if(!item.hasOwnProperty(key) || key === 'Name') { continue; }
if(item[key] != "") {
if(item[key] == "Allow"){
tpl += '<td style="background-color:greenyellow;">'+ key +':<br>'+ item[key] +'</td>';
}
else{
tpl += '<td style="background-color:red;">'+ key +':<br>'+ item[key] +'</td>';
}
} else {
tpl += '<td></td>';
}
}
tpl += '</tr>';
}
tpl += '</table>';
resultElement.innerHTML = tpl;
table { text-align: left; width: 100%; margin-bottom: 50px; border-collapse: collapse;}
td, th { width: 50%; border: 1px solid black; line-height: 1; padding:2px 10px;}
[colspan="2"] { color: blue; font-weight: bolder;text-transform: uppercase; text-align: center;}
<div id="result1"></div>
<div id="test"></div>

Cascading Multi select pick lists CRM 2011

I Have multi select pick list which work fine however it now contains around 70 options to select from with around 12 categories - I have searched around the internet to find a solution that could make the list a little more user friendly.
It would be perfect if I was able to have the pick list with the 12 categories and on select of them they cascade in to their sub options. However the tricky part is this has to be done from within the same field.
Has anyone had a similar request or know of anyway to make this possible?
Thank You
here is the code for the multi select pick list I have currently:
<html xmlns="http://www.w3.org/1999/xhtml"><head><title></title>
<script src="sc_json2.js" type="text/javascript"></script>
<meta charset="utf-8"></head>
<body style="margin: 0px; border: 0px currentColor; font-family: Segoe UI; font-size: 11px; background-color: rgb(246, 248, 250);" onload="onload()">
<div id="MultiSelectField"></div>
<script type="text/javascript">
var FORM_TYPE_CREATE = 1;
var FORM_TYPE_UPDATE = 2;
var FORM_TYPE_READ_ONLY = 3;
var FORM_TYPE_DISABLED = 4;
var FORM_TYPE_QUICK_CREATE = 5;
var FORM_TYPE_BULK_EDIT = 6;
var var_sc_optionset;
var var_sc_optionsetvalue;
var options;
var checkedValues;
var isDirty = false;
var html = "";
function onload() {
var formType = parent.Xrm.Page.ui.getFormType();
if (formType == FORM_TYPE_BULK_EDIT) {
displayMessage();
}
else {
init();
}
}
function init() {
getParameters();
getOptionSetValues();
getCheckedValues();
convertToMultiSelect();
}
function displayMessage() {
MultiSelectField.innerHTML = "This field cannot be displayed or edited in this form mode.";
}
function getParameters() {
var querystring = unescape(window.location.search.replace('?', '').replace('data=', ''));
var params = querystring.split(',');
for (var i = 0; i < params.length; i++) {
if (i == 0) {
var_sc_optionset = params[i];
}
else if (i == 1) {
var_sc_optionsetvalue = params[i];
}
}
}
//populate option-set values and integers
function getOptionSetValues() {
options = parent.Xrm.Page.getAttribute(var_sc_optionset).getOptions();
}
function getCheckedValues() {
var dirtyCheckedOptions = parent.Xrm.Page.getAttribute(var_sc_optionsetvalue).getValue();
if (dirtyCheckedOptions != null) {
checkedValues = dirtyCheckedOptions.split(';');
}
else {
checkedValues = '';
}
}
//Method to convert an optionset to multi select Option Set
function convertToMultiSelect() {
for (var i = 0; i < options.length - 1; i++) {
var pOption = options[i];
if (!isChecked(pOption.text))
html += "<input type='checkbox' class='multiselect_cb' onclick='makeDirty()' style='border:none; width:25px; align:left;' title='" + pOption.text + "'/>";
else
html += "<input type='checkbox' class='multiselect_cb' checked='checked' onclick='makeDirty()' style='border:none; width:25px; align:left;' title='" + pOption.text + "'/>";
html += "<label>" + pOption.text + "</label>";
if (i != options.length - 2) {
html += "<br/>"; //it's a 'br' flag
}
}
MultiSelectField.innerHTML = html;
}
function makeDirty() {
isDirty = true;
}
function isChecked(ptext) {
for (var i = 0; i < checkedValues.length; i++) {
if (checkedValues[i] == ptext)
return true;
}
return false;
}
function saveMultiSelect() {
if (isDirty) {
var divElement = document.getElementById("MultiSelectField");
var result = '';
for (var i = 0; i < divElement.childNodes.length; i++) {
if (divElement.childNodes[i].type == "checkbox" && divElement.childNodes[i].checked) {
result += divElement.childNodes[i].title + ";";
}
}
//clear out the previous results from the field
parent.Xrm.Page.getAttribute(var_sc_optionsetvalue).setValue("");
//populate var_sc_optionsetvalue with the checked values
parent.Xrm.Page.getAttribute(var_sc_optionsetvalue).setValue(result);
isDirty = false;
}
}
</script>
</body></html>

Categories

Resources