How to make a div scrollable without scaling its contents? - javascript

I want a table displayed as a grid.The table is held by a div. In case it extends the div's dimension I want to be able to scroll the div in order to see the entire table.The table content is generated in the script. I also defined some css classes.
var rows = 500;
var cols = 500;
PopulateGrid();
function PopulateGrid() {
var table = document.getElementById("GridTable");
for (i = 0; i < rows; i++) {
var tr = document.createElement('TR');
for (j = 0; j < cols; j++) {
var td = document.createElement('TD')
tr.appendChild(td);
}
table.appendChild(tr);
}
}
td {
border: 1px solid black;
height: 50px;
width: 50px;
}
table {
border-spacing: 0px;
}
.GridContainer {
height: 650px;
width: 1447px;
overflow: scroll;
}
<head runat="server">
<title></title>
</head>
<body>
<div class="GridContainer">
<table id="GridTable"></table>
</div>
</body>
Unfortunately the dt width is scaled while its height seems to correspond with the value defined in css. Am I missing some css property?

Width on TD elements is a bit odd, and the rules can be a bit complex. You are thinking that the table width should be the sum of the individual td elements, but it works in reverse. The minimum required size for the table is determined as well as the size it would like it to be, then it tries to determine sane values for the widths of the TDs. The following works, and it would also work if you set the table width to 500*50px (25000px).
var rows = 500;
var cols = 500;
PopulateGrid();
function PopulateGrid() {
var table = document.getElementById("GridTable");
for (i = 0; i < rows; i++) {
var tr = document.createElement('TR');
for (j = 0; j < cols; j++) {
var td = document.createElement('TD')
tr.appendChild(td);
}
table.appendChild(tr);
}
}
td {
border: 1px solid black;
height: 50px;
width: 50px;
min-width: 50px;
}
table {
border-spacing: 0px;
}
.GridContainer {
height: 650px;
width: 1447px;
overflow: scroll;
}
<head runat="server">
<title></title>
</head>
<body>
<div class="GridContainer">
<table id="GridTable"></table>
</div>
</body>

Related

Is there a way I can get the table to not resize in height when I innerHtml something in the "td"?

I am sorry for the norwegian variable names in the js file, but if u try to click a cell, you will see that the height of it will resize, I am wondering if anyone have an easy and quick change!
<!doctype html>
<html lang="no">
<head>
<title> Standardoppsett </title>
<meta charset="utf-8">
</head>
<style>
.board {
table-layout: fixed;
width: 360px;
height: 360px;
border: 32px solid;
border-color: darkslategray;
border-radius: 5px;
}
.firkant {
border: 1px black solid;
}
.hvit{
background:white;
}
.svart{
background:grey;
}
td:hover {
background: lightgreen;
cursor: pointer
}
</style>
<body>
<div>
<table class="board"></table>
</div>
<script>
let tableEl = document.querySelector("table")
for(let i = 1; i < 9; i++) {
let trEl = document.createElement('tr');
for(let j = 1; j < 9; j++) {
let tdEl = document.createElement('td');
tdEl.setAttribute("id","rute"+i+j)
tdEl.addEventListener("click",plasserDronning)
trEl.appendChild(tdEl);
// Bare på grunn av css
tdEl.className = (i%2 === j%2) ? "hvit firkant" : "svart firkant";
}
tableEl.appendChild(trEl);
}
turTeller = 0
function plasserDronning(e){
let firkantTrykket = e.target
console.log(firkantTrykket.id)
if (turTeller == 0) {
if(firkantTrykket = e.target){
firkantTrykket.innerHTML = "a";
}
turTeller = 1
}
else if(turTeller == 1) {
if(firkantTrykket = e.target){
firkantTrykket.innerHTML = "b";
}
turTeller = 2
}
}
</script>
</body>
</html>
So far I have tried basically everything I am aware of, I have tried to set the table layout to fixed, I have tried to set the "td's" posistion to top and a lot more, if anyone knows what I can do, it would mean a lot!
In above code I suggest to add height properties in you td tag's class that will solve your issue.
if you want to more responsive and you can write media queries.or using other framework like bootstap.
.hvit{
background:white;
height:20px;
}
.svart{
background:grey;
height:20px;
}
You can add height:calc(100% / 8); to the firkant (td) class to prevent the cell from growing.
This way the cell will scale with the table if you decide to increase the table size or make it dynamic.

DOM nodes styles which have been manually fiddled with get invalidated if any parent style changes

Please, take a look at this fiddle (I am using Vue.js to generate lots of DOM nodes here, but my question doesn't seem to be a Vue related issue): https://jsfiddle.net/dmaevsky/kswj23r1/117/ .
When I am monitoring performance using Chrome's performance tool while pressing the button in a rapid succession, I am seeing 42ms 'Update Layer Tree' rendering delay, which makes sense, since the stuff is moving on page, so why not (I am still wondering btw whether there's a way to eliminate this).
However, things get awry when I uncomment the line 30, thus manually setting the td's styles in Javascript:
//nr = 50, nc = 50;
for (let i = 0; i < nr; i++) {
for (let j = 0; j < nc; j++) {
this.$refs[i + ':' + j][0].style.color = 'blue';
}
}
When I now monitor the performance I see all 2500 TD nodes added to the "Recalculating styles" in Chrome when 'Shift down' button is pressed. I just cannot see why that would make any sense ? Using a class instead of setting styles manually does not cause this to happen.
This is just an attempt to understand the browser's style invalidation logic, not a real application, so the number of DOM nodes here is intentionally kept higher than one would reasonably need in a real world application, though close enough.
UPDATE:
This actually DOES seem to be a Vue.js issue finally. I have re-written the code in pure JS (complete HTML below), and I do not observe the same effect anymore.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Create table test</title>
<style>
body {
font-family: Helvetica;
}
#app {
background: #fff;
padding: 20px;
}
#app {
position: relative;
}
#pane {
position: absolute;
}
.table {
table-layout: fixed;
border-collapse: collapse;
margin: 0;
padding: 0;
border: hidden;
width: 8000px;
height: 1600px;
}
.cell {
width: 100px;
height: 20px;
line-height: 16px;
box-sizing: border-box;
padding: 2px;
background: white;
overflow: hidden;
}
</style>
</head>
<body>
<noscript>
<strong>Need JS</strong>
</noscript>
<button onclick="shift()">Shift down</button>
<div id="app">
<div id="pane"></div>
</div>
</body>
</html>
<script>
var pos = 0;
function shift() {
pos++;
document.getElementById('pane').style.top = pos + 'px';
}
function createTable(nr, nc) {
let table = document.createElement('table');
table.className = 'table';
for (let i = 0; i < nr; i++) {
let tr = document.createElement('tr');
for (let j = 0; j < nc; j++) {
let td = document.createElement('td');
let span = document.createElement('span');
span.innerHTML = i + j;
td.className = 'cell';
td.style.color = 'blue';
td.appendChild(span);
tr.appendChild(td);
}
table.appendChild(tr);
}
return table;
}
document.getElementById('pane').appendChild(createTable(80, 80));
</script>
Question to Vue.js experts then: what does Vue do to DOM to warrant the observed behavior in the first fiddle???

JavaScript Manipulation of DOM Issue

I have a table which I want the first column to not move when I am scrolling horizontally. This code below works great for the first column of td's but does not work for the tr's. I have stepped through the code and it all appears to set the values I am expected, but the tr cell does not move with the td cells.
window.onscroll = function()
{
var scrollPosX = window.scrollX;
var theTable = document.getElementById("tablename"),
thead = theTable.getElementsByTagName("thead")[0];
tbody = theTable.getElementsByTagName("tbody")[0];
hrCell = thead.getElementsByTagName("tr")[0];
hrCell.style.left = scrollPosX;
rCells = tbody.getElementsByTagName("td");
for(var i = 0; i < rCells.length; i++)
{
rCells[i].style.left = scrollPosX;
}
}
JQuery is not an option in this problem as the program I am working on does not support it.
<style>
table
{
border: solid black 1px;
}
td{
min-width: 300px;
border: solid black 1px;
}
#run_gen_table td:first-child, #run_gen_table th:first-child
{
background-color: white;
position: relative;
}
</style>
<table id="tablename">
<thead id="headname">
<tr><th>Run No.</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>10</th></tr>
</thead>
<tbody id="bodyname">
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td></tr>
</tbody>
</table>
I have not tested it but your code would alter all the td elements, not just the first column. A better approach would be to use document.querySelector() to select the first td and th elements.
window.onscroll = function()
{
var scrollPosX = window.scrollX;
var rCells = document.querySelector("#tablename th:first-child, #tablename td:first-child");
for(var i = 0; i < rCells.length; i++)
{
rCells[i].style.left = scrollPosX;
}
}

HTML on-click button to run javascript function

I would like to create an on click button to run a javascript function to generate a grid in the style of a crossword.
I have written some javascript to create the grid and I have made the button with the onclick function, but I am unable to get the button to run the script.
I'm sure the solution is glaringly obvious but I'm new to coding so any and all help would be appreciated!
<html>
<body>
<!--<button onclick="generateGrid()">Click to generate crossword grid</button>-->
<div id="crosswordGrid" align="center"></div>
</body>
</html>
function generateGrid () {
var crosswordGrid = document.getElementById("crosswordGrid");
for (var r = 0; r < rows; r++) {
var row = crosswordGrid.appendChild(document.createElement("div"));
for (var c = 0; c < cols; c++) {
row.appendChild(document.createElement("span"));
}
}
const gridSize = 7;
var rows = gridSize;
var cols = gridSize;
}
This is what my current code looks like;
http://jsfiddle.net/YEJ9A/97/
So I think you were mostly the way there. I moved the values you were assigning at the bottom of the file into the default value of the function. See the corrections below.
Also updated on fiddle. https://jsfiddle.net/r8aLbakr/1/
function generateGrid (gridSize = 7, rows = 7, cols = 7, crosswordGrid) {
var crosswordGrid = document.getElementById("crosswordGrid");
for (var r = 0; r < rows; r++) {
var row = crosswordGrid.appendChild(document.createElement("div"));
for (var c = 0; c < cols; c++) {
row.appendChild(document.createElement("span"));
}
}
}
#crosswordGrid div {
line-height: 1px;
}
#crosswordGrid span {
display: inline-block;
width: 28px;
height: 28px;
border: 1px solid black;
}
#crosswordGrid div:nth-child(even) span:nth-child(even) {
background-color: black;
}
#crosswordGrid div:nth-child(odd) span:nth-child(odd) {
background-color: white;
}
<html>
<body>
<button onclick="generateGrid()">Click to generate crossword grid</button>
<div id="crosswordGrid" align="center"></div>
</body>
</html>
Try to use "addEventListener" instead of "onclick"
here is my answer
Code:
document.getElementById ("btn").addEventListener("click", function() {
generateGrid(7);
} , false);
function generateGrid(gridSize) {
var rows = gridSize;
var cols = gridSize;
var crosswordGrid = document.getElementById("crosswordGrid");
for (var r = 0; r < rows; r++) {
var row = crosswordGrid.appendChild(document.createElement("div"));
for (var c = 0; c < cols; c++) {
row.appendChild(document.createElement("span"));
}
}
}
#crosswordGrid div {
line-height: 1px;
}
#crosswordGrid span {
display: inline-block;
width: 28px;
height: 28px;
border: 1px solid black;
}
#crosswordGrid div:nth-child(even) span:nth-child(even) {
background-color: black;
}
#crosswordGrid div:nth-child(odd) span:nth-child(odd) {
background-color: white;
}
<html>
<body>
<button id="btn">Click to generate crossword grid</button>
<div id="crosswordGrid" align="center"></div>
</body>
</html>

Line up generated divs horizontally

I'm creating a map generator that lets a user enter the number of rows and columns in the map, and then create that map (as divs). Everything works correctly, except the divs, instead of being in rows and columns, it's all in one big column. It does have the correct amount of tiles (for example, it has 6 if you enter 3 and 2, or 25 if you enter 5 and 5). The kicker is that if I enter divs in the regular html file, they line up like they're supposed to.
Here's my javascript function:
function createMap(rows, columns) {
var $div = $('<div></div>');
var k = 0;
while (k < rows) {
for (i = 0; i < columns; i++) {
$div.append('<div></div>');
}
$div.append('<br>');
k++;
}
$('body').empty();
$('body').append($div);
}
Here's my CSS:
div {
width: 100px;
height: 100px;
border: 1px solid black;
display: inline-block;
}
The generated divs are reading the CSS fine - they have the proper height, width, and border. It seems that they're just creating a new line for every one. Can anyone tell me why?
You gave ALL your divs a width of 100px. You have divs in a div. So you need to change your styles to only target the children
You want only the children divs to have the width of 100px.
function createMap(rows, columns) {
var $div = $('<div></div>');
var k = 0;
while (k < rows) {
for (i = 0; i < columns; i++) {
$div.append('<div></div>');
}
$div.append('<br>');
k++;
}
$('body').empty();
$('body').append($div);
}
createMap(2,3)
div > div {
width: 100px;
height: 100px;
border: 1px solid black;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Float your divs
div {
width: 100px;
height: 100px;
border: 1px solid black;
display: inline-block;
float: left;
}

Categories