Modal Box/ Pop up is not coming - javascript

This is my code I am selecting two columns , and then I am taking the difference of correspoding cells and creating new column, and displaying it in a single table. I want to display it as a pop-up(modal box). Like on selecting two input checkboxes the resultant table should come as a form of popup and after closing it, i can again select any checkboxes and again a table should be formed and display as popup
But when I am doing this way its is not coming as a pop and the same table is getting appended. Can anyone please help with this one?
function hidemodal() {
$("#myModal").hide();
}
const table = document.getElementById("main-table"),
checkboxes = table.querySelectorAll('.header > input[type="checkbox"]');
let columns = {};
for (let i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener("input", onInput);
}
function onInput(e) {
const input = e.target,
column = input.parentNode.cellIndex,
tds = table.querySelectorAll('td:nth-child(' + (column + 1) + ')');
if (input.checked) {
let list = [];
for (let i = 0; i < tds.length; i++) {
list[list.length] = tds[i].textContent;
}
columns[column] = list;
}
else {
delete columns[column];
}
if (Object.keys(columns).length > 1)
showDifference();
else
table.classList.remove("result");
}
function showDifference() {
var array1 = [];
var array2 = [];
var a = Object.keys(columns)[0], b = Object.keys(columns)[1]
const result = columns[a].map((el, i) => {
first = columns[a][i];
array1.push(first)
second = columns[b][i];
array2.push(second)
const regex = /\d+/;
const firstNumber = parseInt(first.match(regex));
const secondNumber = parseInt(second.match(regex));
const diff = Math.abs(firstNumber - secondNumber);
return `$${diff}`;
})
buildTable();
// var tablediff;
var modalBody = $('<div id="modalContent"></div>');
function buildTable() {
var table = document.createElement("TABLE");
table.setAttribute("id", "myTable");
document.body.appendChild(table);
for (let i = 0; i < 3; i++) {
var y = document.createElement("TR");
y.setAttribute("id", "myTr" + i)
document.getElementById("myTable").appendChild(y);
var z = document.createElement("TD");
var t = document.createTextNode(array1[i]);
var z1 = document.createElement("TD");
var s = document.createTextNode(array2[i]);
var z2 = document.createElement("TD");
var r = document.createTextNode(result[i]);
z.appendChild(t);
z1.appendChild(s);
z2.appendChild(r);
document.getElementById("myTr" + i).appendChild(z);
document.getElementById("myTr" + i).appendChild(z1)
document.getElementById("myTr" + i).appendChild(z2)
}
}
modalBody.append(table);
$(".modal-body").html(modalBody);
}
table {
border: 1px solid white;
text-align: center;
padding: 6px;
background: #e1edf9;
}
td {
border: 1px solid white;
text-align: center;
padding: 6px;
}
td:first-child,
tr:first-child {
background-color: #003a6a !important;
color: white !important;
}
.table-scroll {
position: relative;
width: 100%;
z-index: 1;
margin: auto;
overflow: auto;
}
.table-scroll table {
width: 100%;
min-width: 1280px;
margin: auto;
border-collapse: separate;
border-spacing: 0;
}
.table-wrap {
position: relative;
}
.table-scroll tr:first-child {
background: #333;
color: #fff;
position: -webkit-sticky;
position: sticky;
top: 0;
}
td:first-child {
position: -webkit-sticky;
position: sticky;
left: 0;
z-index: 2;
background: #ccc;
}
.table-scroll tfoot tr {
position: -webkit-sticky;
position: sticky;
bottom: 0;
background: #666;
color: #fff;
z-index: 4;
}
tr:first-child {
z-index: 5;
}
#media screen and (max-width: 500px) {
td:first-child {
position: -webkit-sticky;
position: sticky;
left: 0;
z-index: 2;
background: #ccc;
max-width: 140px;
}
}
.main-table:not(.result) th.result,
.main-table:not(.result) td.result {
display: none;
}
<div id="table-scroll" class="table-scroll">
<table class="data" id="main-table">
<tbody>
<tr>
<th class="header">Three</th>
<th class="header">Four<input type="checkbox" value="on" name="cb4" /></th>
<th class="header">Five<input type="checkbox" value="on" name="cb5" /></th>
<th class="header">Five<input type="checkbox" value="on" name="cb5" /></th>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>12</td>
<td>22</td>
<td>32</td>
<td>34</td>
</tr>
<tr>
<td>21</td>
<td>22</td>
<td>23</td>
<td>7</td>
</tr>
</tbody>
</table>
</div>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" onclick="hidemodal ()">×</button>
</div>
<div class="modal-body"></div>
</div>
</div>
</div>

You are using the same table variable for #main-table and for the results table. However the results table variable is only available inside buildTable(), and when you use modalBody.append(table); outside of that function, you are moving the #main-table instead. So for your own sake, try avoid recycle variable names.
Also, you don't have to use getElementById for the element you just created via createElement()
function hidemodal() {
document.body.classList.remove("popup");
}
function showmodal() {
document.body.classList.add("popup");
}
const table = document.getElementById("main-table"),
checkboxes = table.querySelectorAll('.header > input[type="checkbox"]');
let columns = {};
for (let i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener("input", onInput);
}
function onInput(e) {
const input = e.target,
column = input.parentNode.cellIndex,
tds = table.querySelectorAll('td:nth-child(' + (column + 1) + ')');
if (input.checked) {
let list = [];
for (let i = 0; i < tds.length; i++) {
list[list.length] = tds[i].textContent;
}
columns[column] = list;
} else {
delete columns[column];
}
if (Object.keys(columns).length > 1)
showDifference();
else
table.classList.remove("result");
}
function showDifference() {
var array1 = [];
var array2 = [];
var a = Object.keys(columns)[0],
b = Object.keys(columns)[1]
const result = columns[a].map((el, i) => {
first = columns[a][i];
array1.push(first)
second = columns[b][i];
array2.push(second)
const regex = /\d+/;
const firstNumber = parseInt(first.match(regex));
const secondNumber = parseInt(second.match(regex));
const diff = Math.abs(firstNumber - secondNumber);
return `$${diff}`;
})
// var tablediff;
var modalBody = $('<div id="modalContent"></div>');
buildTable();
function buildTable() {
var modalTable = document.createElement("TABLE");
modalTable.setAttribute("id", "myTable");
modalBody.html(modalTable);
for (let i = 0; i < 3; i++) {
var y = document.createElement("TR");
y.setAttribute("id", "myTr" + i)
modalTable.appendChild(y);
var z = document.createElement("TD");
var t = document.createTextNode(array1[i]);
var z1 = document.createElement("TD");
var s = document.createTextNode(array2[i]);
var z2 = document.createElement("TD");
var r = document.createTextNode(result[i]);
z.appendChild(t);
z1.appendChild(s);
z2.appendChild(r);
y.appendChild(z);
y.appendChild(z1)
y.appendChild(z2)
}
return table;
}
// modalBody.append(table);
$(".modal-body").html(modalBody);
showmodal();
}
table {
border: 1px solid white;
text-align: center;
padding: 6px;
background: #e1edf9;
}
td {
border: 1px solid white;
text-align: center;
padding: 6px;
}
td:first-child,
tr:first-child {
background-color: #003a6a !important;
color: white !important;
}
.table-scroll {
position: relative;
width: 100%;
z-index: 1;
margin: auto;
overflow: auto;
}
.table-scroll table {
width: 100%;
min-width: 1280px;
margin: auto;
border-collapse: separate;
border-spacing: 0;
}
.table-wrap {
position: relative;
}
.table-scroll tr:first-child {
background: #333;
color: #fff;
position: -webkit-sticky;
position: sticky;
top: 0;
}
td:first-child {
position: -webkit-sticky;
position: sticky;
left: 0;
z-index: 2;
background: #ccc;
}
.table-scroll tfoot tr {
position: -webkit-sticky;
position: sticky;
bottom: 0;
background: #666;
color: #fff;
z-index: 4;
}
tr:first-child {
z-index: 5;
}
#media screen and (max-width: 500px) {
td:first-child {
position: -webkit-sticky;
position: sticky;
left: 0;
z-index: 2;
background: #ccc;
max-width: 140px;
}
}
.main-table:not(.result) th.result,
.main-table:not(.result) td.result {
display: none;
}
body:not(.popup)>.modal {
display: none;
}
body.popup> :not(.modal) {
-webkit-filter: blur(1px);
-moz-filter: blur(1px);
-o-filter: blur(1px);
-ms-filter: blur(1px);
filter: blur(1px);
}
.modal {
background-color: rgba(127, 127, 127, 0.5);
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 999;
display: flex;
}
.modal>.modal-dialog {
margin: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="table-scroll" class="table-scroll">
<table class="data" id="main-table">
<tbody>
<tr>
<th class="header">Three</th>
<th class="header">Four<input type="checkbox" value="on" name="cb4" /></th>
<th class="header">Five<input type="checkbox" value="on" name="cb5" /></th>
<th class="header">Five<input type="checkbox" value="on" name="cb5" /></th>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>12</td>
<td>22</td>
<td>32</td>
<td>34</td>
</tr>
<tr>
<td>21</td>
<td>22</td>
<td>23</td>
<td>7</td>
</tr>
</tbody>
</table>
</div>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" onclick="hidemodal ()">×</button>
</div>
<div class="modal-body"></div>
</div>
</div>
</div>

Related

How can i create a button to delete a row?

I have a table that dynamically adds a row after values are inputted. How can I add a delete button at the end of the table which will delete the row and the data that is appended in an array?
I am guessing one way to go about it is using classList and appending it to the last , which in this case is where the "X" delete button is placed in the table.
let myLibrary = [];
function Book(titles, authors, pages, reads){
this.titles = titles,
this.authors = authors,
this.pages = pages,
this.reads = reads
}
function addBookToLibrary(){
let t = document.getElementById("titles").value;
let a = document.getElementById("authors").value;
let p = document.getElementById("pages").value;
let r = document.getElementById("reads").value;
let book = new Book(t, a, p, r);
myLibrary.push(book);
}
function deleteButton(){
let tds = document.querySelectorAll("td");
for (let i = 0; i < tds.length; i++){
let text = tds[i].innerText;
if (text === "x"){
tds[i].classList.add("delete-btn");
}
}
}
let subDisplay = document.getElementById("subDisplay");
subDisplay.addEventListener("click", displayDetails);
let row = 1;
function displayDetails(){
let title = document.getElementById("titles").value;
let author = document.getElementById("authors").value;
let pages = document.getElementById("pages").value;
let read = document.getElementById("reads").value;
let display = document.getElementById("display");
let newRow = display.insertRow(row);
let cell1 = newRow.insertCell(0);
let cell2 = newRow.insertCell(1);
let cell3 = newRow.insertCell(2);
let cell4 = newRow.insertCell(3);
let cell5 = newRow.insertCell(4);
cell1.innerHTML = title;
cell2.innerHTML = author;
cell3.innerHTML = pages;
cell4.innerHTML = read;
cell5.innerHTML = "x";
row++;
modalBg.classList.remove("bg-active");
}
let modalBtn = document.querySelector('.modal-btn');
let modalBg = document.querySelector('.modal-bg');
let modalClose = document.querySelector(".modal-close");
let submitBtn = document.querySelector(".submit-button");
modalBtn.addEventListener("click", function(){
modalBg.classList.add("bg-active");
});
modalClose.addEventListener("click", function(){
modalBg.classList.remove("bg-active");
});
*, *::after, *::before{
box-sizing: border-box;
}
nav {
background-color: black;
color: white;
height: 35px;
position: relative;
}
p {
position: absolute;
margin: 0;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 35px;
}
table {
width: 100%;
}
th {
text-align: left;
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 10px;
}
.modal-bg{
position: fixed;
width: 100%;
height: 100vh;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
visibility: hidden;
opacity: 0;
transition: visibility 0s, opacity 0.5s;
}
.bg-active{
visibility: visible;
opacity: 1;
}
.modal{
position: relative;
padding: 10px;
font-family: "montserrat", sans-serif;
background-color: white;
width: 30%;
height: 30%;
display: flex;
justify-content: space-around;
align-content: center;
flex-direction: column;
}
.modal-button{
padding: 10px 30px;
background-color: black;
color: white;
border: none;
font-family: "Montserrat", sans-serif;
cursor: pointer;
}
.modal-close{
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
}
.submit-button{
margin-top: 10px;
margin-bottom: 10px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src = "script.js" defer></script>
<link rel = "stylesheet" href="styles.css">
</head>
<body>
<nav>
<p>Library</p>
</nav>
<div class = displaytable>
<table id = "display">
<tr>
<th>Title</th>
<th>Author</th>
<th>Pages</th>
<th>Read</th>
<th>Remove</th>
</tr>
</table>
</div>
<button class="modal-btn">Add Book</button>
<button class = "delete-btn">Delete Book</button>
<div class="modal-bg">
<div class ="modal">
<h2>Book</h2>
<label for="name">Title</label>
<input type="text" name="name" id = "titles">
<label for="name">Author</label>
<input type="text" name="name" id = "authors">
<label for="name">Pages</label>
<input type="text" name="name" id = "pages">
<label for="name">Read</label>
<input type="text" name="name" id = "reads">
<span class="modal-close">x</span>
<button class="submit-button" id = "subDisplay" onclick="addBookToLibrary()">Submit</button>
</div>
</div>
</body>
</html>
I would do this by keeping a track of the objects that are on the table using a structure such as an array. Create a separate array and update the same as you update the table. While doing so, do the following:
html = `<tr><td>${item}</td><td><input type="button" onclick="remove('${item}')" value="Remove"></td></tr>`;
Next, add a function that will filter the array to remove the value you clicked from the same and then, recreate the table.
function remove(input) {
arr = arr.filter((value, index, arr) => { return value != input;});
updateTable();
}
I have made a fiddle to demonstrate the same:
https://jsfiddle.net/cruciformhawk7/ozcf3md4/
Edit: After looking at your update, this code might help you.
https://jsfiddle.net/cruciformhawk7/gbuc0j8s/
Hope it helps.

Alternative way to know if mouse is over an element (Javascript)

I have a script which shows a "hover element" (like a zoom) when my mouse is over it. I know it's a bit messy but here's an example:
function showOverflow2(e) {
let cell = e.currentTarget;
let clone = cell.cloneNode(true);
if (cell.children[0].scrollWidth <= cell.children[0].clientWidth) {
return false;
};
clone.innerHTML = clone.children[0].innerHTML;
clone.style.position = 'absolute';
clone.style.backgroundColor = 'white';
clone.style.borderWidth = '2px';
clone.style.lineHeight = cell.scrollHeight + 'px';
clone.style.whiteSpace = 'nowrap';
x0 = (
cell.offsetLeft +
parseFloat(
getComputedStyle(
cell.parentElement.parentElement.parentElement.parentElement
)["padding-left"].slice(0, -2)
) + 2
);
y0 = (
cell.offsetTop +
parseFloat(
getComputedStyle(
cell.parentElement.parentElement.parentElement.parentElement
)["padding-top"].slice(0, -2)
) + 2
);
xmid = x0 + (cell.clientWidth / 2);
ymid = y0 + (cell.clientHeight / 2);
let body = document.getElementsByTagName('body')[0];
body.appendChild(clone);
clone.style.height = cell.scrollHeight + 'px';
clone.style.width = clone.scrollWidth + 'px';
xf = xmid - (clone.clientWidth / 2);
yf = ymid - (clone.clientHeight / 2);
clone.style.top = yf + 'px';
clone.style.left = xf + 'px';
// FOCUS ON THIS PART
clone.addEventListener("mouseout", function() {
clone.remove();
});
// END OF FOCUS
};
let all_cells = document.getElementsByTagName('td');
for (let i = 0; i < all_cells.length; i++) {
let current_cell = all_cells[i];
if (current_cell.className !== 'buttons') {
current_cell.addEventListener("mouseover", showOverflow2);
}
}
body {
margin: 0;
}
#container {
background-color: gainsboro;
border: 2px solid black;
border-radius: 2px;
padding: 1.2%;
max-width: 50%;
}
table {
border-collapse: separate;
border-spacing: 0 0.5rem;
table-layout: fixed;
width: 100%;
}
tr {
background-color: white;
}
td {
width: calc(100%/3);
border: solid gray;
border-width: 2px 1px 2px 0;
padding: 0.7% 1%;
text-align: center;
white-space: nowrap;
}
span {
display: block;
overflow: hidden;
}
td:first-child {
border-left-width: 2px;
border-radius: 3px 0 0 3px;
}
td:last-child {
border-right-width: 2px;
border-radius: 0 3px 3px 0;
}
<div id="container">
<table id="table">
<tr>
<td class="cell1"><span>AAAAAAAAABBBCC</span></td>
<td class="cell2"><span>AAAAAAAAAABBBB</span></td>
<td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
</td>
</tr>
</table>
</div>
To remove the "zoom" and return things to normal, I'm simply using:
clone.addEventListener("mouseout", function() {
clone.remove();
This works fine if you are smoothly moving your mouse over the elements, but with a bigger table and faster movements, you can see for yourselves that some elements don't return to normal:
function showOverflow2(e) {
let cell = e.currentTarget;
let clone = cell.cloneNode(true);
if (cell.children[0].scrollWidth <= cell.children[0].clientWidth) {
return false;
};
clone.innerHTML = clone.children[0].innerHTML;
clone.style.position = 'absolute';
clone.style.backgroundColor = 'white';
clone.style.borderWidth = '2px';
clone.style.lineHeight = cell.scrollHeight + 'px';
clone.style.whiteSpace = 'nowrap';
x0 = (
cell.offsetLeft +
parseFloat(
getComputedStyle(
cell.parentElement.parentElement.parentElement.parentElement
)["padding-left"].slice(0, -2)
) + 2
);
y0 = (
cell.offsetTop +
parseFloat(
getComputedStyle(
cell.parentElement.parentElement.parentElement.parentElement
)["padding-top"].slice(0, -2)
) + 2
);
xmid = x0 + (cell.clientWidth / 2);
ymid = y0 + (cell.clientHeight / 2);
let body = document.getElementsByTagName('body')[0];
body.appendChild(clone);
clone.style.height = cell.scrollHeight + 'px';
clone.style.width = clone.scrollWidth + 'px';
xf = xmid - (clone.clientWidth / 2);
yf = ymid - (clone.clientHeight / 2);
clone.style.top = yf + 'px';
clone.style.left = xf + 'px';
// FOCUS ON THIS PART
clone.addEventListener("mouseout", function() {
clone.remove();
});
// END OF FOCUS
};
let all_cells = document.getElementsByTagName('td');
for (let i = 0; i < all_cells.length; i++) {
let current_cell = all_cells[i];
if (current_cell.className !== 'buttons') {
current_cell.addEventListener("mouseover", showOverflow2);
}
}
body {
margin: 0;
}
#container {
background-color: gainsboro;
border: 2px solid black;
border-radius: 2px;
padding: 1.2%;
max-width: 50%;
}
table {
border-collapse: separate;
border-spacing: 0 0.5rem;
table-layout: fixed;
width: 100%;
}
tr {
background-color: white;
}
td {
width: calc(100%/3);
border: solid gray;
border-width: 2px 1px 2px 0;
padding: 0.7% 1%;
text-align: center;
white-space: nowrap;
}
span {
display: block;
overflow: hidden;
}
td:first-child {
border-left-width: 2px;
border-radius: 3px 0 0 3px;
}
td:last-child {
border-right-width: 2px;
border-radius: 0 3px 3px 0;
}
<div id="container">
<table id="table">
<tr>
<td class="cell1"><span>AAAAAAAAABBBCC</span></td>
<td class="cell2"><span>AAAAAAAAABBBB</span></td>
<td class="cell3"><span>AAAAAAAAAAAABBBBB</span></td>
</td>
</tr>
<tr>
<td class="cell1"><span>AAAAAAAABBBCC</span></td>
<td class="cell2"><span>AAAAAAAAABBBB</span></td>
<td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
</td>
</tr>
<tr>
<td class="cell1"><span>AAAAAAAAABBBCC</span></td>
<td class="cell2"><span>AAAAAAAAAAABBBB</span></td>
<td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
</td>
</tr>
<tr>
<td class="cell1"><span>AAAAAAAAABBBCC</span></td>
<td class="cell2"><span>AAAAAAAAAABBBB</span></td>
<td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
</td>
</tr>
<tr>
<td class="cell1"><span>AAAAAAAAABBBCC</span></td>
<td class="cell2"><span>AAAAAAAAAAABBBB</span></td>
<td class="cell3"><span>AAAAAAAAAAAAAABBBBB</span></td>
</td>
</tr>
<tr>
<td class="cell1"><span>AAAAAAAAAABBBCC</span></td>
<td class="cell2"><span>AAAAAAAAAAaAABBBB</span></td>
<td class="cell3"><span>AAAAAAAAAAAAAAAABBBBB</span></td>
</td>
</tr>
<tr>
<td class="cell1"><span>AAAAAAAABBBCC</span></td>
<td class="cell2"><span>AAAAAAASAABBBB</span></td>
<td class="cell3"><span>AAAAAAAAAAAAAAABBBBB</span></td>
</td>
</tr>
<tr>
<td class="cell1"><span>AAAAAAAAAABBBCC</span></td>
<td class="cell2"><span>AAAAAAAAAABBBB</span></td>
<td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
</td>
</tr>
</table>
</div>
If I can't trust the mouseout event, what can I do to fix this?
I thought about using a eventListener on mouse movement to test if the mouse is inside the element using absolute coordinates, but probably there's a simpler solution.
You could do something similar using CSS by repeating the content (enlarged) and showing and hiding it on hover. Simple example below.
table {
padding: 30px;
}
td {
position: relative;
padding: 4px;
border: 1px solid blue;
}
.grow {
display: none;
background-color: #fff;
border: 1px solid #000;
padding: 3px;
z-index: 10;
}
td:hover .grow {
display: block;
position: absolute;
top: 0;
left: 0;
transform: scale(1.5);
}
<html>
<head></head>
<body>
<table>
<tr>
<td>asdf<span class="grow">ASDF</span></td>
<td>fasd<span class="grow">FASD</span></td>
</table>
</body>
</html>
I'm answering my own question 'cause I needed to combine some ideas to make it work well.
First I need to point out that, for some reason, the problem I described happens in the browser only when the Developer tab (f12) is open, otherwise all works fine.
But still I wanted to be certain that no cell would freeze that way, so I used css like Ed Lucas. Still, I needed Javascript to get the centering right.
After days trying this I finally found a way to center it using css that worked with absolute positioning and the child element being larger.
I didn't remove the Javascript method because it gives me flexibility of commands to trigger and revert this event.
In the end, my code is looking like this:
function showOverflow(e) {
const div = e;
const cell = div.parentElement;
const span = div.children[0];
if (span.scrollWidth <= span.clientWidth) {
return false;
}
const clone = div.cloneNode(true);
clone.classList.add('hovercell');
cell.appendChild(clone);
let cell_style = getComputedStyle(cell);
function cloneRemove(host) {
clone.remove();
clearInterval(host.id);
}
function isInside(host) {
if (cell_style['z-index'] === '0') {
cloneRemove(host);
}
}
let host = {};
host.id = setInterval(isInside.bind(null, host), 100);
clone.addEventListener("mouseleave", function() {
cloneRemove(host);
});
}
td {
border: 2px solid gray;
padding: 0.7% 1%;
text-align: center;
white-space: nowrap;
z-index: 0;
position: relative;
}
td:hover {
z-index: 2;
}
span {
display: block;
overflow: hidden;
}
.hovercell {
background-color: white;
border: 2px solid gray;
padding: 6px 8px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(1.2);
}
<table>
<tbody>
<tr>
<td>
<div onclick="showOverflow(this)">
<span>A big cell--- 1</span>
</div>
</td>
<td>
<div onclick="showOverflow(this)">
<span>A big cell--- 2</span>
</div>
</td>
</tr>
</tbody>
</table>
Hope it helps someone.

table cell height is bigger than it's width (but set the same number for both)

I'm trying to put a grid (table) on a div using Javascript. The div has a width of 600px and a height of 400px. Every cell of the table is 20x20px. But the height of cells is bigger than their width. Why's that? And how to fix that?
var htmlElements = "";
for (var r = 0; r < 20; r++) {
htmlElements += '<tr class="tRow">';
for (var c = 0; c < 30; c++) {
htmlElements += '<td class="tCell"></td>';
}
htmlElements += '</tr>'
}
var theTable = document.getElementById("tab");
theTable.innerHTML = htmlElements;
#workspace {
position: absolute;
width: 600px;
height: 400px;
background-color: cadetblue;
top: 50%;
left: 50%;
margin-left: -300px;
margin-top: -200px;
}
table,
tr,
td {
border: 1px solid black;
border-collapse: collapse;
padding: 0;
}
td {
width: 20px;
height: 20px;
}
<div id="workspace">
<table id="tab">
</table>
</div>
Your cells are rescaling because you have set a fixed height and width for the container #workspace.
In a table, explicit cell widths and heights are always overridden by the table size as a whole.
If you insist on setting a width then ensure the correct calculation is used.
In this case the width is 631px. (30 right borders and 1 left).
I believe your failed to account for the 1px border in your sum.
var htmlElements = "";
for (var r = 0; r < 20; r++) {
htmlElements += '<tr class="tRow">';
for (var c = 0; c < 30; c++) {
htmlElements += '<td class="tCell"></td>';
}
htmlElements += '</tr>'
}
var theTable = document.getElementById("tab");
theTable.innerHTML = htmlElements;
#workspace {
position: absolute;
width: 631px;
height: 421px;
background-color: cadetblue;
top: 50%;
left: 50%;
margin-left: -300px;
margin-top: -200px;
}
table,
tr,
td {
border: 1px solid black;
border-collapse: collapse;
padding: 0;
}
td {
width: 20px;
height: 20px;
}
<div id="workspace">
<table id="tab">
</table>
</div>
Just add box-sizing: border-box; to your cells:
border-box The width and height properties include the content, padding, and border, but do not include the margin. Note that padding
and border will be inside of the box.
var htmlElements = "";
for (var r = 0; r < 20; r++) {
htmlElements += '<tr class="tRow">';
for (var c = 0; c < 30; c++) {
htmlElements += '<td class="tCell"></td>';
}
htmlElements += '</tr>'
}
var theTable = document.getElementById("tab");
theTable.innerHTML = htmlElements;
#workspace {
position: absolute;
width: 600px;
height: 400px;
background-color: cadetblue;
top: 50%;
left: 50%;
margin-left: -300px;
margin-top: -200px;
}
table,
tr,
td {
border: 1px solid black;
border-collapse: collapse;
padding: 0;
box-sizing: border-box;
}
td {
width: 20px;
height: 20px;
}
<div id="workspace">
<table id="tab">
</table>
</div>

Crosshair highlight for table on hover

I have the code below that works perfect for crosshair function. This is fine, however wondering if there is a way to stop the highlight beyond the cursor (hover).
For example, instead of a "cross" shape highlight you end up with a backward "L" shape highlight. So instead of highlighting the whole row & column it only highlights column 3 down to row 2 and row 2 only to column 3. No extended highlight. Hope that makes sense?
Here is my css code:
table {
border-collapse: collapse;
overflow: hidden;
z-index: 1;
}
.permissions table,
th,
td {
border: 2px solid #ccc;
width:90px;
height:90px;
text-align:center;
vertical-align:middle;
font-size:13px;
}
td, th, .row, .col, .ff-fix {
cursor: pointer;
position: relative;
}
tr, col {
border: 1px solid black;
}
td:hover {
background-color:red;
}
td:hover:first-child {
background-color:red;
}
td:hover:nth-child(3n) {
background-color:red;
}
tr:last-child td:hover {
background-color:red;
}
td:hover::before,
.row:hover::before,
.ff-fix:hover::before {
background-color: #ffa;
content: '\00a0';
height: 100%;
left: -5000px;
position: absolute;
top: 0;
width: 10000px;
z-index: -1;
}
td:hover::after,
.col:hover::after,
.ff-fix:hover::after {
background-color: #ffa;
content: '\00a0';
height: 10000px;
left: 0;
position: absolute;
top: -5000px;
width: 100%;
z-index: -1;
}
Here is my html code:
<table>
<col /><col /><col />
<tr>
<th class="col">First Name</th>
<th class="col">Middle Name</th>
<th class="col">Last Name</th>
</tr>
<tr>
<td>Peter</td>
<td>Jeffery</td>
<td>Griffin</td>
</tr>
<tr>
<td>Lois</td>
<td>Marie</td>
<td>Griffin</td>
</tr>
<tr>
<td>Margie</td>
<td>Ann</td>
<td>Thatcher</td>
</tr>
</table>
Following the logic of your CSS, you apply a full-width ::before and a full-height ::after which are displayed over the table. To adjust how these are displayed (a cross vs a "backward L"), adjust the corresponding horizontal and vertical positioning.
Try replacing your td:hover::before and td:hover::after selectors with the following to display the highlighting as a "backward L". Note the positioning is set using right and bottom rule sets, as opposed to your original positioning using left and top.
td:hover::before,
.row:hover::before,
.ff-fix:hover::before {
background-color: #ffa;
content: '\00a0';
height: 100%;
right: 90px;
position: absolute;
top: 0;
width: 10000px;
z-index: -1;
}
td:hover::after,
.col:hover::after,
.ff-fix:hover::after {
background-color: #ffa;
content: '\00a0';
height: 10000px;
left: 0;
position: absolute;
bottom: 90px;
width: 100%;
z-index: -1;
}
See how it looks in this JSFiddle.
I know this is old, but here's a method using Javascript. I prefer this method because it allows for custom backgrounds, and doesn't require CSS workarounds.
HTML:
<table id="hoverTable">
<thead>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
<th>Column4</th>
</thead>
<tbody>
<tr>
<td>Item</td>
<td>Item</td>
<td>Item</td>
<td>Item</td>
</tr>
<tr>
<td>Item</td>
<td>Item</td>
<td>Item</td>
<td>Item</td>
</tr>
<tr>
<td>Item</td>
<td>Item</td>
<td>Item</td>
<td>Item</td>
</tr>
<tr>
<td>Item</td>
<td>Item</td>
<td>Item</td>
<td>Item</td>
</tr>
</tbody>
</table>
SCSS:
body {
background:grey;
}
.hoverHighlight {
background-color:yellow !important;
cursor:default;
}
#hoverTable {
font-family:arial;
border-spacing:0;
border-collapse: collapse;
th, td {
border:2px solid black;
text-align:center;
padding:5px;
margin:0;
}
th {
background:#1167b1;
color:white;
}
td {
text-align:center;
background:#d0efff;
}
}
Javascript:
window.addEventListener('load', function () {
addHoverEventsAndClasses();
})
function toggleHighlight(element, trueOrFalse) {
const currentRow = returnCurRow(element);
const index = element.currentTarget.cellIndex;
const table = document.getElementById('hoverTable').rows;
for (var i = 0; i < table.length; i++) {
const data = table[i];
const cells = data.querySelectorAll(".cell");
if(data.rowIndex === currentRow) {
cells.forEach((td) => {
trueOrFalse ? td.classList.add("hoverHighlight") : td.classList.remove("hoverHighlight");
});
}
cells.forEach((cell) => {
if(cell.cellIndex === index) {
trueOrFalse ? cell.classList.add("hoverHighlight") : cell.classList.remove("hoverHighlight");
}
});
}
};
function addHoverEventsAndClasses() {
const mainTableTDs = document.querySelectorAll("#hoverTable td");
const mainTableTRs = document.querySelectorAll("#hoverTable tr");
//Dynamically add class names to each row and cell to target
addClass(mainTableTDs, "cell");
addClass(mainTableTRs, "row");
mainTableTDs.forEach((td) => {
td.addEventListener("mouseenter", highlightCol);
td.addEventListener("mouseleave", removeHighlightCol);
});
}
//Helper function for adding highlight classes
function addClass(el, cl) {
el.forEach((child) => {
child.classList.add(cl);
});
};
//Toggle highlight functions. Did it this way so multiple arguments could be passed
function highlightCol(e) {
toggleHighlight(e, true);
}
function removeHighlightCol(e) {
toggleHighlight(e, false);
}
//Grab the current row
const returnCurRow = (e) => {
return e.currentTarget.parentElement.rowIndex;
}

"float: left" div gets pushed down on input focus

I have the following form for lyrics upload. I've changed the design of the form a little bit, and now facing a weird problem.
I've created a fake-datalist using JS. On input focus, a fake-datalist (an ul element) is appended next to the input element. Its position is set to absolute so it shouldn't disrupt the flow of the document when it appears. However, it does. I can't seem to identify the problem. Once the datalist appears, the div next to the table gets pushed down. Table width isn't changing when the datalist appears, so it's not squizing the div and pushing it down.
Code Pen
var artists = [{"artist":"3 Doors Down"},{"artist":"5 Seconds of Summer"},{"artist":"Adele"},{"artist":"Alicia Keys"},{"artist":"Amanda Abizaid"},{"artist":"Avril Lavigne"}];
var albums = [{"album":"The Better Life","year":"2000","cover":"3_doors_down_2000_the_better_life.jpg"},{"album":"Away from the Sun","year":"2002","cover":"3_doors_down_2002_away_from_the_sun.jpg"},{"album":"Seventeen Days","year":"2005","cover":"3_doors_down_2005_seventeen_days.jpg"},{"album":"3 Doors Down","year":"2008","cover":"3_doors_down_2008_3_doors_down.jpg"},{"album":"Time of My Life","year":"2011","cover":"3_doors_down_2011_time_of_my_life.jpg"}];
var songs = [{"song":"Kryptonite","track_no":"1"},{"song":"Duck and Run","track_no":"3"},{"song":"Be Like That","track_no":"5"},{"song":"So I Need You","track_no":"11"}];
function datalist(element) {
return new datalist.prototype.init(element);
}
datalist.prototype = {
init: function(element) {
if (!element) {
this.element = document.createElement("ul");
this.element.classList.add("datalist");;
this.hide();
} else {
this.element = element;
}
},
update: function(queryElement) {
this.clear();
var lookUpArray = queryElement.name + "s";
var results = this.search(window[lookUpArray], queryElement.value, queryElement.name);
for (var i = 0; i < results.length; i++) {
var li = document.createElement("li");
var value = results[i][queryElement.name];
switch (queryElement.name) {
case "album":
li.setAttribute("data-year", results[i].year);
break;
case "song":
li.setAttribute("data-track_no", results[i].track_no);
break;
}
if (queryElement.value != "") {
var re = new RegExp(queryElement.value, "gi");
value = value.replace(re, "<span class=\"highlight\">" + "$&" + "</span>");
}
li.innerHTML = value;
this.element.appendChild(li);
}
return results.length;
},
search: function(lookUpArray, string, queryType) {
var results = [];
for (var i = 0; i < lookUpArray.length; i++) {
if (lookUpArray[i][queryType].toLowerCase().search(string.toLowerCase()) != -1) {
results.push(lookUpArray[i]);
}
}
return results;
},
clear: function() {
this.element.innerHTML = "";
},
hide: function() {
this.element.style.display = "none";
},
show: function() {
this.element.style.display = "";
},
remove: function() {
this.element.parentElement.removeChild(this.element);
},
for: function(sibling) {
sibling.parentElement.appendChild(this.element);
this.hide();
},
};
datalist.prototype.init.prototype = datalist.prototype;
var lastVisitedInput = null;
$("#lyrics-form").on("focus", "input.datalist-input", function() {
if (this.parentElement.children.length == 1) {
this.parentElement.appendChild(datalist().element);
}
if (lastVisitedInput) {
datalist(lastVisitedInput.nextElementSibling).hide();
}
lastVisitedInput = this;
if (datalist(this.nextElementSibling).update(this)) {
datalist(this.nextElementSibling).show();
} else {
datalist(this.nextElementSibling).hide();
}
});
$(document).on("click", function(e) {
if (lastVisitedInput) {
var exceptions = getExceptions(lastVisitedInput);
if (!contains(exceptions, e.target)) {
datalist(lastVisitedInput.nextElementSibling).remove();
lastVisitedInput = null;
}
}
});
$("#lyrics-form").on("input", "input.datalist-input", function() {
if (datalist(this.nextElementSibling).update(this)) {
datalist(this.nextElementSibling).show();
} else {
datalist(this.nextElementSibling).hide();
}
});
$("#lyrics-form").on("click", "li", function() {
this.parentElement.previousElementSibling.value = this.innerText;
$(this.parentElement.previousElementSibling).trigger("input");
});
function getRecord(input) {
var lookUpArray = window[input.name + "s"];
for (var i = 0; i < lookUpArray.length; i++) {
if (input.value == lookUpArray[i][input.name]) {
return lookUpArray[i];
}
}
return false;
}
function getExceptions(input) {
var exceptions = [
input,
input.nextElementSibling,
];
for (var i = 0; i < input.nextElementSibling.children.length; i++) {
exceptions.push(input.nextElementSibling.children[i]);
}
return exceptions;
}
function contains(array, item) {
for (var i = 0; i < array.length; i++) {
if (array[i] === item) {
return true;
}
}
return false;
}
* { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } *, *:before, *:after { box-sizing: inherit; } body { line-height: 1.5; font-family: sans-serif; } input[type="button"], input[type="submit"] { cursor: pointer; } textarea, input[type="text"], input[type="search"], input[type="number"], input[type="password"] { border: 1px solid rgba(0,0,0,.2); padding: 4px; margin: 1px; } table { border-collapse: collapse; border-spacing: 0; }
body {
background-color: rgb(230, 230, 230);
font-family: Arial, sans-serif;
font-size: 14px;
color: rgba(0, 0, 0, .8);
box-sizing: border-box;
}
#main {
height: 500px;
background: white;
box-shadow: 0 0 2px rgba(0, 0, 0, .1), 0 2px 2px rgba(0, 0, 0, .1);
margin: 20px auto;
display: table;
padding: 20px;
}
#songInput {
overflow: auto;
}
#songTable td {
position: relative;
}
#songTable,
#coverDiv {
float: left;
}
#coverDiv {
margin-left: 20px;
}
#artist,
#album,
#song {
width: 250px;
}
#artist {
width: 300px;
width: 100%;
}
#year,
#track_no {
width: 70px;
}
#songTable td {
padding-bottom: 20px;
}
#songTable td:first-child {
padding-right: 10px;
}
#songTable .int-input {
padding-left: 20px;
padding-right: 10px;
}
#coverDiv > * {
display: block;
}
#coverDiv img {
width: 137px;
height: 137px;
border: 1px solid rgba(0, 0, 0, .2);
margin: 1px;
}
#coverUpload {
margin: 1px;
margin-top: 10px;
width: 250px;
}
#lyricsBox {
width: 100%;
height: 400px;
margin-top: 15px;
}
#submit {
width: 100%;
margin-top: 15px;
}
.datalist {
border: 1px solid silver;
box-shadow: 0 2px 5px rgba(0, 0, 0, .5);
position: absolute;
top: 32px;
left: 1px;
background: white;
padding: 5px;
max-height: 195px;
width: 180px;
width: 100%;
overflow-y: scroll;
z-index: 1000;
}
.datalist li {
padding: 2px 5px;
cursor: default;
}
.datalist li:hover {
background: rgba(0, 0, 0, .05);
color: black;
}
.datalist .highlight {
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<form action="addlyrics.php" id="lyrics-form" method="post" autocomplete="off" enctype="multipart/form-data">
<div id="songInput">
<table id="songTable">
<tr>
<td>Artist</td>
<td colspan="3">
<input type="search" name="artist" id="artist" class="datalist-input" placeholder="Artist" required />
</td>
</tr>
<tr>
<td>Album</td>
<td>
<input type="search" name="album" id="album" class="datalist-input" placeholder="Album" required />
</td>
<td class="int-input">Year</td>
<td>
<input type="number" name="year" id="year" class="input-num" placeholder="Year" required />
</td>
</tr>
<tr>
<td>Song</td>
<td>
<input type="search" name="song" id="song" class="datalist-input" placeholder="Name" required />
</td>
<td class="int-input">#</td>
<td>
<input type="number" name="track_no" id="track_no" class="input-num" placeholder="ID" required />
</td>
</tr>
</table>
<div id="coverDiv">
<img src="covers/blank.gif" id="cover" />
<input type="file" name="cover" id="coverUpload" accept="image/*" />
</div>
</div>
<textarea name="lyrics" placeholder="Lyrics" id="lyricsBox" /></textarea>
<input type="submit" id="submit" class="button" />
</form>
</div>
Removing overflow: auto; from #songInput, the parent element of the table and the div, solved the problem. Although, I don't understand why overflow: auto; on the parent would push the div down. Dynamically added ul.datalist's position is set to absolute, and when it appears, the only thing it might do is extend the height of the table, which shouldn't effect the div at the right.

Categories

Resources