I'd like to call a function that toggles on a node list of elements with the same class. I basically need to add the function within the if else statement, but the different variants of this seem to throw an error. When I put the code that is inside the two functions directly into the if else statement it works, but I want to do it with functions because this is a simplified version of what will be more complex style changes.
Codepen is here:https://codepen.io/emilychews/pen/GEEpqW?editors=1111
Code is below:
JS
var $mainMenuButton = document.getElementsByClassName('desktopmenubutton');
function newColor() {
e.currentTarget.style.background = "black";
}
function originalColor() {
e.currentTarget.style.background = "red";
}
for (h = 0; h < $mainMenuButton.length; h +=1) {
$mainMenuButton[h].addEventListener('click', function(e) {
if (e.currentTarget.style.backgroundColor === "red") {
newColor();
} else {
originalColor();
}
});
}
CSS
* {font-family: arial;}
.desktopmenubutton {
width: 150px;
height: 100px;
background-color: red;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
color: white
}
.button2 {
left: 300px;
}
HTML
<div class="desktopmenubutton button1">Button 1</div>
<div class="desktopmenubutton button2">Button 2</div>
Pass the element in the function that is inside the if statement.
var $mainMenuButton = document.getElementsByClassName('desktopmenubutton button1');
function newColor(element) {
element.currentTarget.style.backgroundColor = "black";
}
function originalColor(element) {
element.currentTarget.style.backgroundColor = "red";
}
for (h = 0; h < $mainMenuButton.length; h +=1) {
$mainMenuButton[h].addEventListener('click', function(e) {
if (e.currentTarget.style.backgroundColor === "red") {
newColor(e);
} else {
originalColor(e);
}
});
}
You forget to receive the event as a parameter on newColor and originalColor.
var $mainMenuButton =
document.getElementsByClassName('desktopmenubutton');
function newColor(e) {
e.currentTarget.style.background = "black";
}
function originalColor(e) {
e.currentTarget.style.background = "red";
}
for (h = 0; h < $mainMenuButton.length; h +=1) {
$mainMenuButton[h].addEventListener('click', function(e) {
if (e.currentTarget.style.backgroundColor === "red") {
newColor(e);
} else {
originalColor(e);
}
});
}
This should work.
You are not passing e(event) argument
Also note that Element.style.* reads inline css styles, not those styles which are assigned in CSS file/tag.
You could set red color initially in loop so that it could be accessed using Element.style.* property.
var $mainMenuButton = document.getElementsByClassName('desktopmenubutton');
function newColor(e) {
e.currentTarget.style.background = "black";
}
function originalColor(e) {
e.currentTarget.style.background = "red";
}
for (h = 0; h < $mainMenuButton.length; h += 1) {
$mainMenuButton[h].style.background = 'red';
$mainMenuButton[h].addEventListener('click', function(e) {
if (e.currentTarget.style.background == 'red') {
newColor(e);
} else {
originalColor(e);
}
});
}
* {
font-family: arial;
}
.desktopmenubutton {
width: 150px;
height: 100px;
background-color: red;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
color: white
}
.button2 {
left: 300px;
}
<div class="desktopmenubutton button1">Button 1</div>
<div class="desktopmenubutton button2">Button 2</div>
Related
I'm currently doing the etch-a-sketch project of The Odin Project curriculum.
I have this event that when i click and mouseover the div, changue the background color, but I don't know how to remove this event when i release the click.
I tried using removeEventListener, tried using mouseup event but I can't figure out how to make this work.
I want to click and mouseover to draw and when i release the click stop the mouseover and stop to draw.
Another thing is that when I click in some div, this div do not change the background color immediately unless I move to another one on his side, then this other change the color.
Here is my code.
The HTML <body> only have a <div> with "grid-container" Id
JavaScript:
const divCont = document.getElementById("grid-container");
for (i = 1; i<=16; i++) {
let divCol = document.createElement('div')
divCol.classList.add("grid");
for ( j = 1; j<=16; j++){
let divRow = document.createElement('div');
divRow.classList.add("secGrid");
divCol.appendChild(divRow);
}
divCont.appendChild(divCol);
}
const hoverDivs = [...document.querySelectorAll('.secGrid')];
function colorChange(){
hoverDivs.forEach(hoverDiv => {
hoverDiv.addEventListener('click', () => {
hoverDivs.forEach(hoverDiv => {
hoverDiv.addEventListener('mouseover', () => {
hoverDiv.style.backgroundColor = "black"
});
});
});
});
}
colorChange();
CSS:
* body {
box-sizing: border-box;
padding: 0;
margin: 0;
}
#container {
max-width: fit-content;
margin: auto;
}
#grid-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width:100vh;
max-width:100%;
height:100vh;
max-height:100%;
position:relative;
background:red;
background-color: black;
}
.grid {
display: flex;
flex-direction: column;
flex-wrap: wrap;
flex-basis: 100%;
background-color: blue;
}
.secGrid {
background-color: yellow;
flex-basis: 100%;
}
I already have a solution.
I set a variable that says if it's onmousedown or not (changeColor). So if changeColor is true, onmouseover is active, if not, isn't active.
const divCont = document.getElementById("grid-container");
for (i = 1; i<=16; i++) {
let divCol = document.createElement('div')
divCol.classList.add("grid");
for ( j = 1; j<=16; j++){
let divRow = document.createElement('div');
divRow.classList.add("secGrid");
divCol.appendChild(divRow);
}
divCont.appendChild(divCol);
}
const hoverDivs = [...document.querySelectorAll('.secGrid')];
let changeColor = false;
hoverDivs.forEach(hoverDiv => {
hoverDiv.addEventListener('mousedown', () => {
hoverDiv.style.backgroundColor = "black"
changeColor=true;
});
hoverDiv.addEventListener('mouseup', () => {
changeColor=false;
});
hoverDiv.addEventListener('mouseover', () => {
if(changeColor){
hoverDiv.style.backgroundColor = "black";
}
});
});
Here, I have code a program that revolves the targeted div in a rectangular path using CSS positions properties in setInterval() method.
Firstly, the div indeed moves rightwards (using left CSS property) and then downwards (using top CSS property) but when the thirds step comes it doesn't move leftwards (using CSS right property). Why is that so?
let a = 0;
let node = document.querySelector(".node");
let inter1 = setInterval(function() {
if (a == 260) {
clearInterval(inter1);
a = 0;
let inter2 = setInterval(function() {
if (a == 639) {
clearInterval(inter2);
a = 260;
let inter3 = setInterval(function() {
if (a == 0) {
clearInterval(inter3);
} else {
a -= 1;
node.style.right = a + "px";
}
}, 1)
} else {
a += 1;
node.style.top = a + "px";
}
}, 1)
} else {
a += 1;
node.style.left = a + "px";
}
}, 1)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: serif;
}
body {
background: black;
color: white;
width: 100vw;
}
.node {
background: dodgerblue;
color: white;
display: inline-block;
width: 100px;
height: 100px;
position: absolute;
}
<div class="node"></div>
Like the user #JavaScript wrote, you should decide for one - left or right.
Therefor you could change right to left in the inter3 statement:
let inter3 = setInterval(function() {
if (a == 0) {
clearInterval(inter3);
} else {
a -= 1;
node.style.left = a + "px";
}
}, 1);
let a = 0;
let node = document.querySelector(".node");
let inter1 = setInterval(function() {
if (a == 260) {
clearInterval(inter1);
a = 0;
let inter2 = setInterval(function() {
if (a == 639) {
clearInterval(inter2);
a = 260;
let inter3 = setInterval(function() {
if (a == 0) {
clearInterval(inter3);
} else {
a -= 1;
node.style.left = a + "px";
}
}, 1)
} else {
a += 1;
node.style.top = a + "px";
}
}, 1)
} else {
a += 1;
node.style.left = a + "px";
}
}, 1)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: serif;
}
body {
background: black;
color: white;
width: 100vw;
}
.node {
background: dodgerblue;
color: white;
display: inline-block;
width: 100px;
height: 100px;
position: absolute;
}
<div class="node"></div>
When we click this add button we will add a new cube which will drop immediately, but if we click it very quickly, there will be too many cubes dropping. I want to limit the number of the total animated dropping cube.
For example, even if we click the button very quickly and 10 cubes are added to the page, only two cubes are dropping, and others must wait until they finished.
For example, the 3rd and 4th cubes will start to drop when cube 1 and cube 2 finished.
I was thinking maybe we can have a global variable of the total animated cubes count, ++ and -- it when a new cube is starting and finishing animation, use setInterval to check if the variable is less than 2, but this can't make the animation based on the cubes created order. May I know how to solve this? Thank you so much!
var btn = document.getElementById('add');
var container = document.getElementById('cubes-container');
var cubeId = 0;
btn.addEventListener('click', addCube);
var currentAnimateCount = 0;
function dropCube(cube) {
var pos = 0;
let intervalId = setInterval(function() {
if (pos == 200) {
clearInterval(intervalId);
} else {
pos++;
cube.style.top = pos + "px";
}
}, 1);
}
function addCube() {
let cube = document.createElement('div');
let cubeContainer = document.createElement('div');
cube.className = 'cube';
cube.id = cubeId;
cube.innerHTML = cube.id;
cubeId++;
cubeContainer.className = 'cube-container';
cubeContainer.append(cube);
container.append(cubeContainer);
let pos = 0;
dropCube(cube)
}
#cubes-container {
display: grid;
grid-template-columns: repeat(10, 1fr);
}
.cube-container {
position: relative;
height: 30px;
}
.cube {
width: 30px;
height: 30px;
background-color: orange;
text-align: center;
display: grid;
align-items: center;
justify-items: center;
position: absolute;
}
<button id="add">add new</button>
<div id="cubes-container">
</div>
Consider the following example. It is using jQuery versus JavaScript. It could be similarly scripted.
$(function() {
function addCube(target) {
var i = $(".cube").length;
var container = $("<div>", {
class: "cube-container"
}).appendTo(target);
$("<div>", {
class: "cube",
id: "cube-" + i
}).html(i).appendTo(container);
return container;
}
function dropCube(cube) {
$(cube).addClass("falling").animate({
top: "200px"
}, 2000, function() {
$(cube).removeClass("falling");
if (cubes.length && $(".falling").length < 2) {
dropCube(cubes.shift());
}
});
}
var cubes = [];
$("#add").click(function() {
cubes.push(addCube("#cubes-container"));
if ($(".falling").length < 2) {
dropCube(cubes.shift());
}
});
});
/*
var btn = document.getElementById('add');
var container = document.getElementById('cubes-container');
var cubeId = 0;
btn.addEventListener('click', addCube);
var currentAnimateCount = 0;
function dropCube(cube) {
var pos = 0;
let intervalId = setInterval(function() {
if (pos == 200) {
clearInterval(intervalId);
} else {
pos++;
cube.style.top = pos + "px";
}
}, 1);
}
function addCube() {
let cube = document.createElement('div');
let cubeContainer = document.createElement('div');
cube.className = 'cube';
cube.id = cubeId;
cube.innerHTML = cube.id;
cubeId++;
cubeContainer.className = 'cube-container';
cubeContainer.append(cube);
container.append(cubeContainer);
let pos = 0;
dropCube(cube)
}
*/
#cubes-container {
display: grid;
grid-template-columns: repeat(10, 1fr);
}
.cube-container {
position: relative;
height: 30px;
}
.cube {
width: 30px;
height: 30px;
background-color: orange;
text-align: center;
display: grid;
align-items: center;
justify-items: center;
position: absolute;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="add">add new</button>
<div id="cubes-container"></div>
Using an Array, you cna .shift() the first item of the array. Also adding a Class to the falling items allows you to keep a count of which ones are falling. I like to use Animate since it allows for a callback when the animation is done, so you can check for the next item.
Update for JavaScript
var btn = document.getElementById('add');
var container = document.getElementById('cubes-container');
var cubes = [];
btn.addEventListener('click', function(event) {
cubes.push(addCube());
if (document.getElementsByClassName("falling").length < 2) {
dropCube(cubes.shift());
}
});
function dropCube(cube) {
var pos = 0;
cube.classList.add("falling");
var intervalId = setInterval(function() {
if (pos == 200) {
clearInterval(intervalId);
cube.classList.remove("falling");
if (document.getElementsByClassName("falling").length < 2 && cubes.length) {
dropCube(cubes.shift());
}
} else {
pos++;
cube.style.top = pos + "px";
}
}, 1);
}
function addCube() {
let cube = document.createElement('div');
let cubeContainer = document.createElement('div');
cube.className = 'cube';
cube.id = document.getElementsByClassName("cube").length;
cube.innerHTML = cube.id;
cubeContainer.className = 'cube-container';
cubeContainer.append(cube);
container.append(cubeContainer);
return cubeContainer;
}
#cubes-container {
display: grid;
grid-template-columns: repeat(10, 1fr);
}
.cube-container {
position: relative;
height: 30px;
}
.cube {
width: 30px;
height: 30px;
background-color: orange;
text-align: center;
display: grid;
align-items: center;
justify-items: center;
position: absolute;
top: 0;
}
<button id="add">add new</button>
<div id="cubes-container"></div>
Ok so I have a div with an animation:
var x = true;
function dynamicTaskbar(thumb) {
function anim1() {
thumb.style.backgroundColor = "green";
}
function anim2() {
thumb.style.backgroundColor = "blue";
}
if (x === false) {
thumb.style.backgroundColor = "red";
thumb.removeEventListener("mouseover", anim1);
thumb.removeEventListener("mouseleave", anim2);
x = true;
} else {
thumb.style.backgroundColor = "blue";
thumb.addEventListener("mouseover", anim1);
thumb.addEventListener("mouseleave", anim2);
x = false;
}
}
//Create window's thumbnail for taskbar
var thumbnail = document.createElement("div");
thumbnail.setAttribute("class", "thumbnail");
taskbar.append(thumbnail);
taskbar.style.width = taskbar.style.width + thumbnail.style.width + "px";
thumbnail.addEventListener("mousedown", function() {
dynamicTaskbar(thumbnail);
});
#taskbar {
background-color: red;
border: solid 1px black;
width: 50px;
height: 30px;
}
.thumbnail {
width: 50px;
height: 30px;
border: solid 1px black;
}
<div id="taskbar"></div>
By default, the div is red.
When it is clicked:
If x is true, it becomes false and the div turns blue. Two event listeners, mouseover (the div becomes green) and mouseleave (the div becomes red again) are added.
If x is false, it becomes true and the div turns red. But here is my problem: both event listeners (mouseover and mouseleave) are suppose to be removed, but it doesn't work. I searched over the Internet but found nothing that fixed my problem.
Any help?
The solution for this problem is extracting the anim1() and anim2() funtions from the dynamicTaskbar() function.
Since both functions are located inside the dynamicTaskbar() function they are created again and again with each execution of the function causing the instances to be different then the initial ones.
If for example in the first execution (1st click) of dynamicTaskbar() the "object id" of anim1() will be "1" and in the second execution it will be "2". Therefore when you're trying to remove the listener you're actually trying to remove it for a different object reference.
Take a look at the example:
var x = true;
function anim1(thumb) {
thumbnail.style.backgroundColor = "green";
}
function anim2(thumb) {
thumbnail.style.backgroundColor = "blue";
}
function dynamicTaskbar(thumb) {
if (x === false) {
thumbnail.style.backgroundColor = "red";
thumbnail.removeEventListener("mouseover", anim1);
thumbnail.removeEventListener("mouseleave", anim2);
x = true;
} else {
thumbnail.style.backgroundColor = "blue";
thumbnail.addEventListener("mouseover", anim1);
thumbnail.addEventListener("mouseleave", anim2);
x = false;
}
}
//Create window's thumbnail for taskbar
var thumbnail = document.createElement("div");
thumbnail.setAttribute("class", "thumbnail");
taskbar.append(thumbnail);
taskbar.style.width = taskbar.style.width + thumbnail.style.width + "px";
thumbnail.addEventListener("mousedown", function() {
dynamicTaskbar(thumbnail);
});
#taskbar {
background-color: red;
border: solid 1px black;
width: 50px;
height: 30px;
}
.thumbnail {
width: 50px;
height: 30px;
border: solid 1px black;
}
<div id="taskbar"></div>
I'm trying to build a responsive sketch application with jQuery. It works, except for when the size for the divs within the .box class become less than 7px. I tried to make a fiddle but I couldn't see any output. I'll just leave the code here and hope for the best!
var wide = 150;
$(document).ready(function() {
makeGrid(wide);
$('body').on('mousedown mouseup', function mouseState(e) {
if (e.type == "mousedown") {
$(".box").mouseenter(function() {
$(this).css("background-color", "black");
});
} else {
$(".box").unbind('mouseenter mouseleave');
}
});
});
var makeGrid = function(wide) {
var boxSide = calculateBoxSide(wide);
var boxRowNumber = calculateRowNumbers(boxSide);
var boxSideLength = boxSide + "px";
$("body").css("line-height", boxSideLength);
for (i = 0; i < wide; i++) {
for (j = 0; j < boxRowNumber; j++) {
$box = $('<div class="box">').appendTo(".sketchpad")
$box.css("width", boxSideLength);
$box.css("height", boxSideLength);
}
}
}
var calculateBoxSide = function(wide) {
return $(".sketchpad").width() / wide;
}
var calculateRowNumbers = function(boxSideLength) {
return Math.round($(".sketchpad").height() / boxSideLength);
}
.sketchpad {
margin: 0 auto;
width: 50%;
height: 500px;
text-align: center;
}
.box {
display: inline-block;
background-color: grey;
vertical-align: top;
}
.box:hover {
background-color: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="sketchpad"></div>