Revealing items on hover, hide them after X seconds - javascript

I'm trying to accomplish a "reveal" effect where I show items from a grid when hovering them.
Everything's OK here but once revealed I want to make them disappear again after X seconds – so it's not that when you move the mouse from the item they disappear inmediately.
That's what I tried so far but the items are not going back to their "unrevealed" state after I leave the mouse from the item.
var timeout;
$(".home-box").hover(function () {
clearTimeout(timeout);
$(this).css("opacity", 1);
}, function () {
timeout = setTimeout(function(){
$(this).css("opacity", 0);
},500);
});
Does anyone have any idea about how to solve it?
Thanks in advance.

You should use mouseenter and mouseleave events and add separate functionalities in each.
The reference to this might be lost in the callback function passed to setTimeout.
$(".home-box").mouseenter(function() {
clearTimeout(timeout);
$(this).css("opacity", 1);
});
$(".home-box").mouseleave(function() {
var $element = $(this)
timeout = setTimeout(function(){
$element.css("opacity", 0);
},500);
});

Was it necessary? I used the event mouseover instead of the hover, as the hover will always fire when the mouse moves, even if you try to move the cursor away from the object.
$(".home-box").mouseover(function () {
$('img').css("opacity", 1);
setTimeout(function(){
$('img').css("opacity", 0);
}, 2000);
});
.home-box {
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
border: 1px solid green;
position: relative;
}
img {
opacity: 0;
position: absolute;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="home-box">
hover me pls and wait...
<img src="https://im0-tub-ru.yandex.net/i?id=1a59e5c138260403e2230f0d2b264513&n=13">
</div>

The issue is that this has a different meaning within the setTimeout - you can store the box (this) and reuse it.
var timeout;
$(".home-box").hover(function() {
clearTimeout(timeout);
$(this).css("opacity", 1);
}, function() {
var box = this;
timeout = setTimeout(function() {
$(box).css("opacity", 0);
}, 500);
});

Related

Unable to animate the icons with Javascript

I am trying to animate 4 icons to simulate wifi signals with Javascript, hower after the last signal is reached
the animation does not restart again.
Here is what i have tried.
I would appreciate any help and idea how to achieve this either with
CSS or Javascript.
function makeSignal(){
let wifi_icon = document.getElementById("wifi-signal");
wifi_icon.classList.add('ri-signal-wifi-line');
setTimeout(function() {
wifi_icon.classList.remove('ri-signal-wifi-line');
wifi_icon.classList.add('ri-signal-wifi-1-line');
}, 500);
setTimeout(function() {
wifi_icon.classList.remove('ri-signal-wifi-1-line');
wifi_icon.classList.add('ri-signal-wifi-2-line');
}, 1000);
setTimeout(function(){
wifi_icon.classList.remove('ri-signal-wifi-2-line');
wifi_icon.classList.add('ri-signal-wifi-3-line');
}, 1500);
}
makeSignal();
setInterval(makeSignal, 2000);
#signal {
display: block;
width: 100px;
height: 100px;
margin: 5px auto;
}
<link href="https://cdn.jsdelivr.net/npm/remixicon#2.5.0/fonts/remixicon.css" rel="stylesheet">
<div id="signal">
<i id="wifi-signal" class="ri-5x"></i>
</div>
Well, I have no idea if this works, but it seems that in the last setTimeout, you use wifi_icon.classList.add('ri-signal-wifi-3-line') and then, at the start of the function (next loop), you never remove that class. So add something like:
let wifi_icon = document.getElementById("wifi-signal");
wifi_icon.classList.remove('ri-signal-wifi-3-line');
wifi_icon.classList.add('ri-signal-wifi-line');

Temporarily Stop One Function Execution with setTimeOut() when a Button is Clicked

I have an animation triggered by a scroll event, which makes a menu slide out of view. There is also a button that when clicked brings the menu back into view.
Because the menu can be closed by scrolling, when the user clicks the button to bring the menu in, if they scroll during this period of the animation, the menu disappears again without the animation completing.
I have put together a simplified version of the animation here http://codepen.io/emilychews/pen/evbzMQ
I need to temporarily prevent the scroll function working after the button is clicked, which I'm assuming would be best done with the setTimeout() method on the click function? I've tried a number of things but can't seem to solve it/ get it to work.
Any help would be awesome. For quick reference as well the code is below
JQUERY
jQuery(document).ready(function($){
// slide menu to left on scroll
function hideOnScroll() {
$(window).scroll(function() {
if ( $(document).scrollTop() > 1) {
$('.menubox').css('left', '-25%');
}
});
}
hideOnScroll(); // call hideOnScroll function
// click handler to bring menu back in
$('.mybutton').on('click', function() {
$('.menubox').css('left', '0%');
var scrollPause = setTimeout(hideOnScroll, 2000) // temporarily pause hideOnScroll function
});
}); //end of jQuery
CSS
body {
margin: 0;
padding: 0;
height: 200vh;}
.menubox {
top: 100;
position: fixed;
width: 20%;
height: 100%;
background: red;
padding: 10px;
color: white;
transition: all 2s;
}
.mybutton {
position: fixed;
left: 40%;
top: 50px;
padding: 5px 10px;
}
HTML
<div class="menubox">Menu Box</div>
<button class="mybutton">Click to bring back menu</button>
** Also please note I've simplified the animation for the sake of the forum, the actual animation function contains Greensock code, but I didn't want to include this in case it confused the issue. I can't therefore just use the .addClass() and .removeClass() or have a workaround that changes the given CSS or scrollTop() values. I need to disable the hideOnScroll() function when the button is clicked for the duration of the click invoked animation - which in the examples is 2s. Thus I think the only way to achieve this is with the setTimeOut() method (i may be wrong on this). But I can't get it to work.
Many thanks
Emily
you can simply check the offset is complete.
function hideOnScroll() {
$(window).scroll(function() {
if ( $(document).scrollTop() > 1) {
if( $('.menubox').offset().left == 0 ){
$('.menubox').css('left', '-25%');
}
});
}
http://codepen.io/anon/pen/aJXGbr
I have made a few changes in your javascript. Have a look
var animating = false;
$(document).ready(function(){
function hideOnScroll() {
$(window).scroll(function() {
event.preventDefault();
if ( $(document).scrollTop() > 1 && !animating){
console.log("Hiding")
animating = true;
$('.menubox').animate({'left': '-25%'},2000,function(){
animating = false;
});
}
});
}
hideOnScroll();
$('.mybutton').click(function() {
var pos = $(window).scrollTop();
animating = true;
$('.menubox').animate({'left':'0%'},2000,function(){
console.log("Finished Opening");
animating = false;
});
console.log("Animating Open");
var siId = setInterval(function(){
if(animating){
console.log("Preventing Window Scrolling.");
$(window).scrollTop(pos);
}
else{
console.log("Stopping setInterval");
animating = false;
clearInterval(siId);
}
},0);
});
});
This will stop your browser window from scrolling until your Menu Open Animation is finished.
Also I have removed the transitionproperty from style.
Tested in Google Chrome.
Kindly inform me if i have misinterpreted your question.

jQuery doesn't show and hide the header

I'm trying to make a header that appears at a certain place of the page.
So what I'm doing is checking the scroll to top of the page and the top offset of the element after which the header should appear. If the scrollTop is greater than offset the header is shown, otherwise it disappears.
But! When I scroll to the place, the header position is constantly switching between top: -13% and top: -12.999998%. After some time it finally shows the header but it never disappears.
What am I doing wrong?!
JSFiddle: https://jsfiddle.net/5k5s016f/
Well, i think the problem is that the .animate() functions are running constantly, causing the animations to "restart" before its ends.
It is not the most beautiful solution, but just adding a flag that controls the execution of the functions and a timeout to run the handler less frequently solves the problem.
https://jsfiddle.net/5k5s016f/2/
var visible = false;
$(window).scroll(function() {
setTimeout(function(){
var height = $(window).scrollTop();
var $page2 = $("#page2");
var offset = $page2.offset().top;
if (height > offset) {
if (visible) {
return;
}
visible = true;
$(".floating-header").show().animate({
top: 0
});
} else {
if (!visible) {
return;
}
visible = false;
$(".floating-header").animate({
top: "-13%"
});
}
}, 200)
});
The issue you are seeing is because each time a scroll event gets called animation queues up. If you wait long enough, you can see that the animation to set top to 0 actually works.
You can use the stop() function to stop all animation before attempting to run another one.
Something like this
if (height > offset) {
$(".floating-header").stop().show().animate({
top: "0"
}, 700);
} else {
$(".floating-header").stop().animate({
top: "-13%"
}, 700);
}
A couple of improvements I can suggest are
Debounce the scroll event handler
Check the current state of the header before queuing animation. i.e. do not try to hide it if it is already hidden and vice versa
Your logic is all messed up. Basically, you want to make sure that you are only animating when you absolutely need to - no more, no less. And since scroll events happen hundreds of times... constantly rapid firing as the user scrolls... you want to make sure you are doing the least amount of work possible during each scroll event. This especially means that you don't want to be querying the DOM on every scroll event if you don't have to (ps. $('selector') is a dom query). Take a look at this fiddle:
https://jsfiddle.net/5k5s016f/6/
Looks like I'm last to the party due to interruptions, but since I wrote it up I'll post the answer FWIW.
jsFiddle Demo
You need to debounce your code. Here is a simple system, but studing Ben Alman's explanation/examples is also recommended.
var $m1 = $('#m1'), $m2 = $('#m2'); //TESTING ONLY
var $win = $(window), $page2 = $("#page2"), $hdr=$(".floating-header");
var $offset = $page2.offset().top;
var hvis = false, curpos;
$win.scroll(function() {
curpos = $win.scrollTop();
$m1.html(curpos); //TESTING ONLY
$m2.html($offset);//TESTING ONLY
if ( curpos > $offset ) {
if ( !hvis ){
hvis = true;
//$m1.html(curpos);
$hdr.finish().animate({
top: "0"
}, 700);
}
} else {
if ( hvis ){
$hdr.finish().animate({
top: "-60px"
}, 700);
hvis = false;
}
}
});
html,
body {
height: 100vh;
width: 100vw;
}
#page1,
#page2,
#page3 {
height: 100%;
width: 100%;
background-color: #fff;
}
.floating-header {
position: fixed;
top: -60px;
background-color: #000;
width: 100%;
height: 60px;
}
.msg{position:fixed;bottom:10px;height:30px;width:80px;text-align:center;}
.msg{padding-top:10px;}
#m1 {left:3px; border:1px solid orange;background:wheat;}
#m2 {right:3px;border:1px solid green; background:palegreen;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<header class="floating-header">Header</header>
<div id="page1">
<p>Page1</p>
</div>
<div id="page2">
<p>Page2</p>
</div>
<div id="page3">
<p>Page3</p>
</div>
<div id="m1" class="msg"></div>
<div id="m2" class="msg"></div>

SetInterval times not running correctly

I've inherited a bug to look at consisting of two images that "flip" and use set interval to time when this happens.
From what I believe the initial change should happen after 4 seconds, then for each image change every 12 seconds (obviously this isn't important at the minute).
At the moment the first image changes at 4 seconds and the second one at around 8.
I'm also open to any improvements that can be made to this code as well.
//SPINNING LOGO
if ($("#flipLogo").length) {
function spinLogo() {
$('#flipLogo').addClass("active");
$('#flipLogo2').addClass("active");
// console.log("yup yup");
setTimeout(function () {
$('#flipLogo').removeClass("active");
$('#flipLogo2').removeClass("active");
}, 4000);
clearInterval();
}
setInterval(function () {
spinLogo();
clearInterval();
}, 12000);
}
I believe you are looking for $.toggleClass to switch between the active states.
Additionally, as Hacketo said you are calling clearInterval wrong - it should be called with the return value of setInterval if you want to stop the interval (I don't think you want to do this?)
Try this:
//SPINNING LOGO
function spinLogo() {
// Flip the active classes on or off
$('#flipLogo').toggleClass("active");
$('#flipLogo2').toggleClass("active");
}
if ($("#flipLogo").length) {
// after 4 seconds
setTimeout(function() {
// flip the logo
spinLogo();
// Set a timer to flip it again every 12 seconds
setInterval(spinLogo, 12000);
}, 4000);
}
Here it is in action:
//SPINNING LOGO
function spinLogo() {
// Flip the active classes on or off
$('#flipLogo').toggleClass("active");
$('#flipLogo2').toggleClass("active");
}
if ($("#flipLogo").length) {
// after 4 seconds
setTimeout(function() {
// flip the logo
spinLogo();
// Set a timer to flip it again every 12 seconds
setInterval(spinLogo, 12000);
}, 4000);
}
.flippable {
width: 100px;
height: 100px;
border: 1px solid black;
text-align: center;
display: none;
color: white;
}
.flippable.active {
display: block;
}
#flipLogo {
background: blue;
}
#flipLogo2 {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="flipLogo" class="flippable active">Logo 1</div>
<div id="flipLogo2" class="flippable">Logo 2</div>
(ps it is bad form to define functions inside if statements, as hoisting will move them them to a place you might not expect)

how to give effect like youTube has on mouse movement,

How to apply event of mousemove, so we can get effect like vlc player has for seekbar, or Youtube has for VideoTitle.
i.e : On mouse movement show title, if mouse not moved then hide title
Why need : I am developing website something like video library, there is one seekbar which I want to disable when mouse is not moved till someminute, and if mouse move then make it visible.
What I Did :
document.body.onmousedown = function() {
$(".myPrivateSeek").hide();
};
document.body.onmouseup = function() {
$(".myPrivateSeek").show();
};
althought its wroking,Unfortunately its not so much helpfull,
You can make use of mousemove event.
Below is a working code for that , you can play with it here in JSfiddle and modify as you want.
HTML
<div id="item">
<p>This is my item</p>
<div class="tooltip">Tooltip</div>
</div>
CSS
#item {
position: relative;
background: #CCC;
}
#item .tooltip {
position: fixed;
width: 80px;
height: 30px;
background: #06F;
z-index: 10;
display: none;
}
jQuery
$(document).ready(function() {
$("#item").on('mousemove', function(e) {
$('.tooltip').css('left', e.pageX + 10).css('top', e.pageY + 10).css('display', 'block');
});
$("#item").mouseout(function() {
$('.tooltip').css('display', 'none');
});
});
If you would like it so that on mouse movement your element appears then after a specified time of no movement it automatically disappears you could implement the following:
$(document).ready(function () {
var timeoutId;
//Replace document.body with the element you wish the mouse movement to be recognised within.
$(document.body).on('mousemove', function () {
//Checks if an existing timeout function exists, if so remove it.
if (timeoutId) {
clearTimeout(timeoutId);
}
$(".myPrivateSeek").show();
//Set a callback for how long to wait after the mouse has stopped moving to hide your element.
timeoutId = setTimeout(function () {
$(".myPrivateSeek").hide();
}, 1000); //The time in milliseconds to wait.
});
});

Categories

Resources