I have an Exercise to querySelect the image from the HTML and change it on mouseover , I did that correctly like this :
var img = document.querySelector("#image1").addEventListener('mouseover' ,function (){
this.src="images/image1_2.jpg")}
The question is that I have an advanced exercise to change five images in the same way but with " one function "
I did it with five function this way :
const image1 = document.querySelector("#image1")
const image2 = document.querySelector("#image2")
const image3 = document.querySelector("#image3")
const image4 = document.querySelector("#image4")
const image5 = document.querySelector("#image5")
image1.addEventListener('mouseover', function (){
this.src = "images/image1_2.jpg"
})
image2.addEventListener('mouseover' , function (){
this.src= "images/image2_2.jpg"
})
image3.addEventListener('mouseover', function (){
this.src = "images/image3_2.jpg"
})
image4.addEventListener('mouseover', function (){
this.src = "images/image4_2.jpg"
})
image5.addEventListener('mouseover', function (){
this.src = "images/image5_2.jpg"
})
, but I need to do it with one function , any hint on how to do it ?
I hope your img has an initial src. Otherwise you won't be able to mouse over it.
That being said. You will need to use a className instead of an id for each image because they are the same category.
<img src="images/image1_1.jpg" class="token" />
<img src="images/image2_1.jpg" class="token" />
<img ...
Change token to whatever you like.
And then select them by using either document.getElementsByClassName or document.querySelectorAll. They return an HTML collection which is an array-like object.
var images = document.querySelectorAll(".token");
In the snippets below, I use simple divs to illustrate what can be done.
Using forEach loop. you will have to convert the collection to an array in order to use forEach
var imgs = [ ...document.querySelectorAll(".img") ];
imgs.forEach((img, i) => {
img.addEventListener('mouseover', function () {
this.textContent = "images/image" + (i + 1) + "_2.jpg";
});
});
div {
width: 200px;
height: 30px;
float: left;
margin: 5px 1em;
font-weight: bold;
color: white;
text-shadow: 1px 1px 0 black;
}
<div class="img" style="background: #234;"></div>
<div class="img" style="background: #7fb;"></div>
<div class="img" style="background: #ace;"></div>
<div class="img" style="background: #d8f;"></div>
<div class="img" style="background: #e6a;"></div>
Using a simple for loop. no need for convertion
var imgs = document.querySelectorAll(".img");
for (let i = 0; i < imgs.length; i++)
imgs[i].addEventListener('mouseover', function () {
this.textContent = "images/image" + (i + 1) + "_2.jpg";
});
div {
width: 200px;
height: 30px;
float: left;
margin: 5px 1em;
font-weight: bold;
color: white;
text-shadow: 1px 1px 0 black;
}
<div class="img" style="background: #234;"></div>
<div class="img" style="background: #7fb;"></div>
<div class="img" style="background: #ace;"></div>
<div class="img" style="background: #d8f;"></div>
<div class="img" style="background: #e6a;"></div>
Maybe make the event listener 'listen' on the body element, then check which element was hovered whith an if statement. I think it can be done whithout 'if' too. You will have to use 'this'.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
Don't ask us to do your exercice, but ask for a hint so you can do it by yourself and learn.
You are close to the solution. What you want is, when you hover any of the images, you want to change all the src. So your code must be something like :
When I hover any of my images (use document.getElementsByClassName), I've got a function which instead of changing the source of the current image changes the source of the five images (so you'll have a line by image to change each src).
Your question is unclear if you want to change ALL images with one hover or one-by-one.
If you want to change all images in same time, your function should look something like this.
function changeall{
document.getElementById("image1").src="....";
document.getElementById("image2").src="....";
document.getElementById("image3").src="....";
document.getElementById("image4").src="....";
document.getElementById("image5").src="....";
}
If you want to change it one by one it will require your to modify your html code also.I don't want to finish your exercise therefore I will only write you main points that you need to look after
Make your images have same class
Add two functions onmouseover and one onmouseout
One function should change custom attribute so that you know which image was hovered on
example:
<img .... onmouseover="changeimg();function(){document.getElementById("id-of-that-img").customattribute ="1";}" onmouseout="document.getElementById("id-of-that-img").customattribute ="0";}">
I know that it is kinda messy but I didn't want to create separate named functions for this.
When customattribute is at 0 you know that it is not being hovered on, and when its 1 you know that it is.
Make a loop for checking each element of that class if it has customattribute === 1.
I would personally use a variable to counter for my images.
something like this:
var counter = 0;
var x =setInterval(function(){
if(document.getElementsByClassName('class')[counter].customattribute===1){
//what_to_do_if_img_is_being_hovered_on}
clearInterval(x);
//stops the loop
else{
counter++;}},1);
I haven't tried the code out and it probably has a flaw but it is there just to give you a hint about how you can solve your problem.
Related
I have some images on an html page. When an image is clicked, I change the image src to show that it is selected. This is working properly. When another image on the same row is selected, I would like to unselect the other images on that row. I've got code below. Unfortunately, when i call getAttribute("src"), I am only getting the initial value that is set when the page is loaded and defined below. I've tried this with both an input type of image as well as an img tag. Any ideas?
var imgOther = document.getElementById(bwdTerms[i] + i);
var imgSrc = imgOther.getAttribute("src");
if (imgSrc.indexOf("_selected") > -1) {
imgOther.click();
}
If I'm not explaining this right, and I doubt I am, I'm glad to answer questions. I've also tried this with jquery.
TIA
There's not enough code here for me to see where you're going wrong. I rewrote it to assign all images to one variable, then add onclick events to each one that reset all images before setting the clicked one to the new src.
const images = document.querySelectorAll(".cats > img");
images.forEach(img => {
img.addEventListener("click", function(e){
images.forEach(img => img.src = img !== e.target ? img.dataset.image : e.target.src);
e.target.src = e.target.src === img.dataset.image ? "https://placekitten.com/500/500" : img.dataset.image;
});
});
.cats{
display: flex;
gap: 20px;
}
.cats > img {
width: 150px;
height: 150px;
}
.cats > img:hover {
cursor: pointer;
}
<div class="cats">
<img src="https://placekitten.com/200/200" data-image="https://placekitten.com/200/200">
<img src="https://placekitten.com/210/200" data-image="https://placekitten.com/210/200">
<img src="https://placekitten.com/200/210" data-image="https://placekitten.com/200/210">
<img src="https://placekitten.com/230/210" data-image="https://placekitten.com/230/210">
<img src="https://placekitten.com/300/250" data-image="https://placekitten.com/300/250">
</div>
I have a div container with several images. I want the user to select an image (avatar) from the provided list. Then the avatar image will be uploaded and also accessible. Once the user selects the avatar, I want to save the location of the selected avatar to my database. What is the best way to select the image? Is there any easy way to do this?
HTML
<div class="image-container">
<img src="images/gorillaAvatars/brownGorilla.png" id="brownGorilla">
<img src="images/gorillaAvatars/gorilla.png" id="Gorilla">
<img src="images/gorillaAvatars/greenGorilla.png" id="greenGorilla">
<img src="images/gorillaAvatars/kidGorilla.png" id="kidGorilla">
<img src="images/gorillaAvatars/surpriseGorilla.png" id="surpriseGorilla">
</div>
CSS
<style>
.image-container{
width:60%;
border: solid magenta 1px;
padding: 5px;
margin: 30px;
display: flex;
justify-content: space-evenly;
}
img{
width:80px;
}
img:hover,
img:focus,
img:active{
background-color: blue;
border-radius: 20px;
}
<style>
Javascript
const brownGorillaAvatar = "https://brownGorilla.png";
const mainGorillaAvatar ="https://gorilla.png"
const greenGorillaAvatar ="https://greenGorilla.png"
const kidGorillaAvatar ="https://kidGorilla.png"
const surpriseGorillaAvatar ="https://surpriseGorilla.png"
const avatar = [brownGorillaAvatar,mainGorillaAvatar,greenGorillaAvatar,kidGorillaAvatar, surpriseGorillaAvatar]
brownG.addEventListener('click', avatarSelect);
bigG.addEventListener('click', avatarSelect1);
greenG.addEventListener('click', avatarSelect2);
kidG.addEventListener('click', avatarSelect3);
surpG.addEventListener('click', avatarSelect4);
function avatarSelect (){
console.log(avatar[0])
}
function avatarSelect1 (){
console.log(avatar[1])
}
function avatarSelect2 (){
console.log(avatar[2])
}
function avatarSelect3 (){
console.log(avatar[3])
}
function avatarSelect4 (){
console.log(avatar[4])
}
Rather than attaching an event to each image object, it would be better to attach an event to the container surrounding it.
You can avoid overlapping codes and respond flexibly even if image objects increase.
for example
const imageContainer = document.getElementById("image-container");
imageContainer.onclick = function(e) {
console.log(e.target.id); // you can get img tag's id
}
Have a look at how Event Bubbling and delegation work in javascript to get a better understanding but you want to add the event to the parent container not to each element. So by adding new elements to your array they will be clickable.
const avatars = [
'brownGorillaAvatar',
'mainGorillaAvatar',
'greenGorillaAvatar',
'kidGorillaAvatar',
'surpriseGorillaAvatar'
]
const avatarContainer = document.querySelector('#avatarContainer');
avatars.forEach((avatar) => {
const span = document.createElement('span');
span.innerHTML = avatar;
avatarContainer.appendChild(span);
})
avatarContainer.addEventListener('click', (evt) => {
console.log(evt.target);
})
<html>
<head></head>
<body>
<section id="avatarContainer">
</section>
</body>
</html>
I'd like to use the mouseOver/mouseOut function in JS to change the colour of an icon.
The icon is white but I'd like it to turn turquoise upon hover over and then back to white when the mouse moves away from the icon.
In my file I have 3 docs:
.html
.css
.js
and 2 images:
skull.png (white icon)
skull2.png (turquoise icon)
Here is my html:
<div id='skull'>
<a href="#" onmouseover="mouseOver()" onmouseout="mouseOut()">
<img class="icon" src="skull.png" alt="skull"/></a>
</div>
Here is my css for the 'icon' class:
.icon {
margin: 0 25px;
height: 40px;
width: 40px;
}
And the js for the function:
function mouseOver() {
document.getElementById("skull").innerHTML = '<img src="skull2.png" />';
}
function mouseOut() {
document.getElementById("skull").innerHTML = '<img src="skull.png" />';
}
I'm having two issues:
The first is that when I hover over the white skull, the skull whilst turning turquoise does not pick up the dimensions set out by the "icon" class. The dimensions are the size of the .png rather. I'd like them the size of skull.png as specified in the css. Not sure how this works?
When you hover off the turquoise skull, the icon does not return to white
Here is a video to show what I mean a little more: https://www.screenmailer.com/v/I5amMjkBaaeLtLU
(Apologies I'm pretty new to programming)
Thanks :)
First of all, you do not have to change the entire inner HTML, and you could go about it by changing only the image src attribute. This way you can get the image by ID only once and not every time that the function is called.
var img = document.getElementById('myImg');
img.onmouseout = function () {
this.src = 'http://www.facetheforce.today/darthvader/200/200';
};
img.onmouseover = function () {
this.src = 'http://www.facetheforce.today/c3po-alt/200/200';
};
<img id="myImg" src="http://www.facetheforce.today/darthvader/200/200"/>
Another way you can go about it is by using CSS hover and background image.
For example:
#bg-image {
width: 200px;
height: 200px;
display: block;
background: url("http://www.facetheforce.today/darthvader/200/200");
}
#bg-image:hover {
background: url("http://www.facetheforce.today/c3po-alt/200/200");
}
<div id="bg-image"></div>
Try this
function mouseOver() {
document.getElementById("skull").innerHTML = '<a href="#" onmouseover="mouseOver()" onmouseout="mouseOut()"><img src="skull2.png" class="icon" alt="skull" />';
}
function mouseOut() {
document.getElementById("skull").innerHTML = '<a href="#" onmouseover="mouseOver()" onmouseout="mouseOut()"><img src="skull.png" class="icon" alt="skull" />';
}
You are not setting the img class as .icon. Also, your areremoving the anchor from your div in the first mouseOver call because you are replacing it's content by <img src="skull2.png" />
This must solve your two problems, but there's a better way to do this.
Add an id to your image, then get in the functions and change only the images's src attribute.
I'm new to stack overflow so sorry if I don't articulate my problems well or show my code properly. working on a homework assignment where I have to create a game like the classic mastermind one. I have designed the game board and have created a 'round 1' division with toggling color buttons, submit button, and even calls up the proper result image (combination of white & black dots as img png).
My js code for duplicating the rounds is below. my problem is duplicating the round and all the functionality 9 more times. I would like to disable the toggle color buttons of a round once it is submitted and I would need to assign a new id to both the title of the round as well as the div where the result image would appear (since that changes with each new guess). But no matter what I try (generate all the code as string and append to body) the best I can get is 10 rounds but only functionality with round 1. All classes and Ids are same so the same event handlers and jQuery links should apply, yes?
Any-who, any help or suggestion is appreciated (thanks).
script code for creating rounds-
const nextRound = '
<div id="Round" class="level">
<h3 class="title"></h3>
<div class="buttondisplay">
<a id="boxa" class="button" class="active"></a>
<a id="boxb" class="button" class="active"></a>
<a id="boxc" class="button" class="active"></a>
<a id="boxd" class="button" class="active"></a>
</div><a id="submit" class="submitter">SUBMIT</a>
<div id="res1" class="results"></div>
</div>';
const buildRounds = () => { for (i = 1; i <= 10; i++){
$('#Gameboard').append(nextRound); }
}
The elements I would want to apply new ids are the boxa, boxb, boxc, and boxd, as well as the 'submit' and res1 (for resultsimage.png). Have been banging my head trying to make this work. Any help would be great. Or if you need more of the code, I can provide.
Thanks!
Rick
Issue
ids must be unique per page. You have a total of 6 different ids and each of those ids has 10 duplicates. jQuery/JavaScript will expect only one #Round or it expects one #boxc so once it finds an id it stops there and all the other duplicates are ignored or worse not entirely ignored. Basically when you have more than one element sharing an id, you will most likely get undesirable results if any at all. So you must make each id unique and a common way to do that is to assign a number to each id during a loop (i.e. "Round"+i)
BTW an element cannot have any duplicate attributes as well. So
<a id="boxd" class="button" class="active"></a>
is invalid and most likely the class='button' will be overwritten by class='active'. For multiple classes on a single element the syntax is:
<a id="boxd" class="button active"></a>
Details are commented in demo
Verify that all ids are unique by inspecting the page with DevTools.
Added Demo 2 which uses String Literals instead of Template Literals. IE does not support Template Literals hence Demo 2.
Demo 1 -- Using Template Literals
// Pass a number of rounds (i.e. 'qty')
function buildRounds(qty) {
/* Declare 'i' with 'let' limits i to only what
|| applies within the scope of the 'for' loop.
|| This limit helps 'i' to increment properly
|| without the influence of references outside
|| of the loop.
*/
for (let i = 1; i <= qty; i++) {
/* Use ES6 Template Literals* for complex strings
|| by wrapping the whole string with backticks `.
|| What is seen in code is literally rendered so
|| new lines are NOT ignored and escaping quotes
|| like this: `\'`or `\"` is not needed.
|| ${variable} is an interpolation of a value
|| inserted into the string. Note that the value 'i'
|| will be different on each loop therefore
|| ensuring unique ids.
*/
const nextRound = `
<div id="round${i}" class="level">
<h3 class="title">Round ${i}</h3>
<div class="buttonDisplay">
<a id="boxA${i}" class="button">A</a>
<a id="boxB${i}" class="button">B</a>
<a id="boxC${i}" class="button">C</a>
<a id="boxD${i}" class="button">D</a>
</div>
<a id="submit${i}" class="submitter">SUBMIT</a>
<div id="result${i}" class="results"></div>
</div>
`;
$('#gameBoard').append(nextRound);
}
/* Added function will toggle the '.active' class on/off
|| on each clicked '.button'. I don't know exactly what
|| good a "status" class would be if on every button,
|| so I changed it so now it can be toggled by user
*/
$('.button').on('click', function() {
$(this).toggleClass('active');
});
}
/* Call buildRounds() and pass the number
|| of rounds desired.
*/
buildRounds(10);
/* * Template Literals are not supported by M$ browsers
|| (i.e. IE). See Demo 2
*/
.button,
.submitter {
display: inline-block;
border: 3px ridge blue;
padding: 0 5px;
margin: 10px 5px;
color: blue;
cursor: pointer;
}
.button.active {
border: 3px inset red;
outline: 2px solid tomato;
color: red;
}
<main id='gameBoard'></main>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Demo 2 -- Using + to concat strings.
function buildRounds(qty) {
for (let i = 1; i <= qty; i++) {
/* This portion of the code is modifed to the use
|| of string literals instead of template literals.
|| If IE support is needed, then use this version.
*/
const nextRound = '<div id="round' + i + '" class ="level"><h3 class="title"> Round ' + i + ' </h3><div class="buttonDisplay"><a id="boxA' + i + '" class="button">A</a><a id="boxB' + i + '" class="button">B</a><a id="boxC' + i + '" class="button">C</a><a id="boxD' + i + '" class="button">D</a></div><a id="submit' + i + '" class="submitter">SUBMIT</a><div id="result' + i + '" class = "results"></div></div>';
$('#gameBoard').append(nextRound);
}
$('.button').on('click', function() {
$(this).toggleClass('active');
});
}
buildRounds(10);
.button,
.submitter {
display: inline-block;
border: 3px ridge blue;
padding: 0 5px;
margin: 10px 5px;
color: blue;
cursor: pointer;
}
.button.active {
border: 3px inset red;
outline: 2px solid tomato;
color: red;
}
<main id='gameBoard'></main>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
would like to add a play/stop button to an image onmouseover. I have several images in the same div that are called separately. If Image A is called I would like to have a arrow icon/button appear on the image. And onmouseout, the arrow/icon button to disappear from the image. I do not need this on all my images.
The functionality of the icon/button will be to change Image A to it's loop form and back.
Thanks for any help.
Here's what I have used so far: Not sure this is the most efficient way, but I have the main chart and call other charts as overlays, some are transparent layers some are not. When the main map is displayed, I want to call the buttons that float on top of the map. these will utilize the onmouseover/mouseout. And when clicked I want to change the main map to its loop version.
#chart
{
width: 1000px;
height:700px;
border: solid 1px #d9d9d9;
vertical-align: middle;
position: relative;
z-index: 1;
float: left;
}
<div id="chart">
<img name="mymap" src="http://www.dalta.com/still_image.gif"
width="1000px" height="700px" alt="Map" align="middle" />
<div class="basemap" id="HI_basemap" >
<img src="WEB_HI_BASEMAP.gif" width="1000" height="700"></div>
<div class="basemap" id="HI_etp" >
<img src="WEB_HI_ETP_BASEMAP.gif" width="1000" height="700"></div>
<div class="basemap" id="HI_vor" >
<img src="WEB_VOR_HAWAII.gif" width="1000" height="700"></div>
<div class="basemap" id="HI_route" >
<img src="WEB_ROUTES_HI.gif" width="1000" height="700"></div>
</div>
Tried this instead, but need a way to make infinite loop between 2 images.
intImage = 2;
function swapImage() {
switch (intImage) {
case 1:
IMG1.src = "http://ftpweb.delta.com/weather/WEB0HR.gif"
intImage = 2
return(false);
case 2:
IMG1.src = "http://ftpweb.delta.com/weather/WEB.gif"
intImage = 1
return(false);
}
}
I call this with an onClick but it only lets me do the function 1 time. Any ideas?
Then you can add the id attribute, to the image A. Such as this:
<img src="link/to/file.png" alt="photo" id="a" />
Now the JS would be as:
$('#a').hover(function () {
// do what so ever,
}
$('#a').mouseleave(function () {
// do what so ever,
}
There are many other events in the API. You can use them, and execute the code. However to play/stop you can do this:
$('#a').hover(function () {
$('.audioFile').play();
}
This can be achieved by giving a unique id to each of the images .
Then use getElementById("some id") to get a reference to that image. Then attach the onMouseOver and onMouseOut events to these refernces. This task will become very simple if you give a systematic id to the images like img1,img2 etc since you can use a for loop in this case.