How to make button that changes grid dimensions using JS? - javascript

I have created a 16x16 grid. I'm trying to put a button above the grid, which when the user clicks, will prompt them for new grid dimensions (between 1 and 64). For example, if you click the button and input 25, the dimensions of the grid will change from 16x16 to 25x25.
I'm having trouble in figuring out how to get the user's input into a javascript function, so it outputs the updated grid. Code here:
HTML:
<!doctype html>
<html>
<head>
<title>SketchPad</title>
<link rel="stylesheet" type="text/css" href="style.css" >
</head>
<body>
<h1> SketchPad </h1>
<div id="container">
</div>
<button class="button" type="button" onclick="myFunction()">Choose Your Grid</button>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="jquery.js"></script>
</body>
</html>
CSS:
h1 {
text-align: center;
color: black;
}
tr, td, table {
border-style: solid;
border-width: 1px;
background-color: gray;
margin: auto;
height: 25px;
width: 525px;
margin-top: 20px;
}
td {
transition: .3s background-color;
}
td:hover {
background-color: red;
}
button {
height: 25px;
width: 225px;
margin: 0 auto;
position: relative;
top: 50%;
left: 40%;
margin-top: -40px;
}
Javascript:
var rows=16;
var cols=16;
document.write("<table>");
for (i=0; i<rows; i++) {
document.write("<tr>");
for (j=0; j<cols; j++) {
document.write("<td>"+"</td>");
}
document.write("</tr>");
}
document.write("</table>");
$( "td").css("color", "red");
$(".button").click(function() {
prompt("Please select your grid size");
});
function grid(rows, cols) {
//function goes here//
}

Try something like the following.
Write a function which empties your container and redraws your grid inside it.
Initialize your grid in a document.ready() hander.
Define an event handler for your button click, which prompts to redraw the grid at a user-defined size.
$(document).ready(function() {
grid(16,16);
});
$(".button").click(function() {
var size = prompt("Please select your grid size");
grid(size, size);
});
function grid(rows, cols) {
var table = "<table>";
var size = (1 / rows * 525) + "px";
for (i=0; i<rows; i++) {
table += "<tr>";
for (j=0; j<cols; j++) {
table += "<td>"+"</td>";
}
table += "</tr>";
}
table += "</table>";
$("#container").empty().append(table);
$("tr").css("height", size);
$("td").css("color", "red").css("width", size);
}
h1 {
text-align: center;
color: black;
}
table {
height: 525px;
width: 525px;
}
tr, td, table {
border-style: solid;
border-width: 1px;
background-color: gray;
margin: auto;
margin-top: 20px;
}
td {
transition: .3s background-color;
}
td:hover {
background-color: red;
}
button {
height: 25px;
width: 225px;
margin: 0 auto;
position: relative;
top: 50%;
left: 40%;
margin-top: -40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h1> SketchPad </h1>
<div id="container">
</div>
<button class="button" type="button">Choose Your Grid</button>

Related

Issue with stretching of grid when grid gets generated below 16 rows

I am generating a grid on page load. When you generate a grid below 16 the grid gets stretched like this:
https://imgur.com/a/1IPnXn0
I have tried to adjust the width of the row with css. I have also made changes to the container with css. I believe this has something to do specifically with the width of the .row css which is set to 25.25%
working codepen
https://codepen.io/dhuang6/pen/ZVKWGe
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="container">
<div id="Btns">
<button id="recreate"
onclick="resizeGrid(this.value)">remake
grid</button>
</div>
<br />
</div>
<script src="script.js"></script>
</body>
</html>
window.onload = function(){
var createGrid = prompt("How many rows do you want?");
for(i = 0; i <= createGrid; i++){
var row = document.createElement('div');
row.className = "row";
row.id = "row" + i;
for(k= 0; k <= createGrid; k++ ){
var box = document.createElement('div');
box.className = "box";
row.appendChild(box);
}
container.appendChild(row);
}
return container;
}
#container {
width: 50%;
height: 50%;
margin-top:50px;
margin-left: auto;
margin-right: auto;
background: "white";
overflow:hidden;
box-sizing: border-box;
}
.row{
border:1px solid red;
height:1em;
width:25.25%;
overflow:hidden;
box-sizing: border-box;
}
.box{
display: inline-block;
width: 8.25%;
height: 1em;
border: 1px solid red;
border-bottom: 0px;
border-left: 0px;
float:right;
overflow:hidden;
box-sizing: border-box;
margin: auto;
}
When you inspect the element of the .row of the html the width is usually set to 265px or something really long like that. I believe that is part of the problem. When you generate a grid larger than 16 this issue doesn't occur.
Thank you for helping me.
You need to dynamically set the box width: https://codepen.io/brien-givens/pen/wRdGJa
Here is a working version using a table instead of divs.
There are alot of css changes so make sure to look over the code carefully or copy it verbatim. Also because of the way tables work the grid is basically turned 90deg so keep that in mind.
//try flexbox
/*
adding a button and having the submit grab the value for the backend function
*/
//trying to make a function for creating divs
window.onload = function(){
var createGrid = prompt("How many rows do you want?"),
table = document.getElementById('table');
console.log(createGrid);
for(i = 0; i <= createGrid; i++){
var row = document.createElement('tr'); //changed from div
row.className = "row";
row.id = "row" + i;
for(k= 0; k <= createGrid; k++ ){
var box = document.createElement('td'); //changed from div
box.className = "box";
row.appendChild(box);
}
table.appendChild(row); //changed from container.
}
return container;
}
//create a grid
//generates a grid with the original div container already on index.html you need to start messing with the code you work with to gain a better understanding of what it's doing
function grid() {
var container = document.getElementById("container");
for (i = 0; i <= 16; i++){
for(k = 0; k <= 16; k ++){
var box = document.createElement("div");
box.className = "box";
// row.appendChild(box);
}
container.appendChild(row);
}
return container;
}
// grid(document.body);
function resizeGrid(){
clearGrid();
//missing a clear grid function!
}
//right now the resizing is adding to the bottom of the old grid.
function clearGrid(){
}
document.addEventListener("mouseover",(e)=>{
if(!e.target.classList.contains("box")){
return;
}
e.target.style.background = "#3d3d3d";
})
/*
added the container that holds the grid to manipulate the css.
made it appear more like the etch-a-sketch board.
width: 25.25%;
*/
#container {
width: 50%;
height: 50%;
margin-top:50px;
margin-left: auto;
margin-right: auto;
background: "white";
overflow:hidden;
box-sizing: border-box;
}
#table {
width: 100%;
border-collapse: collapse;
}
/*
there is a bit of extra space being generated on the right side of the grid.
row seems to be causing the issue will need to review.
Checked the grid creation which seems to be fine.
*/
.row{
border:1px solid red;
height:1em;
width:25.25%;
overflow:hidden;
box-sizing: border-box;
}
.box{
width: 8.25%;
height: 1em;
border: 1px solid red;
overflow:hidden;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div id="container">
<div id="Btns">
<button id="recreate" onclick="resizeGrid(this.value)">remake grid</button>
</div>
<br />
</div>
<table id="table"></table>
<script src="script.js"></script>
</body>
</html>
Move the button to end of the page to make the first child selector work and apply this CSS
#container {
width: 50%;
height: 50%;
margin-top:50px;
margin-left: auto;
margin-right: auto;
background: "white";
overflow:hidden;
box-sizing: border-box;
}
.row{
line-height: 0;
}
.row:first-child .box{
border-top: 1px solid red;
}
.box{
display: inline-block;
width: 15px;
height: 15px;
border: 1px solid red;
box-sizing: border-box;
border-left: none;
border-top: none;
margin: 0;
}
.box:first-child{
border-left: 1px solid red;
}

Clickable grid with each <td> changing colors using onclick method

So I'm just learning how to make a clickable grid using Jquery and I have difficulty in finding how to make each block to change colors on click. I was attempting to add a class to each through the addClass method. My main difficulty is to find each to incorporate an onclick or changeColor method.
$('body').on('click', 'td', changeColor());
function generateGrid(rows, cols) {
var grid = "<table>";
for (row = 1; row <= rows; row++) {
grid += "<tr>";
for (col = 1; col <= cols; col++) {
var cell = "<td> </td>";
grid += cell;
}
grid += "</tr>";
}
$("#tableContainer").empty();
$("#tableContainer").append(grid);
return grid;
}
function changeColor() {
this.addClass("clicked");
}
body {
background-color: whitesmoke;
}
#tableContainer {
display: table;
padding: 1px;
margin-right: auto;
margin-left: auto;
}
td {
border: 1px solid;
width: 50px;
height: 50px;
padding: .5px;
background-color: skyblue;
display: table-cell;
align-items: center;
cursor: pointer;
}
td:hover {
display: block;
width: 100%;
background-color: grey;
}
.clicked {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<link rel="stylesheet" href="a3.css">
<script src="a3.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<body>
<!-- <input type = "button" id="bClick" onclick="myFunction()"> -->
Rows: <input type="number" name="Rows" id="Rows"><br> Columns: <input type="number" name="Columns" id="Columns"><br> Mines: <input type="number" name="mines"> <br><br>
<button onclick="generateGrid(document.getElementById('Rows').value, document.getElementById('Columns').value)"> Click for Grid </button>
<div id="tableContainer"></div>
</body>
</html>
You are executing the function you're passing as the event handler argument so remove the ().
$(document.body).on('click', 'td', changeColor);
Then you will be able to use this in the handler.
function changeColor() {
const $this = $(this);
if ($this.hasClass("clicked")) {
$this.removeClass("clicked")
} else {
$this.addClass("clicked");
}
}
$(document.body).on('click', 'td', changeColor);
function generateGrid(rows, cols) {
var grid = "<table>";
for (row = 1; row <= rows; row++) {
grid += "<tr>";
for (col = 1; col <= cols; col++) {
var cell = "<td> </td>";
grid += cell;
}
grid += "</tr>";
}
$("#tableContainer").empty();
$("#tableContainer").append(grid);
return grid;
}
function changeColor() {
const $this = $(this);
if ($this.hasClass("clicked")) {
$this.removeClass("clicked")
} else {
$this.addClass("clicked");
}
}
body {
background-color: whitesmoke;
}
#tableContainer {
display: table;
padding: 1px;
margin-right: auto;
margin-left: auto;
}
td {
border: 1px solid;
width: 50px;
height: 50px;
padding: .5px;
background-color: skyblue;
display: table-cell;
align-items: center;
cursor: pointer;
}
td:hover {
display: block;
width: 100%;
background-color: grey;
}
.clicked {
background-color: red;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="a3.css">
<script src="a3.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
</head>
<body>
<!-- <input type = "button" id="bClick" onclick="myFunction()"> -->
Rows: <input type="number" name="Rows" id="Rows"><br> Columns: <input type="number" name="Columns" id="Columns"><br> Mines: <input type="number" name="mines"> <br><br>
<button onclick="generateGrid(document.getElementById('Rows').value, document.getElementById('Columns').value)"> Click for Grid </button>
<div id="tableContainer"></div>
</body>
</html>
Your issue here is that you are binding the click event on the td before they are ever on the page. You need to make sure to bind the click function at the bottom of your generateGrid() function, like so:
function generateGrid(rows, cols) {
var grid = "<table>";
for (row = 1; row <= rows; row++) {
grid += "<tr>";
for (col = 1; col <= cols; col++) {
var cell = "<td> </td>";
grid += cell;
}
grid += "</tr>";
}
$("#tableContainer").empty();
$("#tableContainer").append(grid);
$('td').click(function(){
changeColor($(this));
});
}
function changeColor(cell) {
if(cell.hasClass('clicked')){
cell.removeClass('clicked');
} else {
cell.addClass('clicked');
}
}
body {
background-color: whitesmoke;
}
#tableContainer {
display: table;
padding: 1px;
margin-right: auto;
margin-left: auto;
}
td {
border: 1px solid;
width: 50px;
height: 50px;
padding: .5px;
background-color: skyblue;
display: table-cell;
align-items: center;
cursor: pointer;
}
td:hover {
display: block;
width: 100%;
background-color: grey;
}
td.clicked {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<link rel="stylesheet" href="a3.css">
<script src="a3.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<body>
<!-- <input type = "button" id="bClick" onclick="myFunction()"> -->
Rows: <input type="number" name="Rows" id="Rows"><br> Columns: <input type="number" name="Columns" id="Columns"><br> Mines: <input type="number" name="mines"> <br><br>
<button onclick="generateGrid(document.getElementById('Rows').value, document.getElementById('Columns').value)"> Click for Grid </button>
<div id="tableContainer"></div>
</body>
</html>

how to run javascript function 'live' without refresh?

im trying to make a average grade calculator, now thats is going fine but now i want to calculate the average immediately when a number gets inputted in one of the fields. I've been trying this with "on(), live(), onkeyup()" but can't get it to work.
The result of the average now displays beneath the inputfields 'onclick' on the button. I want the average displayed there but then as soon as you input numbers in one of the fields it should show there as it now does after the onclick.
What i've tryed with the 'on(), live(), onkeyup()' is to connect them to the input fields and connect them to the calculator() function.
Is there a easy way to do this or a other certain way?
greetings.
function calculator() {
var weight = 0;
var mark = 0;
var weights = document.querySelectorAll('[id^=weight-]');
var grades = document.querySelectorAll('[id^=mark-]');
var trs = document.getElementsByTagName('tr');
var tBody = document.getElementsByTagName('tbody')[0];
var totalWeight = 0;
var totalGrade = 0;
for (var i = 0; i < weights.length; i++) {
totalWeight += +weights[i].value;
}
for (var i = 0; i < grades.length; i++) {
totalGrade += +grades[i].value;
}
var finalGrade=totalGrade/totalWeight;
var display = document.getElementById('output-div');
var newTr = document.createElement('TR');
newTr.innerHTML = `<td><input id="weight-${trs.length + 1}" type="text" size=2 value=""></td><td><input id="mark-${trs.length + 1}" type="text" size=2 value=""></td>`;
tBody.appendChild(newTr);
display.innerHTML='Je gemiddelde is: ' +finalGrade.toFixed(2);
}
html {
background-color: ;
}
header {
background-color: ;
}
h2 {
text-align: center;
}
h3 {
text-align: center;
}
body {
font-family: 'Roboto', sans-serif;
}
table {
margin: auto;
}
tr {
background-color: ;
}
td {
background-color: ;
}
#table-title {
font-size: 20px;
font-style: italic;
text-align: center;
position: relative;
}
input {
text-align: center;
}
[id^="mark"] {
width: 100px;
}
[id^="weight"] {
width: 100px;
}
#calc-btn-div {
position: relative;
width: 150px;
margin: auto;
}
#calc-btn {
position: relative;
padding: 5px;
margin-top: 20px;
}
#calc-btn:hover {
border-color: black;
box-shadow: 8px 8px 8px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
}
/* #add-input-div {
height: 50px;
text-align: center;
width: 300px;
margin: auto;
margin-top: 20px;
}
#add-input-btn {
position: relative;
padding: 5px;
margin-top: 20px;
}
#add-input-btn:hover {
border-color: black;
box-shadow: 8px 8px 8px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
} */
#output-div {
background-color: ;
height: 50px;
text-align: center;
width: 300px;
margin: auto;
margin-top: 20px;
}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content/Box */
.modal-content {
background-color: #fefefe;
margin: 15% auto; /* 15% from the top and centered */
padding: 20px;
border: 1px solid #888;
width: 80%; /* Could be more or less, depending on screen size */
}
/* The Close Button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
</head>
<header>
<h2>Gemiddelde cijfer</h2>
<h3>Voer hieronder je cijfers in</h3>
</header>
<body>
<table id="table">
<tr id="table-title">
<td>Weging</td>
<td>Cijfer</td>
</tr>
<tr>
<td><input id="weight-1" type="text" size=2 value=""></td>
<td><input id="mark-1" type="text" size=2 value=""></td>
</tr>
</table>
<div id="calc-btn-div">
<input id="calc-btn" type="button" value="Berekenen je gemiddelde" onclick="calculator()">
</div>
<!-- <div id="add-input-div">
<input id="add-input-btn" type="button" value="Voeg cijfer toe" onclick="addInput()">
</div> -->
<div id="output-div"></div>
</body>
</html>
Using vanilla JavaScript I would attach an eventListener to the inputfields like this
document.getElementById('weight-1').addEventListener('change',function(){
calculator();
});
document.getElementById('mark-1').addEventListener('change',function(){
calculator();
});
These addEventListener functions adds listeners to the "input" field's predefined 'change'-events, and fires the calculator(); function from your code.
Seeing that you are using some sort of dynamic generation of the inputfields, you could add the listeners to your inputfields using the same querySelector that you use to target them during calculation. It would mean replacing getElementById('weight-1') in my example above with querySelectorAll('[id^=weight-]') for the weight-fields.
Also, doing work with values, IO, and calculation between html and JavaScript, I would suggest using a library like jQuery. jQuery simplifies these processes a lot.
This is the documentation for the jQuery alternative onClick function:
https://api.jquery.com/change/
I think you could do that with an angularJS module. Take a look at this tutorial : https://www.w3schools.com/angular/angular_modules.asp
maybe it will help.

Creating a grid using for loops jquery

I am trying to create a 16x16 grid using jquery. I have a main div, and then I'm trying to create the grid within it. I am using for loops, but when the code below runs, I get a 16x32 grid.
Could anyone explain what is going on and why that is happening?
<html>
<head>
<title>etch-a-sketch</title>
<link type="text/css" rel="stylesheet" href="stylesheet.css"/>
</head>
<body>
<div id=main>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type='text/javascript' src='app.js'></script>
</body>
#main {
height: 192px;
width: 192px;
background-color: antiquewhite;
}
.squares {
height: 10px;
width: 10px;
margin: 1px;
background-color: aquamarine;
display: inline-block;
}
$(document).ready(function() {
for(var x = 0; x < 16; x++) {
for(var y=0; y<16; y++) {
$("<div class='squares'></div>").appendTo('#main');
}
}
});
You get a 16x16 grid. When you're using "inline", spaces take place. Just change the CSS code to this:
#main {
height: 192px;
width: 192px;
background-color: antiquewhite;
}
.squares {
height: 10px;
width: 10px;
margin: 1px;
background-color: aquamarine;
display: block;
float: left;
}
Note:
display: block;
float: left;
I think your thought process was off.. I think the best way to make a 16x16 grid (256 boxes total) would be the way I went below and use css to style them.
The HTML
<div id="main">
</div>
The CSS
#main {
width: 100%;
}
.squares {
width:6%;
height: 50px;
border: 1px solid red;
display:inline-block;
}
The Javascript
for(var x = 0; x < 256; x++) {
$("<div class='squares'>hi</div>").appendTo('#main');
}

Issues about grouping and appending div

[EDIT] I tried to dynamically create 6 horizontal lines every 1 second using setTimeout method. So it should shows every 6 horizontal lines as a group for every 1 second. Here, I call 6 horizontal lines as group. However, I want to append each group horizontally rather than vertically. When trying to append a group and the width of the border is not long enough to hold a new group, append the new group to next lines. And also I want a "pilar" between each grounp of 6 horizontal lines, and I only want to create 8 group of horizontal lines. The first picture below is what I get after running my code. The second one is what I need. The code below is my html, css, and js code. Hope someone could help me out. Thank you in advance.
html:
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="code.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script type="text/javascript" src="code_js.js"></script>
</head>
<body>
<div id = "output">
</div>
</body>
</html>
css:
.deco {
border-bottom: 1px solid black;
width: 120px;
margin-left:0px;
margin-bottom:10px;
z-index: 2;
position: relative;
/*display: inline-block;*/
margin-right: 20px;
}
#output {
background: #ffe6e6;
width: 600px;
height: 800px;
position:absolute;
}
js:
$(document).ready(function() {
makeItHappen(0);
});
function makeItHappen(order) {
for (var i = 0; i < 7; i++) {
var hr = document.createElement('hr');
hr.className = "deco"
hr.id = "hr" + i;
$('#output').append(hr);
}
makeTable(function() {
if(++order < 7) {
makeItHappen(order);
}
});
}
function makeTable(callback) {
setTimeout(function() {
callback();
}, 1000);
}
You can use display:flex to get the output you are expecting
$(document).ready(function() {
makeItHappen(0);
});
function makeItHappen(order) {
var output = $("#output");
var div = $("<div></div>");
div.attr('id', order);
for (var i = 0; i < 7; i++) {
var hr = document.createElement('hr');
hr.className = "deco"
hr.id = "hr" + i;
$(div).append(hr);
}
output.append(div);
makeTable(function() {
if (++order < 7) {
makeItHappen(order);
}
});
}
function makeTable(callback) {
setTimeout(function() {
callback();
}, 1000);
}
.deco {
border-bottom: 1px solid black;
width: 120px;
margin-left: 0px;
margin-bottom: 10px;
z-index: 2;
position: relative;
/*display: inline-block;*/
margin-left: 10px;
}
#output div:nth-child(2n+1) {
border-right: 5px solid green;
margin-top: 5px;
}
#output div:nth-child(2n) {
border-right: 5px solid green;
margin-top: 5px;
height: auto;
}
#output {
display: flex;
flex-wrap: wrap;
}
#output {
background: #ffe6e6;
width: 500px;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output">
</div>
Hope it helps

Categories

Resources