How to put an object within a canvas using onclick? - javascript

This website's purpose is to display maps using buttons, and then have the user click on a country to visit a website via invisible <a> tags. This is achieved by creating a canvas that becomes unhidden onclick and changing the canvas background according to the button. The end goal is to have the <a> tags appear when its corresponding button is clicked and then disappear when another button is pressed. However, when the button is pressed, the <a> tags spawn above the canvas and not in it.
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Map</title>
<link rel="stylesheet" href="style.css">
<script src="map.js"></script>
</head>
<body>
<h1>Where do you wanna go?</h1>
<table>
<!--North America-->
<tr><td><button id="nA" onclick="northAmerica()">North America</button></tr></td>
<td><button id="nA2" onclick="nNorthAmerica()">Northern North America</button></td>
<td><button id="nA4" onclick="cenAmerica()">Central America</button></td>
HELLO
hello
<td><canvas class="map" id="c"></canvas></td>
</table>
map.js
//NORTH AMERICA
function northAmerica(){
let nA2 = document.getElementById("nA2");
let nA3 = document.getElementById("nA3");
let nA4 = document.getElementById("nA4");
let x = document.getElementById("x");
let y = document.getElementById("y");
nA2.style.display = "block";
nA3.style.display = "block";
nA4.style.display = "block";
var c = document.getElementById("c");
c.style.display="block";
}
function nNorthAmerica(){
c.style.backgroundImage = "url('https://i.imgur.com/ipPrjz1.jpg')";
c.style.backgroundSize = "65em 45em";
c.style.display="block";
x.style.display = "block";
}
function cenAmerica(){
c.style.backgroundImage = "url('https://i.imgur.com/84LVJaY.gif')";
c.style.backgroundSize = "65em 45em";
y.style.display = "block";
}
/*The purpose of this block is to hide the elements until they are called upon*/
#nA2, #nA3, #nA4, #c, #x, #y{
display:none;
}
button{
width:10em;
height:5em;
font:sans-serif;
}
.map{
width:65em;
height:35em;
}
I expect that function nNorthAmerica spawns the element x onto the page since by default it is hidden, and same for cenAmerica and y. However, I do not know how to have the <a> tags appear within the canvas.

I assume you want to overlay the links - HELLO & hello - on top of the canvas?
This can be done by wrapping the canvas and the a elements in a div. If you then set the position attribute af the canvas to relative and the a elements absolute it's origin will be the top-left corner of the canvas.
Here's an example:
function northAmerica() {
let nA2 = document.getElementById("nA2");
let nA3 = document.getElementById("nA3");
let nA4 = document.getElementById("nA4");
let x = document.getElementById("x");
let y = document.getElementById("y");
nA2.style.display = "block";
nA3.style.display = "block";
nA4.style.display = "block";
var c = document.getElementById("c");
c.style.display = "block";
}
function nNorthAmerica() {
c.style.backgroundImage = "url('https://i.imgur.com/ipPrjz1.jpg')";
c.style.backgroundSize = "65em 45em";
c.style.display = "block";
x.style.display = "block";
}
function cenAmerica() {
c.style.backgroundImage = "url('https://i.imgur.com/84LVJaY.gif')";
c.style.backgroundSize = "65em 45em";
y.style.display = "block";
}
#nA2,
#nA3,
#nA4,
#c,
#x,
#y {
display: none;
position: absolute;
}
button {
width: 10em;
height: 5em;
font: sans-serif;
}
.map {
width: 65em;
height: 35em;
position: relative;
}
<table>
<tr>
<td><button id="nA" onclick="northAmerica()">North America</button></tr>
</td>
<td><button id="nA2" onclick="nNorthAmerica()">Northern North America</button></td>
<td><button id="nA4" onclick="cenAmerica()">Central America</button></td>
</table>
<div><canvas class="map" id="c"></canvas>
HELLO
hello</div>

Related

Weird bug occurring for Event listeners( I think)

Whenever I click either 'Reset', 'Color Black', or 'Erase' randomly the entire grid will color in black. If that happens and I click Erase I can clear them off and then sometimes randomly the excess black that was randomly created will disappear. Not really sure what the issue is. I THINK it may be an issue with how the Event Listeners are set up, but this is the only configuration of them that gets the buttons to work. Any ideas what the issue might be?
let blackBtn = document.querySelector('#black');
let eraseBtn = document.querySelector('#eraser');
let resetBtn = document.querySelector('#reset');
let resize = document.querySelector('.resize');
let value = 16; // For default 16x16 grid size
//Create grid
function createGrid(size = value) {
grid.style["grid-template-rows"] = `repeat(${size}, 1fr)`;
grid.style["grid-template-columns"] = `repeat(${size}, 1fr)`;
for (let i = 0; i < size * size; i++) {
const block = document.createElement('div');
block.className = 'block';
grid.appendChild(block);
}
grid.addEventListener("mouseover", colorBlack);
resize.addEventListener("click", resizeGrid);
resetBtn.addEventListener("click", clearGrid);
eraseBtn.addEventListener("click", eraseColor);
blackBtn.addEventListener("click", blackPaint);
}
//Resize the grid
function resizeGrid() {
const newSize = parseInt(prompt("New Size: ", 16));
grid.innerHTML = '';
resize.removeEventListener("click", resizeGrid);
grid.removeEventListener("mouseover", colorBlack);
createGrid(newSize);
}
//Fill in background color of black
function colorBlack(e) {
if (e.target.className !== "block") return false;
e.target.style.backgroundColor = 'black';
}
//Clear background color from grid
function clearGrid(size, newSize) {
grid.innerHTML = '';
resize.removeEventListener("click", resizeGrid);
grid.removeEventListener("mouseover", colorBlack);
createGrid();
}
//Colors divs black after clicking 'Color Black'
function blackPaint(e) {
grid.removeEventListener("mouseover", eraseColor);
grid.addEventListener("mouseover", (e) => {
e.target.style.backgroundColor = 'black';
})
}
//Colors over black divs with white to 'erase' it
function eraseColor(e) {
grid.removeEventListener("mouseover", colorBlack);
grid.addEventListener("mouseover", (e) => {
e.target.style.backgroundColor = 'white';
})
}
createGrid();
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
#grid {
width: 20rem;
height: 20rem;
border: 1px solid #333;
display: grid;
flex-wrap: grid;
}
.block {
border: 1px solid black;
}
<!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>Etch-A-Sketch</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<p>Etch-A-Sketch</p>
</header>
<div class="gameBoard">
<div id="actions">
<button class="resize">Resize</button>
<button id="reset">Reset</button>
<button id="black">Color Black</button>
<button id="eraser">Eraser</button>
</div>
<div id='grid'></div>
<div class="block"></div>
</div>
<script src="script.js"></script>
</body>
</html>
When you click on Black or Erase, you add event listeners that call anonymous functions. These can't be removed with removeEventListener() when you switch modes. So these old event listeners continue to run, erasing and filling in elements.
You should have two functions, colorBlack() and colorWhite(), and switch between them in the mouseover event listener. Also, when you reset or resize, you should go back to black.
The problem with Clear is that it calls createGrid(), which adds all the event listeners again. You remove some of the old listeners before you call it, but not all, so you get duplication. You should separate creating the grid and adding the event listeners, so you don't repeat the listeners, and then you wouldn't need to remove them.
let blackBtn = document.querySelector('#black');
let eraseBtn = document.querySelector('#eraser');
let resetBtn = document.querySelector('#reset');
let resize = document.querySelector('.resize');
let value = 16; // For default 16x16 grid size
//Create grid
function createGrid(size = value) {
grid.style["grid-template-rows"] = `repeat(${size}, 1fr)`;
grid.style["grid-template-columns"] = `repeat(${size}, 1fr)`;
for (let i = 0; i < size * size; i++) {
const block = document.createElement('div');
block.className = 'block';
grid.appendChild(block);
}
}
function addListeners() {
grid.addEventListener("mouseover", colorBlack);
resize.addEventListener("click", resizeGrid);
resetBtn.addEventListener("click", clearGrid);
eraseBtn.addEventListener("click", eraseColor);
blackBtn.addEventListener("click", blackPaint);
}
//Resize the grid
function resizeGrid() {
const newSize = parseInt(prompt("New Size: ", 16));
grid.innerHTML = '';
createGrid(newSize);
blackPaint();
}
//Fill in background color of black
function colorBlack(e) {
if (e.target.className !== "block") return false;
e.target.style.backgroundColor = 'black';
}
//Fill in background color of white
function colorWhite(e) {
if (e.target.className !== "block") return false;
e.target.style.backgroundColor = 'white';
}
//Clear background color from grid
function clearGrid(size, newSize) {
grid.innerHTML = '';
createGrid();
blackPaint();
}
//Colors divs black after clicking 'Color Black'
function blackPaint(e) {
grid.removeEventListener("mouseover", colorWhite);
grid.addEventListener("mouseover", colorBlack);
}
//Colors over black divs with white to 'erase' it
function eraseColor(e) {
grid.removeEventListener("mouseover", colorBlack);
grid.addEventListener("mouseover", colorWhite);
}
createGrid();
addListeners();
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
#grid {
width: 20rem;
height: 20rem;
border: 1px solid #333;
display: grid;
flex-wrap: grid;
}
.block {
border: 1px solid black;
}
<!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>Etch-A-Sketch</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<p>Etch-A-Sketch</p>
</header>
<div class="gameBoard">
<div id="actions">
<button class="resize">Resize</button>
<button id="reset">Reset</button>
<button id="black">Color Black</button>
<button id="eraser">Eraser</button>
</div>
<div id='grid'></div>
<div class="block"></div>
</div>
<script src="script.js"></script>
</body>
</html>

Unable to set div's background to linear gradient using Javascript

I'm trying to make a dynamic div element with styles including linear gradient. It should be displayed dynamically with a button, but the gradient does not get added.
var x = document.getElementById("btn");
x.addEventListener("click", addbox);
function addbox() {
var y = document.createElement("Div");
y.id = "div1";
y.style.border = "1px";
y.style.borderRadius = "20px";
y.style.height = "200px";
y.style.width = "500px";
y.style.backgroundImage = "linearGradient(to bottom right, yellow , cyan)";
document.getElementsByTagName("body")[0].appendChild(y);
}
#btn {
height: 50px;
width: 150px;
}
<button id="btn" onclick="addbox()"> CLICK ME TO DISPLAY </button>
Your code has a lot of little mistakes but here is something that works:
<!doctype html>
<html>
<head>
<title> ADD BOX ON CLICK FUNCTION </title>
<style>
#btn {
height: 50px;
width: 150px;
}
</style>
</head>
<body>
<script>
function addbox() {
var y = document.createElement("Div");
y.id = "div1";
y.style.border = "1px";
y.style.borderRadius = "20px";
y.style.height = "200px";
y.style.width = "500px";
y.style.background = "linear-gradient(to bottom right, yellow , cyan)";
document.getElementsByTagName("body")[0].appendChild(y);
}
window.addEventListener("DOMContentLoaded", (event) => {
var x = document.getElementById("btn");
x.addEventListener("click", addbox);
});
</script>
<button id="btn"> CLICK ME TO DISPLAY </button>
</body>
</html>
Your document.getElementById("btn") cannot work before the page has finished loading, so you have to put this inside a window.addEventListener("DOMContentLoaded") event that will fire only when your div is there
Remove the onclick="addbox()" from the div because it would fire twice per click
linearGradient spelling is wrong. It's linear-gradient
The property to apply the linear gradient is not y.style.backgroundImage but y.style.background

How to Hide and then Show on Click Multiple Content Items by Default?

I have the following code. By default it shows, but I want to hide it by default.
Also, I'm unable to control both of the divs, only 1 of the show/hide toggles work, I want for them (but have been unsuccessful) both to work.
How can I hide by default and expand on click?
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
#myDIV {
width: 100%;
padding: 50px 0;
text-align: center;
background-color: lightblue;
margin-top: 20px;
}
</style>
</head>
<body>
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<button onclick="myFunction()">Try it</button>
<div id="myDIV">
This is my DIV element.
</div>
<br><br>
<button onclick="myFunction()">Try it 2</button>
<div id="myDIV2">
This is my DIV element.
</div>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>
<script>
function myFunction() {
var x = document.getElementById("myDIV");
var x = document.getElementById("myDIV2");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
</body>
</html>
var x = document.getElementById("myDIV");
var x = document.getElementById("myDIV2");
You are overwriting your x variable.
Assign myDIV2 to another variable like y and repeat the process.
Better would be to just assign the same class instead of id to the elements you want to hide and just toggle the class instead of trying to get each element by id.
https://ultimatecourses.com/blog/javascript-hasclass-addclass-removeclass-toggleclass
Just separate the function on the first and scond button
function myFunction_1() {
var x = document.getElementById("myDIV");
var y = document.getElementById("myDIV2");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
function myFunction_2() {
var y = document.getElementById("myDIV2");
if (y.style.display === "none") {
y.style.display = "block";
} else {
y.style.display = "none";
}
}
#myDIV {
width: 100%;
padding: 50px 0;
text-align: center;
background-color: lightblue;
margin-top: 20px;
}
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<button onclick="myFunction_1()">Try it</button>
<div id="myDIV">
This is my DIV element.
</div>
<br><br>
<button onclick="myFunction_2()">Try it 2</button>
<div id="myDIV2">
This is my DIV element.
</div>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>

JavaScript/HTML Page Refresh Alert

I'm trying to make an alert in JavaScript which warns the user that they probably shouldn't reload the page. But I want them to be able to navigate to other pages without an alert, just not refresh the current page. I have found some alerts but they either provide alerts in both cases, or provide an alert and refresh the page anyway. I want the user to be warned and then be able to stop the page from refreshing. I guess it means that they also shouldn't be able to go back to the page once they have left it?
<body onunload="window.alert('Hello!');">
You can use onbeforeunload and set a variable as follows:
var l=false;
window.onbeforeunload = function() {
if (!l) {
return "you shouldn't leave";
}
}
Leave
(This doesn't work on Run Snippet because it's in an iframe)
This you may find useful. In conjunction With above code;;;
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
#dialogoverlay{
display: none;
opacity: .8;
position: fixed;
top: 0px;
left: 0px;
background: #FFF;
width: 100%;
z-index: 10;
}
#dialogbox{
display: none;
position: fixed;
background: #000;
border-radius:7px;
width:550px;
z-index: 10;
}
#dialogbox > div{ background:#FFF; margin:8px; }
#dialogbox > div > #dialogboxhead{ background: #666; font-size:19px; padding:10px; color:#CCC; }
#dialogbox > div > #dialogboxbody{ background: #333; padding:20px; color:#FFF; }
#dialogbox > div > #dialogboxfoot{ background: #666; padding:10px; text-align:right; }
</style>
<script>
function CustomAlert(){
this.render = function(dialog){
var winW = window.innerWidth;
var winH = window.innerHeight;
var dialogoverlay = document.getElementById('dialogoverlay');
var dialogbox = document.getElementById('dialogbox');
dialogoverlay.style.display = "block";
dialogoverlay.style.height = winH+"px";
dialogbox.style.left = (winW/2) - (550 * .5)+"px";
dialogbox.style.top = "100px";
dialogbox.style.display = "block";
document.getElementById('dialogboxhead').innerHTML = "Acknowledge This Message";
document.getElementById('dialogboxbody').innerHTML = dialog;
document.getElementById('dialogboxfoot').innerHTML = '<button onclick="Alert.ok()">OK</button>';
}
this.ok = function(){
document.getElementById('dialogbox').style.display = "none";
document.getElementById('dialogoverlay').style.display = "none";
}
}
var Alert = new CustomAlert();
function deletePost(id){
var db_id = id.replace("post_", "");
// Run Ajax request here to delete post from database
document.body.removeChild(document.getElementById(id));
}
function CustomConfirm(){
this.render = function(dialog,op,id){
var winW = window.innerWidth;
var winH = window.innerHeight;
var dialogoverlay = document.getElementById('dialogoverlay');
var dialogbox = document.getElementById('dialogbox');
dialogoverlay.style.display = "block";
dialogoverlay.style.height = winH+"px";
dialogbox.style.left = (winW/2) - (550 * .5)+"px";
dialogbox.style.top = "100px";
dialogbox.style.display = "block";
document.getElementById('dialogboxhead').innerHTML = "Confirm that action";
document.getElementById('dialogboxbody').innerHTML = dialog;
document.getElementById('dialogboxfoot').innerHTML = '<button onclick="Confirm.yes(\''+op+'\',\''+id+'\')">Yes</button> <button onclick="Confirm.no()">No</button>';
}
this.no = function(){
document.getElementById('dialogbox').style.display = "none";
document.getElementById('dialogoverlay').style.display = "none";
}
this.yes = function(op,id){
if(op == "delete_post"){
deletePost(id);
}
document.getElementById('dialogbox').style.display = "none";
document.getElementById('dialogoverlay').style.display = "none";
}
}
var Confirm = new CustomConfirm();
</script>
</head>
<body>
<div id="dialogoverlay"></div>
<div id="dialogbox">
<div>
<div id="dialogboxhead"></div>
<div id="dialogboxbody"></div>
<div id="dialogboxfoot"></div>
</div>
</div>
<p id="post_1">
Today is a lovely day ...
<button onclick="Confirm.render('Delete Post?','delete_post','post_1')">Delete</button>
</p>
<p id="post_2">
I like pickles ...
<button onclick="Confirm.render('Delete Post?','delete_post','post_2')">Delete</button>
</p>
<button onclick="Alert.render('Hello World')">Custom Alert</button>
</body>
</html>
This allows you to give Custom alerts.
Explination of the code here: Alert Box

javascript not rendering styles

I dont know why this code is not working!
html, css, javascript is not working in same html page
plz help I cant figure out this.. is it problem on browser or my code is wrong
every thing seems to be fine...
function render() {
var winW = window.innerWidth;
var winH = window.innerHeight;
alert('hello');
var overlay = document.getElementsByClassName('overlay');
var alert = document.getElementsByClassName('alertbox');
overlay.style.display = 'block';
overlay.style.background = 'blue';
overlay.style.height = winH + 'px';
overlay.style.width = winW + 'px';
overlay.style.border = '10px solid black';
}
.overlay{
display: none;
opacity: 0.8;
position: fixed;
background: #ccc;
z-index: 10;
width: 100%;
height:100%;
}
.alertbox{
display: none;
position: fixed;
background: magenta;
z-index: 10;
border-radius: 8px;
width: 500px;
}
<html>
<head>
<title></title>
</head>
<body>
<h3>Custom Alert Box Demo</h3>
<button type="button" onclick="alert('hello world')">render overlay</button>
<button type="button" onclick="render()">render overlay</button>
<div class="overlay"></div>
<div class="alertbox">
<div class="head"></div>
<div class="body"></div>
<div class="foot"></div>
</div>
</body>
</html>
See this fiddle
Your script has two errors. Please replace your script with the below given one
function render() {
var winW = window.innerWidth;
var winH = window.innerHeight;
var overlay = document.getElementsByClassName('overlay')[0];
var alert = document.getElementsByClassName('alertbox')[0];
overlay.style.display = 'block';
overlay.style.background = 'blue';
overlay.style.height = winH + 'px';
overlay.style.width = winW + 'px';
overlay.style.border = '10px solid black';
}
First error was in the line,
alert('hello');
because, you have a variable with name alert in your script and thus you will get an error alert is not a function in your console. If you want the alert to be shown, then you should rename your variable with name alert to some other name, may be for eg, rename it to alert1. Please see the fiddle.
Second error was in the line
var overlay = document.getElementsByClassName('overlay');
because document.getElementsByClassName() always returns an array.
According to the docs
getElementsByClassName() Returns an array-like object of all child elements which have all of
the given class names. When called on the document object, the
complete document is searched, including the root node. You may also
call getElementsByClassName() on any element; it will return only
elements which are descendants of the specified root element with the
given class names.
What I have done in the fiddle is that, I've selected the first element with the class name overlay using the index position 0. Similarly for the class alertbox.

Categories