Loop Function on Mouseover in Vanilla Javascript - javascript

I am trying to create a carousel of images and wanted to horizontal scroll when the user hovers over the left and right side of the div. I have two "invisible" divs for the left and right controls and gave them eventListeners:
right.addEventListener("mouseover", goRight)
function goRight() {
document.getElementById('images').scrollLeft += 20;
}
left.addEventListener("mouseover", goLeft)
function goLeft() {
document.getElementById('images').scrollLeft -= 20;
}
When I hover over them, it will scroll once, but I would like it to continuously scroll until I mouseout. How I can I make goRight()/goLeft() loop while I am hovering on the controls?

One solution is to use the setInterval() method which should be cancelled on mouseout. You can store the interval id and use clearInterval() on mouseout:
const delay = 100;
let intervalId;
function goLeft() {
intervalId = setInterval(
() => (document.getElementById('images').scrollLeft -= 20),
delay,
);
}
function goRight() {
intervalId = setInterval(
() => (document.getElementById('images').scrollLeft += 20),
delay,
);
}
function stopScrolling() {
clearInterval(intervalId);
}
left.addEventListener('mouseover', goLeft);
left.addEventListener('mouseout', stopScrolling);
right.addEventListener('mouseover', goRight);
right.addEventListener('mouseout', stopScrolling);

You can create a Boolean that will be 'true' when the user has his mouse over the element.
// for the right side:
let mouseOverRight = false;
right.addEventListener("mouseenter", function(){
mouseOverRight = true;
});
right.addEventListener("mouseleave", function(){
mouseOverRight = false;
});
Then using an interval, change the delay to whatever speed you want
window.setInterval(function(){
if (mouseOverRight)
/// Scroll logic here
}, 300);
Then of course you would have to do the same for the left side.

Related

Why doesn't my mouseOver functions work?

The game is quite simple you click on the start button to begin then move your mouse along the track until you reach the end then the timer stops and shows you the score. If you go out of the track you get a score of zero.
Why don't my mouseOver functions work?
Link to my full code: http://www.codecademy.com/TictacTactic/codebits/AQBK4L/edit
Thank you in advance!
var score = 1000;
var timer = setInterval(countDown(), 1000);
$(document).ready(function() {
$('#start').click(function() {
$('#game').mouseover(function() {
stopTimer();
score = 0
$('#points').html(score)
});
$('#end').mouseover(function() {
stopTimer()
$('#points').html(score)
});
});
});
function countDown() {
score = score - 1;
}
function stopTimer() {
clearInterval(timer);
}
Most events are in lowercase, like mouseover, mouseout etc. There are also others that have capitals, like DOMContentLoaded. Most (if not all) programming languages are case-sensitive, watch out for these.
Try this
var clicked = false;
$('#start').click(function() {
if(!clicked){
clicked = true;
}
});
$("#game").hover(function(){
if(clicked){
stopTimer();
score = 0;
$("#points").html(score);
}
});
$("#end").hover(function(){
if(clicked){
stopTimer();
$("#points").html(score);
}
});
Then later if you don't want the hover event to work just set clicked to false I.E : clicked = false;

prevent animation double click issue

Hi I have problem with my slider please visit this site and check http://paruyr.bl.ee/
after click on my arrows it becomes work in an asynchronous way, ones it changes very fast and then slow and it repeats.
I think it is from start slider and stop slider.
var sliderPrev = 0,
sliderNext = 1;
$("#slider > img").fadeIn(1000);
startSlider();
function startSlider(){
count = $("#slider > img").size();
loop = setInterval(function(){
if (sliderNext>(count-1)) {
sliderNext = 0;
sliderPrev = 0;
};
$("#slider").animate({left:+(-sliderNext)*100+'%'},900);
sliderPrev = sliderNext;
sliderNext=sliderNext+1;
},6000)
}
function prev () {
var newSlide=sliderPrev-1;
showSlide(newSlide);
}
function next () {
var newSlide=sliderPrev+1;
showSlide(sliderNext);
}
function stopLoop () {
window.clearInterval(loop);
}
function showSlide(id) {
stopLoop();
if (id>(count-1)) {
id = 0;
} else if(id<0){
id=count-1;
}
$("#slider").animate({left:+(-id)*100+'%'},900);
sliderPrev = id;
sliderNext=id+1;
startSlider();
};
$("#slider, .arrows").hover(function() {
stopLoop()
}, function() {
startSlider()
});
function onlyNext () {
var newSlide=sliderPrev+1;
onlyShowSlide(newSlide);
}
function onlyShowSlide(id) {
if (id>(count-1)) {
id = 0;
} else if(id<0){
id=count-1;
}
$("#slider").animate({left:+(-id)*100+'%'},900);
sliderPrev = id;
sliderNext=id+1;
};
I think the best option would be to check if the animation is in progress and prevent the action if it is, something like this:
function prev () {
if(!$('#slider').is(":animated"))
{
var newSlide=sliderPrev-1;
showSlide(newSlide);
}
}
function next () {
if(!$('#slider').is(":animated"))
{
var newSlide=sliderPrev+1;
showSlide(sliderNext);
}
}
To illustrate the difference between this and just sticking a stop() in, check this JSFiddle. You will notice some choppy movements if you click multiple times in the stop() version.
What I would do is add a class to your slider when the animation starts and remove the class when it finishes:
$("#slider").animate({left:+(-id)*100+'%'}, {
duration: 900,
start: function() {
$('#slider').addClass('blocked');
},
complete: function() {
$('#slider').removeClass('blocked');
}
});
Now check on each click event if the slider is blocked or not:
function next () {
if (!$('#slider').hasClass('blocked')) {
var newSlide=sliderPrev+1;
showSlide(sliderNext);
}
}
This is a very simple solution, I'm sure there is a better one.
EDIT: As marcjae pointed out, you could stop the animations from queuing. This means when you double click, the slideshow still will move 2 slides. With my approach the second click will be ignored completely.
You can use a variable flag to control if the animation is still being done, or simply use .stop() to avoid stacking the animation.
$("#pull").click(function(){
$("#togle-menu").stop().slideToggle("slow");
});
It is occurring because your animations are being queued.
Try adding:
.stop( true, true )
Before each of your animation methods. i.e.
$("#slider").stop( true, true ).animate({left:+(-id)*100+'%'},900);
The answers about stop are good, but you have a bigger issue that is causing the described behavior. The issue is here:
$("#slider, .arrows").hover(function() {
stopLoop()
}, function() {
startSlider()
});
You have bound this to the .arrows as well as the #slider and the arrows are contained within the slider. So, when you mouse out of an arrow and then out of the entire slider, you are calling start twice in a row without calling stop between. You can see this if you hover onto the arrow and then off of the slider multiple times in a row. The slides will change many times after 6 seconds.
Similarly, consider the case of a single click:
Enter the `#slider` [stopLoop]
Enter the `.arrows` [stopLoop]
Click the arrow [stopLoop]
[startSlider]
Leave the `.arrows` [startSlider]
Leave the `#slider` [startSlider]
As you can see from this sequence of events, startSlider is called 3 times in a row without calling stopLoop inbetween. The result is 3 intervals created, 2 of which will not be stopped the next time stopLoop is called.
You should just have this hover on the #slider and more importantly, add a call to stopLoop as the first step in startSlider. That will ensure that the interval is always cleared before creating a new one.
$("#slider").hover(function() {
stopLoop()
}, function() {
startSlider()
});
function startSlider(){
stopLoop();
/* start the slider */
}

A Function to Check if the Mouse is Still Hovering an Element Every 10 Milliseconds (and run a function if it is)

I was wondering if there is a function to be run after an element (e.g. div class="myiv") is hovered and check every X milliseconds if it's still hovered, and if it is, run another function.
EDIT: This did the trick for me:
http://jsfiddle.net/z8yaB/
For most purposes in simple interfaces, you may use jquery's hover function and simply store in a boolean somewhere if the mouse is hover. And then you may use a simple setInterval loop to check every ms this state. You yet could see in the first comment this answer in the linked duplicate (edit : and now in the other answers here).
But there are cases, especially when you have objects moving "between" the mouse and your object when hover generate false alarms.
For those cases, I made this function that checks if an event is really hover an element when jquery calls my handler :
var bubbling = {};
bubbling.eventIsOver = function(event, o) {
if ((!o) || o==null) return false;
var pos = o.offset();
var ex = event.pageX;
var ey = event.pageY;
if (
ex>=pos.left
&& ex<=pos.left+o.width()
&& ey>=pos.top
&& ey<=pos.top+o.height()
) {
return true;
}
return false;
};
I use this function to check that the mouse really leaved when I received the mouseout event :
$('body').delegate(' myselector ', 'mouseenter', function(event) {
bubbling.bubbleTarget = $(this);
// store somewhere that the mouse is in the object
}).live('mouseout', function(event) {
if (bubbling.eventIsOver(event, bubbling.bubbleTarget)) return;
// store somewhere that the mouse leaved the object
});
You can use variablename = setInterval(...) to initiate a function repeatedly on mouseover, and clearInterval(variablename) to stop it on mouseout.
http://jsfiddle.net/XE8sK/
var marker;
$('#test').on('mouseover', function() {
marker = setInterval(function() {
$('#siren').show().fadeOut('slow');
}, 500);
}).on('mouseout', function() {
clearInterval(marker);
});​
jQuery has the hover() method which gives you this functionality out of the box:
$('.myiv').hover(
function () {
// the element is hovered over... do stuff
},
function () {
// the element is no longer hovered... do stuff
}
);
To check every x milliseconds if the element is still hovered and respond adjust to the following:
var x = 10; // number of milliseconds
var intervalId;
$('.myiv').hover(
function () {
// the element is hovered over... do stuff
intervalId = window.setInterval(someFunction, x);
},
function () {
// the element is no longer hovered... do stuff
window.clearInterval(intervalId);
}
);
DEMO - http://jsfiddle.net/z8yaB/
var interval = 0;
$('.myiv').hover(
function () {
interval = setInterval(function(){
console.log('still hovering');
},1000);
},
function () {
clearInterval(interval);
}
);

Javascript "while hovered" loop

Can anybody help me on this one...I have a button which when is hovered, triggers an action. But I'd like it to repeat it for as long as the button is hovered.
I'd appreciate any solution, be it in jquery or pure javascript - here is how my code looks at this moment (in jquery):
var scrollingposition = 0;
$('#button').hover(function(){
++scrollingposition;
$('#object').css("right", scrollingposition);
});
Now how can i put this into some kind of while loop, so that #object is moving px by px for as #button is hovered, not just when the mouse enters it?
OK... another stab at the answer:
$('myselector').each(function () {
var hovered = false;
var loop = window.setInterval(function () {
if (hovered) {
// ...
}
}, 250);
$(this).hover(
function () {
hovered = true;
},
function () {
hovered = false;
}
);
});
The 250 means the task repeats every quarter of a second. You can decrease this number to make it faster or increase it to make it slower.
Nathan's answer is a good start, but you should also use window.clearInterval when the mouse leaves the element (mouseleave event) to cancel the repeated action which was set up using setInterval(), because this way the "loop" is running only when the mouse pointer enters the element (mouseover event).
Here is a sample code:
function doSomethingRepeatedly(){
// do this repeatedly when hovering the element
}
var intervalId;
$(document).ready(function () {
$('#myelement').hover(function () {
var intervalDelay = 10;
// call doSomethingRepeatedly() function repeatedly with 10ms delay between the function calls
intervalId = setInterval(doSomethingRepeatedly, intervalDelay);
}, function () {
// cancel calling doSomethingRepeatedly() function repeatedly
clearInterval(intervalId);
});
});
I created a sample code on jsFiddle which demonstrates how to scroll the background-image of an element left-to-right and then backwards on hover with the code shown above:
http://jsfiddle.net/Sk8erPeter/HLT3J/15/
If its an animation you can "stop" an animation half way through. So it looks like you're moving something to the left so you could do:
var maxScroll = 9999;
$('#button').hover(
function(){ $('#object').animate({ "right":maxScroll+"px" }, 10000); },
function(){ $('#object').stop(); } );
var buttonHovered = false;
$('#button').hover(function () {
buttonHovered = true;
while (buttonHovered) {
...
}
},
function () {
buttonHovered = false;
});
If you want to do this for multiple objects, it might be better to make it a bit more object oriented than a global variable though.
Edit:
Think the best way of dealing with multiple objects is to put it in an .each() block:
$('myselector').each(function () {
var hovered = false;
$(this).hover(function () {
hovered = true;
while (hovered) {
...
}
},
function () {
hovered = false;
});
});
Edit2:
Or you could do it by adding a class:
$('selector').hover(function () {
$(this).addClass('hovered');
while ($(this).hasClass('hovered')) {
...
}
}, function () {
$(this).removeClass('hovered');
});
var scrollingposition = 0;
$('#button').hover(function(){
var $this = $(this);
var $obj = $("#object");
while ( $this.is(":hover") ) {
scrollingposition += 1;
$obj.css("right", scrollingposition);
}
});

Detecting when the mouse is not moving

I am able to find the cursor position. But I need to find out if the mouse is stable. If the mouse wasn't moved for more than 1 minute, then we have to alert the user.
How its possible, are there any special events for this? (Only for IE in javascript)
Set a timeout when the mouse is moved one minute into the future, and if the mouse is moved, clear the timeout:
var timeout;
document.onmousemove = function(){
clearTimeout(timeout);
timeout = setTimeout(function(){alert("move your mouse");}, 60000);
}
Here's a one-and-done function that can check any element for movement:
function mouse (element, delay, callback) {
// Counter Object
element.ms = {};
// Counter Value
element.ms.x = 0;
// Counter Function
element.ms.y = function () {
// Callback Trigger
if ((++element.ms.x) == delay) element.ms.callback(element, element.ms);
};
// Counter Callback
element.ms.callback = callback;
// Function Toggle
element.ms.toggle = function (state) {
// Stop Loop
if ([0, "off"][state]) clearInterval(element.ms.z);
// Create Loop
if ([1, "on"][state]) element.ms.z = setInterval(element.ms.y, 1);
};
// Function Disable
element.ms.remove = function () {
// Delete Counter Object
element.ms = null; return delete element.ms;
};
// Function Trigger
element.onmousemove = function () {
// Reset Counter Value
element.ms.x = -1;
};
// Return
return element.ms;
};
Usage:
mouse(element, delay, callback)
Examples:
Make a video player hide the mouse after 5 seconds when idle and fullscreen
let x = mouse(video, 5000, function (a) {
if (document.webkitIsFullScreen) video.style.cursor = "none";
});
x.toggle(1); addEventListener("mousemove", function () {
video.style.cursor = "auto";
});
Chat Room AFK (45 Seconds) (assuming you have a chat box and a send message function):
let x = mouse(chatBox, (45e3), function (a) {
chatBox.send({ text: chatBox.username + " is AFK.", italic: true });
});
x.toggle(1); x.addEventListener("mousemove", function () {
chatBox.send({ text: chatBox.username + " is no longer AFK", italic: true });
});
Is there not a way to set a timer to start incrementing after every mouse movement event?
If it gets to a minute then pop up the message box, but every time the mouse moves the timer gets reset.
Use a timer that resets its value on mousemove event.
If timer reaches 1 minute --> Do something.
More info on timer here http://www.w3schools.com/js/js_timing.asp
And more info on catchin mouse events here http://www.quirksmode.org/js/events_mouse.html
Yes, you have a onmousemove event in Javascript, so to achieve what you need you just have to do code something like this:
startTimer();
element.onmousemove = stopTimer(); //this stops and resets the timer
You can use it on the document body tag for instance.
UPDATE: #Marius has achieved a better example than this one.
You can use the onmousemove event. Inside it, clearTimeout(), and setTimeout(your_warning, 1 minute).
You could use this script/snippet to detect the mouse pointer position and "remember" it. Then use a timer "setTimeout(...)" to check the position let's say every second and remember that time.
If more than one minute passed and the position hasn't changed, you could alert the user.

Categories