I have a grid generator, it uses Javascript and jQuery to generate blocks in a grid that are displayed with HTML and CSS. I am trying to set up a button that will change the :hover behavior of the blocks (specifically, change their background-color). I am unable to do this and I'm not sure why my code is not working. I will copy and paste it here and I apologize that it is very long. You can see it in action here: http://codepen.io/anon/pen
HTML
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script type="text/javascript" src="script.js"></script>
<title> Odin #2 by Max Pleaner </title>
<link rel="stylesheet" type="text/css" href='stylesheet.css'>
</head>
<body>
<p> Welcome to my Odin Project #2 page. This is me showing off my basic JS and jQuery skills. If you move your mouse through the blocks you can see frogs come out of hiding. If you press the clear button below you can select a new number of blocks to fill the same space.</p>
<button id="button"> Generate a number of blocks of your liking that will position themselves to all fit in the 960px by 960px grid. </button>
<button id="button2"> <strike> Click here to generate new blocks and make hovering on blocks produce random colors.</strike> Why isn't this button working?! It's drawing new blocks fine, but not changing the :hover style as intended. </button>
<div id="square_holder">
</div>
<img src="Q6w802v.jpg" alt="froggy" ></img>
</body>
</html>
CSS
body {
background-color: grey;
}
p {
color: aqua;
}
#square_holder {
width: 960px;
}
.block {
background-color: green;
display:inline-block;
border: 1px solid black;
width: 232px;
height: 232px;
}
.block:hover {
background-color: blue;
//background-image:url("Q6w802v.jpg");
background-size: contain;
}
JS
$(document).ready(function(){
draw_grid(4);
$('#button').click(function(){
get_input();
});
$('#button2').click(function(){
get_input();
$('.block:hover').css("background-image", "none").css("background-color", get_random_color());
});
});
var draw_grid = function (blocks) {
var totalno = Math.pow(blocks, 2);
var dimension = (960 - 1 -(blocks * 2))/blocks;
for(var i = 0; i < totalno; i++){
$("#square_holder").append("<div class='block' id=" + i + "></div>");
};
$(".block").css("height", dimension).css("width", dimension);
}
var get_input = function(){
alert('Do you want to change the number of boxes?<b></b>');
$('#square_holder').empty();
var user_entry = prompt("What number do you choose?");
alert("Watch in awe as the grid fills ..... ");
draw_grid(user_entry);
}
var get_random_color = function() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
};
You need to use background, not background-color. Taken from the MDN page for background-image:
The CSS background-image property sets one or several background images for an element. The images are drawn on successive stacking context layers, with the first specified being drawn as if it is the closest to the user. The borders of the element are then drawn on top of them, and the background-color is drawn beneath them.
This translates into a declaration of background-image at all (even as none) will sit on top of background-color. Therefore, if you set background instead of background-color, it will supercede all other property-specific declarations.
Related
i'm trying to change each of my div's background color to black when my mouse enters the div using an eventlistener. it currently is only switching the first div to black but not any other div. why is my eventlistener only applying to the first 'contentDivs' div?
example:
this is my html code:
<body>
<div id="mainContainer"></div>
<script src="index.js"></script>
</body>
this is my javascript code:
for(x=0; x<64; x++) {
const contentDivs = document.createElement('div');
contentDivs.id = 'contentDivs';
document.getElementById('mainContainer').appendChild(contentDivs);
}
document.getElementById('contentDivs').addEventListener('mouseenter', () => {
document.getElementById('contentDivs').style.background = 'black';
})
this is what shows up when inspecting the elements in google chrome:
If you want to select many elements you can use querySelectorAll. If you want to select one please use querySelector.
I've used minimal changes for your example. Ideally you should take advice of comments and change the identifying method to be class rather than id.
Lastly, I've added another effect using css alone, so you can compare how to make style changes using :hover class.
for (x = 0; x < 64; x++) {
const contentDivs = document.createElement('div');
contentDivs.id = 'contentDivs';
document.getElementById('mainContainer').appendChild(contentDivs);
}
document.querySelectorAll('#contentDivs').forEach(function(elem) {
elem.addEventListener('mouseenter', () => {
elem.style.background = 'black';
})
})
#contentDivs {
width: 20px;
height: 20px;
background: pink;
float: left;
margin: 10px;
transition: 500ms all;
}
#contentDivs:hover {
transform: scale(1.5);
}
<body>
<div id="mainContainer"></div>
</body>
I am trying to set the background color of a div upon page load to blue. Then I want to cycle through 3 different colors (red, yellow, and green) when clicked and have the selected color remain. Below is my sample code. You can see the first two do nothing when clicked due to setting the blue color on load. I didn't load the 3rd div to blue on load to show how I want the behavior to act once clicked. Any help is appreciated.
function colorload() {
var element = document.getElementById("day1");
element.style.backgroundColor = "blue";
var element = document.getElementById("day2");
element.style.backgroundColor = "blue";
}
function changeColor(e, numb) {
var color = e.className;
e.className = (color == 'red') ? 'amber' :
(color == 'amber') ? 'green' :
(color == 'green') ? 'red' :
'undefined';
}
<style onload="colorload()">
.red {background-color:red;}
.amber {background-color:yellow;}
.green {background-color:green;}
div {
width:200px;
height:100px;
margin:50px;
text-align: center;
vertical-align: middle;
line-height: 90px;
font-weight:bold;
user-select: none;
cursor:pointer;
}
</style>
<html>
<body>
<div class="red" id="day1" onclick="changeColor(this, 1)">One</div>
<div class="green" id="day2" onclick="changeColor(this, 2)">Two</div>
<div class="amber" id="day3" onclick="changeColor(this, 3)">Three</div>
</body>
</html>
i made an update to your html and JS codes,
i used in this example .style instead of css classes, if you are interested on using classes you can refer to my comments and this link on mdn it's pretty simple.
Html file
<html>
<body>
<!-- i used .btn class and data-col to play with indexes -->
<div class="btn" id="day1" data-col="0" onclick="changeColor(event)">One</div>
<div class="btn" id="day2" data-col="0" onclick="changeColor(event)">Two</div>
<div class="btn" id="day3" data-col="0" onclick="changeColor(event)">Three</div>
</body>
</html>
Js file
let divs;
let colors = ['blue', 'red', 'green' , 'yellow'];
// when loading the page, we are catching all divs having the class "btn"
// to render it with Blue background
document.body.onload = function() {
divs = document.querySelectorAll('.btn');
divs.forEach(btn => {
const selectedColorIndex = btn.dataset.col;
btn.style = 'background:'+colors[selectedColorIndex];
});
};
function changeColor(e) {
// catch the clicked div which passed by the "event" value in the html file
let divElement = e.target;
// get data-col value and convert it to number with (+)
const selectedColorIndex = +divElement.dataset.col;
// check if we have a next color or get the red index
const nextSelectedColor = selectedColorIndex +1 >= colors.length?1:selectedColorIndex+1;
// update data-col with the next new color index to conserve the iteration (loop)
divElement.dataset.col = nextSelectedColor;
// if you want to use classes you can access with
// .classList.add(..) and .classList.remove(..) OR
// .classList.toggle(..)
divElement.style = 'background:'+ colors[nextSelectedColor]; // update the element background with selected color
}
You can also replay the same codes or update: it here is the full replayed code in JSFiddle which i made to make it more easy.
I am developing a web application using AngularJS. I find myself in a situation where I have a bar (with the css I created a line) that must dynamically lengthen and shorten.
I know that JQuery scripts are sufficient to do this. For example, if my css is like this:
.my_line{
display:block;
width:2px;
background: #FFAD0D;
height: 200px; /*This is the part that needs to dynamically change*/
}
I could in the controller resize the line (of my_line class) simply with:
$(".my_line").css("height", someExpression*100 + 'px');
The thing is, I would like to dynamically resize the line based on the size of another div element (Or, in general, any HTML element of my choice).
I don't know how to get (at run-time) the size of a certain page element in terms of height.
Only in this way I would be able to create a line that dynamically lengthens or shortens as the size of a div (or some other element) changes!
How do you do this? So I will avoid writing hard-coded the measures but I want make sure that they vary as the dimensions of other elements on the page vary
I hope this is helping:
$(".my_line").css("height", $("#referenceElement").height()*5 + 'px');
.my_line{
display:inline-block;
width:2px;
background: #FFAD0D;
}
#referenceElement {
display:inline-block;
background: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="my_line"></div>
<div id="referenceElement">Hi, I'm 5 time smaller than the orange line!</div>
Here I am using the setInterval to track the div's height (you can do width as well) and storing it in a previousHeight variable and comparing it every interval
Then according to the comparison, it will determine if the height of the div has changed. If it has then it will change the height of the other div according to the height of the first div
You can create multiple variables and track multiple elements in the same setInterval
$(document).ready(function(){
var previousHeight = parseInt($("#my-div").css("height"));
setInterval(function(){ checkHeight(); }, 100);
function checkHeight() {
// Check height of elements here
var currentHeight = parseInt($("#my-div").css("height"));
if(currentHeight != previousHeight) {
previousHeight = currentHeight;
$("#dynamic-div").css("height", parseInt(currentHeight) + "px");
}
}
$("#button").click(function() {
$("#my-div").css("height", parseInt(previousHeight) + 5 + "px");
})
})
#my-div{
background: #000000;
height: 20px;
width: 20px;
}
#dynamic-div{
background: teal;
height: 20px;
width: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="my-div">
</div>
<button id="button">Increase div height</button>
<div id="dynamic-div">
</div>
100% stuck on a homework assignment...
I have some simple JavaScript with the intent of changing the background image and text of a div upon mouseover over certain images. However, what I am trying to execute now is to revert the div back to its original state upon mouseout.
I am able to revert the divs background color with
document.getElementById('image').style.backgroundImage = "";
Essentially killing the background image and forcing it to revert to the background color that is there upon page load.
Now what I'm trying to do is store the original innerHTML text "Hover over an image below to display here." as a variable
var originalText = document.getElementById('image').innerHTML;
and then call it back when I need it.
function unDo() {
document.getElementById('image').style.backgroundImage = "";
document.getElementById('image').innerHTML = originalText;
however,
var originalText = document.getElementById('image').innerHTML;
is returning "undefined", which means I've goofed up somehow when storing the variable, right? I've tried innerText as well and that doesn't seem to do much for me. Below is the full HTML and JavaScript below.
/*Name this external file gallery.js*/
var originalText = document.getElementById('image').innerHTML;
function upDate(previewPic) {
document.getElementById('image').innerHTML = previewPic.alt;
document.getElementById('image').style.backgroundImage = "url('" + previewPic.src + "')";
/* In this function you should
1) change the url for the background image of the div with the id = "image"
to the source file of the preview image
2) Change the text of the div with the id = "image"
to the alt text of the preview image
*/
}
function unDo() {
document.getElementById('image').style.backgroundImage = "";
document.getElementById('image').innerHTML = originalText;
/* In this function you should
1) Update the url for the background image of the div with the id = "image"
back to the orginal-image. You can use the css code to see what that original URL was
2) Change the text of the div with the id = "image"
back to the original text. You can use the html code to see what that original text was
*/
}
body {
margin: 2%;
border: 1px solid black;
background-color: #b3b3b3;
}
#image {
line-height: 650px;
width: 575px;
height: 650px;
border: 5px solid black;
margin: 0 auto;
background-color: #8e68ff;
background-image: url('');
background-repeat: no-repeat;
color: #FFFFFF;
text-align: center;
background-size: 100%;
margin-bottom: 25px;
font-size: 150%;
}
.preview {
width: 10%;
margin-left: 17%;
border: 10px solid black;
}
img {
width: 95%;
}
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Photo Gallery</title>
<link rel="stylesheet" href="css/gallery.css">
<script src="js/gallery.js"></script>
</head>
<body>
<div id="image">
Hover over an image below to display here.
</div>
<img class="preview" alt="Styling with a Bandana" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/389177/bacon.jpg" onmouseover="upDate(this)" onmouseout="unDo()">
<img class="preview" alt="With My Boy" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/389177/bacon2.JPG" onmouseover="upDate(this)" onmouseout="unDo()">
<img class="preview" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/389177/bacon3.jpg" alt="Young Puppy" onmouseover="upDate(this)" onmouseout="unDo()">
</body>
</html>
note: I'm not allowed to change the HTML for this assignment. Only the JavaScript. You do NOT have to do my homework for me. However, a hint in the right direction would be nice.
screenshotoflocalenvironment
Seems like this could be happening because your script tag in your html is above the body.
When you declare the "original text" variable at the beginning of your script, the page hasn't loaded yet, and so it comes back undefined, because it can't find anything in the document with an "image" class.
Sometimes it loads quick enough maybe, other times it doesn't
Instead, move your script tag in your html to right below the body tag. So the script loads after the body has loaded. Should fix it.
**additional tip.
Store your element (i.e: the "image") in a variable instead of calling getElementbyId multiple times. Every time you do this javaScript searches the entire DOM which is resource intensive in bigger applications and can get pretty slow. Just a pet peeve of mine.
First save the background color in a variable :
z = document.getElementById("mydiv").style.backgroundColor;
Then on mouse out, restore this color :
document.getElementById("mydiv").style.backgroundColor = z;
It works for me. My full code is :
` <script>
var z;
$( document ).ready(function() {
document.getElementById("mydiv").onmouseover = function() {mouseOver()};
document.getElementById("mydiv").onmouseout = function() {mouseOut()};
});
function mouseOver() {
z = document.getElementById("mydiv").style.backgroundColor;
document.getElementById("mydiv").style.backgroundImage = "url('londoneye.jpg')";
}
function mouseOut() {
document.getElementById("mydiv").style.backgroundImage = "";
document.getElementById("mydiv").style.backgroundColor = z;
}
</script>`
The html is :
<div id="mydiv" style="width:400px; height:400px; background-color:yellow;margin-left:50px; margin-top:50px;">
I have a markup that contains five boxes, a next button, and a kind of navigation menu, which I can use to point to a specific box. The next button id used to perform a translation of the boxes, which works the way thought it was. But the indicators doesn't work properly.
Here's my code:
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body>
<!-- Boxes -->
<div class="box current-box">0</div>
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<!-- End Boxes -->
<button class="next_button">Next</button>
<!-- Navigation -->
<div class="numbers-nav">
<button class="number">0</button>
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button class="number">4</button>
</div>
<!-- End Navigation -->
</body>
</html>
CSS
*{
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
.box{
width: 100px;
height: 100px;
background: yellow;
transform: translateX(0px);
transition: transform 0.5s linear;
border: 1px solid #000;
text-align: center;
line-height: 100px;
font-family: 'Lucida Sans Unicode', sans-serif;
}
.numbers-nav{
display: inline-flex;
margin-left: 10px;
}
.number{
display: block;
}
JAVASCRIPT
var nextButton = document.querySelector('.next_button'); // The 'Next' button
var boxes = document.getElementsByClassName('box'); // Get all the yellow squares within the document
var boxesList = Array.from(boxes); // Creates an array with the boxes
var numbersNav = document.querySelector('.numbers-nav'); // Get the container of all indicators (the numbers)
var numbers = Array.from(numbersNav.children); // Creates an array with all the numbers itself
var transitionCompleted = true; // Indicates that the transition is complete
function transitioned(e) {
console.log('=== transition finished ===');
transitionCompleted = true;
}
window.addEventListener('DOMContentLoaded', function(){
var currentBox = document.querySelector('.current-box');
currentBox.style.transform = 'translateX(' + 100 + 'px)';
// Prevent multiple click when transition
boxesList.forEach(function (box, index) {
box.addEventListener('transitionend', transitioned);
box.addEventListener('webkitTransitionEnd', transitioned);
box.addEventListener('oTransitionEnd', transitioned);
box.addEventListener('MSTransitionEnd', transitioned);
});
// When the user clicks, translate the 'current-box' to 0px and then translate its next sibling 100px to the right
nextButton.addEventListener('click', translateNext);
// When the user clicks a number, repeat the translateNext function until 'current box' match the clicked number
numbersNav.addEventListener('click', moveToSpecificBox);
});
function translateNext(e){
console.log('Transition completed: ' + transitionCompleted);
if(transitionCompleted == true){
transitionCompleted = false;
var currentBox = document.querySelector('.current-box');
var nextBox = currentBox.nextElementSibling;
currentBox.style.transform = 'translateX(' + 0 + 'px)';
nextBox.style.transform = 'translateX(' + 100 + 'px)';
currentBox.classList.remove('current-box');
nextBox.classList.add('current-box');
}
}
function moveToSpecificBox(e) {
console.log('=== translating until an specific box ===');
var targetNumber = e.target.closest('.number');
// Discovers the position of the number inside the navigation box has been clicked
var targetIndexNumber = numbers.findIndex(function(number){
return number === targetNumber}
);
// Indicates the box that should have the 'current-box' class until the end of this code block.
var boxTarget = boxesList[targetIndexNumber];
while(!boxTarget.classList.contains('current-box')){
translateNext();
}
}
The idea is that the moment I click the next button, the box with the “current-box” class has a transformation, moving to its starting position, while the next box is moved 100px to the right, and becomes the "current box".
All boxes have their transition monitored to prevent functionality from triggering while elements are still moving. Therefore, while the transition is not finished, clicking in the next button doesn’t perform any action.
The navigation menu has indicators that are used to point to a specific box. When a number is clicked, it should repeat the functionality of the next button until the pointed box has the "current box" class.
If I click 2 as soon as the page loads, for example, the following should happen:
1st
Translate box 0 to 0px
Translate box 1 to 100px
Box 0 loses current-box class
box 1 receives the class "current-box"
2nd
Translate box 1 to 0px
Translate box 2 to 100px
Box 1 loses current-box class
box 2 receives the "current-box" class
Since box 2 is now the current one, the loop should stop. The following code snippet is responsible for doing that:
while(!boxTarget.classList.contains('current-box')){
translateNext();
}
That code checks to see if the pointed box has the class "current box" and if it does not, the function "translateNext" will be executed.
The problem is that the code is generating an infinite loop.
I think this is happening because of the event listener that is monitoring the transition. The elements never get their transition finished, so the transitionedCompleted become permanently false.
It's possible to see what is happening adding an limit to the loop, like this one:
var stop = 0;
while(!boxTarget.classList.contains('current-box')){
If(stop >= 5){ break }
translateNext();
stop++;
}
The translateNext function is executed only once, the transitionCompleted variable gets the false value, and its value is never changed again.
So, how can I call a function within a loop, while transition listener still works?
I don't think that you would want to use the while loop. Because, what is there to loop over?
In your code the transitioned function is fired whenever a transition is ended. So I would recommend that you call translateNext in that function. This way translateNext will only be called whenever a transition has finished and the next transition has to begin.
One of JavaScript's features is events. They enable you to trigger functions when certain events occur. It is a powerful feature and utilizing them can be a strong paradigm to work from.
function transitioned(e) {
console.log('=== transition finished ===');
transitionCompleted = true;
translateNext();
}
And in your translateNext function you are selecting the nextElementSibling of the current element. You can use this to check if the current element is the last element. And make the function keep going until the last element has been reached. Add the following if statement.
var currentBox = document.querySelector('.current-box');
var nextBox = currentBox.nextElementSibling;
if (nextBox === null) {
return;
}
This statement checks if the nextElementSibling is there will stop the function from running when it is not there.
I hope this will help.