setTimeout not working with onmouseout - javascript

First, here are the problematic lines of code:
<a onmouseover="hoverDisplay(this)" onmouseout="setTimeout(unHoverDisplay(), 3000);" href="http://rabbit.jpg">
Rabbit
</a><br>
Basically, I want the image to load and appear when I hover over the link, and I want the it to disappear after some time when I hover out of the link. The methods:
hoverDisplay(this)
unHoverDisplay()
display and remove the image, respectively, but when I tried to delay unHoverDisplay(), it didn't work; the image disappeared the moment my mouse hovered off the link.
I've tried adding and removing the semicolon after the setTimeout (not sure if the semicolon is necessary or not), and I tried delaying the hoverDisplay function as well, which did not work. Aside from the delay problem, the two functions work as intended.
This seems like a simple issue, but I can't figure out what I'm doing wrong. Help is appreciated. Thanks.
Not sure if this is necessary, but here are the implementations of the two functions:
//Display image for link that you hover over
var address; //Address of image
var toBeDisplayed; //Declaring img object
var maxHeight=screen.height;
var maxWidth=screen.width;
var invisible=document.getElementById("invisible"); //the div in which the image is contained
function hoverDisplay(imageLink)
{
address=imageLink.getAttribute("href"); //get address
toBeDisplayed=document.createElement("img"); //create img
toBeDisplayed.setAttribute("src", address); //give img the address
//Resize img if it doesnt fit on the screen
if(toBeDisplayed.height > maxHeight)
{
toBeDisplayed.style.height="" + maxHeight + "px";
}
else if(toBeDisplayed.width > maxWidth)
{
toBeDisplayed.style.width="" + maxWidth + "px";
}
invisible.appendChild(toBeDisplayed); //display image by adding it as a child to a div
invisible.style.visibility="visible"; //make div visible
toBeDisplayed.style.border="solid yellow 5px";
}
//Remove image once you hover out of the link
function unHoverDisplay()
{
//Removes all children of the div
while(invisible.firstChild)
{
invisible.removeChild(invisible.firstChild); //remove img by removing it as a child
}
invisible.style.visibility="hidden";
}

The trouble is that the parentheses after unHoverDisplay in your first argument to setTimeout are causing unHoverDisplay to be executed immediately. You simply want to pass the function by its identifier without the parentheses:
onmouseout="setTimeout(unHoverDisplay, 3000);"

You are passing a function as a parameter to setTimeout, not invoking it. Hence, you don't need those parentheses along with the function name, all that is required is the function name itself.
onmouseout = "setTimeout(unHoverDisplay, 3000);"

Related

How to switch between different HTML elements with the same onclick function?

Right now i have four images which are being dynamically presented on html. This is done via an onload function. Basically when i click on of those wheels I would like the image to change for around one second then go back. But right now only one wheel changes colour which is quite annoying.
function setWheels() {
document.querySelector(".blue-wheel").innerHTML = "<img src='blue-dark.svg.svg' onclick='buttonEvent()'>";
document.querySelector(".red-wheel").innerHTML = "<img src='red-dark.svg.svg' onclick='buttonEvent()'>";
document.querySelector(".green-wheel").innerHTML = "<img src='green-dark.svg.svg'>";
document.querySelector(".yellow-wheel").innerHTML = "<img src='yellow-dark.svg.svg'>";
}
function buttonEvent() {
if (document.querySelector(".blue-wheel")) {
document.querySelector(".blue-wheel").innerHTML = "<img src='blue-light.svg.svg'>";
setTimeout(setWheels, 800);
}
else if (document.querySelector(".red-wheel")) {
document.querySelector(".red-wheel").innerHTML =<img src='red-light.svg.svg'>";
setTimeout(setWheels, 800);
}
}
I havnt added the other coloured wheels as i do predict that they will have the same effect. I do believe that the setTimeout may be one of the problems as I'm calling the setWheels function but the first if statement seems to be the only one that changes colour even when i click the other div.
Your if statements aren't checking anything useful. if(document.querySelector(".blue-wheel")) is only checking if that element is there, not if the image inside was clicked.
If you want to know which image was clicked, pass it in as a parameter to the function.
<img src='blue-dark.svg.svg' onclick='buttonEvent(this)'>
and in your javascript, just change the src for the image that was clicked and then set a timeout to change it back.
function buttonEvent(e) {
e.src = e.src.replace('dark', 'light');
setTimeout(() => {e.src = e.src.replace('light', 'dark')}, 800);
}
if you want to protect against fast clicking while the image is already highlighted (improve performance) you can add a return:
function buttonEvent(e) {
if (!e.src.includes('dark')) return;
e.src = e.src.replace('dark', 'light');
setTimeout(() => {e.src = e.src.replace('light', 'dark')}, 800);
}
You are missing a "
.innerHTML =<img src='red-light.svg.svg'>";
should be
.innerHTML = "<img src='red-light.svg.svg'>";
you can use a variable (let x=0) to count on what image are you on. then make function that will see what x = 0 so it will show the first image then add one to the x (like "x++")but before you show the image you need to remove the last one, so then you need to loop through the images (you can give the same class to the images) like ".forEach()" and in that function you can see if that image is on the page or is shown to the user then just remove it, then x =1 in that case just show the second image and so on. you can add "if" statement that will check "if x>=(image count)" when that happens then just "x=0" and it will reset

jQuery: fade out, change background image, then fade in

I'm trying to fade the container div around this target div, then change the background, then fade it back in. The problem is that all the functions in this block are called instantaneously, which means the background is swapped out immediately, then the div fades out and in. Not sure how to implement this as a stepped operation.
For now, don't worry about the "myType" part. I have a dropdown menu on the page that you select which changes the background image in the div to a different image based on the selection. I've removed that functionality from this code, since it isn't actually relevant.
HTML:
<div id="itemCustomize">
<div id="itemBaseImg"></div>
</div>
jQuery:
$(myType).change(function() {
$("#itemCustomize").fadeOut(500);
$("#itemBaseImg").css('background-image', 'url(myimage.jpg)';
$("#itemCustomize").fadeIn(500);
}
Update:
The true implementation is actually different. I should have considered that. I have an array of images which I generate an image URL from by parsing the base URL with the variable "url", then add the base image part of the URL by calling on an index. This worked before it was wrapped in a callback function, but now that I want to fade in and out the wrapper div, it doesn't work.
$(myType).change(function() {
$("#itemCustomize").fadeOut(500, function() {
$("#itemBaseImg").css('background-image', url + itemBaseImg[myType.selectedIndex] + ")");
});
$("#itemCustomize").fadeIn(500);
});
You can use the complete callback on jQuery fadeOut function to make them run one after another.
$(select).change(function() {
$("#containerdiv").fadeOut(500, function() {
$("#targetdiv").css('background-image', 'url(myimage.jpg)';
$("#containerdiv").fadeIn(500);
});
}
See: http://api.jquery.com/fadeout/
I figured it out. I needed to create a variable to pass into the index. Thanks for everyone's help!
$(myType).change(function() {
var myIndex = this.selectedIndex;
$("#itemCustomize").fadeOut(50, function() {
$("#itemBaseImg").css('background-image', url + itemBaseImg[myIndex] + ")");
$("#itemCustomize").fadeIn(200);
});
});

Issue with jQuery .one() method

I've got a container that includes several icons the user can hover over and be shown a block of text next to it. I'm grabbing the blocks of text from an array and have a randomize function so that they're always shown a different block of text when revisiting the page.
I ran into an issue where every time you hover over an icon, it keeps adding more array elements, because the function gets called each time you hover over the icon. So I decided to use the one() method so the function only runs once, however that's where my real issue is. Using the one() method doesn't show ANY text, and I'm pretty sure it's due to the nested function I have.
You can test this out here: http://www.evanvolmering.com/bootstrap/docs/examples/carousel/eyeswideshut.html
In the banner a video will play, and shortly into it a little icon will appear in the bottom of left of the banner. Hovering over it will show some text. When you hover over it again it adds another array item, and so on. It works, but I don't want it to keep adding array items.
10 seconds later another icon will appear to the top right, which currently has the one() method applied to it. As you can see nothing happens when you hover over it. Not sure where to go from here.
My randomize code (which I got from another StackOverflow answer):
var numRandoms = 14;
function makeUniqueRandom() {
if (!uniqueRandoms.length) {
for (var i = 0; i < numRandoms; i++) {
uniqueRandoms.push(i);
}
}
var index = Math.floor(Math.random() * uniqueRandoms.length);
var val = uniqueRandoms[index];
uniqueRandoms.splice(index, 1);
return val;
}
My code which currently 'works' but keeps adding more array items on hover:
$('img.button1').hover(function(){
$('p.trivia1').fadeIn("slow");
$( 'p.trivia1' ).append(makeUniqueRandom());
},
function(){
$("p.trivia1").stop().fadeOut("slow");
});
My code that uses one() but doesn't do anything on hover:
$('img.button2').one("hover",function(){
$('p.trivia2').fadeIn("slow");
$( 'p.trivia2' ).append(makeUniqueRandom());
},
function(){
$("p.trivia2").stop().fadeOut("slow");
});
Use mouseenter/mouseleave instead of hover
$('img.button1').on('mouseenter',function(){
$('p.trivia1').fadeIn("slow");
$( 'p.trivia1' ).append(makeUniqueRandom());
}).on('mouseleave',function(){
$("p.trivia1").stop().fadeOut("slow");
});

Nested function and else condition not working

I am practicing JS doing a project and have run into issues (again).
Just upfront, to explain what i want.
I have the top level buttons with nation names, on click a pic will fade into a container just for that. It gets the pic from the first array on line 1.This all works very well. However...
When that container is visible, I want a click handler on the "next" button to the right. This handler is one function (line 29-42) which animates the second div(.containsNext) by changing opacity and rotate values.
This function also calls another function (next, this should change the target div background with pics from the new Array) and has an if else statement.
The if condition works as it is supposed to.
The else condition does not run, even if i take out the nested next() function.
I think the error (console doesn't return one) on the next function is the lines 15 and 16, I know those lines look "funny":-)
And the if statement in the wrapper function does not work either.
How to fix this? Please make sure to select France, Italy or Croatia buttons, or the next button will not respond at all (do not know why either).
One more question on the side, what would be an economical way to store the pics for all the nations arrays selected/triggered by the next button?
Also how to do implement the proper nations array to be selected based on the top button nation selection?
Thank you guys
function
var imgLenght = 3;
var currentImg = 1;
function next() {
var imgContainer = document.querySelector(".containsNext");
if(currentImg > 0)
{
imgContainer.style.background = "url(" + "im[currentImg-1]" + ")";
currentImg = currentImg - 1;
}
}
Link to the pen:
http://codepen.io/damianocel/pen/gPggLB
use correctly nested quotes:
imgContainer.style.background = 'url("' + im[currentImg-1] + '")';

Replace ending on multiple img src

I have 10 buttons each with a different image and text. I have each button to click on/off and if another button is clicked I want the active button to turn off. I am struggling with the latter.
var x = 300;
//port1
$('#port1').click(
function(){
var src = $('.image', this).attr('src');
//var srcs = $(this).attr('src');
if($(this).hasClass("highlight")) {
$('.butt').removeClass('highlight');
$('.image', this).attr('src', src.replace(/_dark(\.[^.]+)?$/, '_light$1'));
$('.p1').fadeOut(x);
}
else{
$('.butt').removeClass('highlight');
// $('.butt').attr('src').replace('_dark.png', '_light.png');
$('.butt img').each(function() {
var src2 = $('.image').attr('src').replace(/_dark(\.[^.]+)?$/, '_light$1');
$('.image').attr('src', src2);
});
$('.talk').fadeOut(x);
$(this).addClass('highlight');
$('.image', this).attr('src', src.replace(/_light(\.[^.]+)?$/, '_dark$1'));
$('.p0').fadeOut(x);
$('.p1').fadeIn(x);
}
});
The problem I am running into is that when I click the button, it changes the src on all the other buttons to be exactly the same as this one and does not just change the ending on the other sources to '_dark'. I thought adding this 'each' function would help and it did not.
Edit: I am new to coding but i attempted a jsfiddle: http://jsfiddle.net/messedUP90/yxjoxe41/
The random computers that appear was the effect I am going for and the code I wrote to do it before I remembered that each icon was going to be different. Look at the first button titled "un" for where the error I am talking about happens.
http://jsfiddle.net/gtf1dk0m/1/
You need to re-set the variable src.
This code does it:
$('.butt').each( function( index ) {
if ( $(this).attr('src') ) {
$(this).attr('src', $(this).attr('src').replace(/_dark(\.[^.]+)?$/, '_light$1'));
}
});
ignore the fact that the image does not change color in the jsfiddle. it works in dreamweaver. :)
There is some strange code and naming conventions in this function... such as var src = $('.image', this).attr('src');... theres a lot unexplained by the question asked here and with no jsfiddle it's hard to imagine what you mean or see what HTML elements you're using...
so I will try to answer based on purely your description and not your code.
If you want to remove all instances of a class such as an active class you could simply do an each function however your later comments about it changing all other image sources once clicked is in this line $('.image').attr('src', src2);. You have effectively targeted all images under the class .butt which seems to be all of your images. Perhaps what you want is actually to iterate over all elements and remove the active state such as...
$(".butt img").each(function() {
//Remove Active Classes
if($(this).hasClass("activeImage")) {
$(this).removeClass("activeImage");
}
});
Then you are now free to take the clicked button and add its active state in...
$(".buttons").each(function() {
$(this).click(function() {
//Old Code
$(".butt img").each(function() {
//Remove Active Classes
if($(this).hasClass("activeImage")) {
$(this).removeClass("activeImage");
}
});
//New Code
$(this).addClass("activeImage");
});
});
Then in your CSS you could make sure that you have a rule like
.activeImage {
background-image: url("blah.png") !important;
/* You Get The Idea */
}

Categories