JavaScript repeat action when mouse held down - javascript

Is there to have a JavaScript function repeated every so many milliseconds that an html button is held down? It would be great if this could be done with standard JavaScript, but using jQuery or a jQuery plugin would be great too.

On the mousedown() event, this code starts a repeating timer (every 500ms in this example) that is cancelled as soon as the mouseup() event occurs. This should be adaptable to what you want:
var intervalId;
$("#button").mousedown(function() {
intervalId = setInterval(do_something, 500);
}).mouseup(function() {
clearInterval(intervalId);
});
function do_something() {
// whatever
}
See setInterval() for more information on clearing timers.

I would use the javascript function setInterval() within a function that gets called on mouse down.
<input type="button" id="button" onmousedown="inter=setInterval(startAction, 1*1000);"
onmouseup="clearInterval(inter);" value="click here" />
<script type="text/javascript">
function startAction(){
//whatever you want done
}
</script>

var intervalId;
$("#button").mousedown(function() {
intervalId = setInterval(do_something, 500);
}).mouseup(function() {
clearInterval(intervalId);
}).mouseleave(function() {
//this should help solve the problem that occurs when the mouse leaves the button while pressed down
clearInterval(intervalId);
});
function do_something() {
// whatever
}

I see a problem with both solutions listed above.
onmouseup is only triggered if the mouse is released while it is over the button. If the user keeps the mouse down then moves the mouse away before releasing it then clearInterval is never fired and so do_something will fire forever.
You would need to add another event, "onmouseout", that also calls clearInterval.

Related

Clearing an interval does not work

I'm working on a rather strange and complex function. The idea is that there is a timer that runs a slider. This timer gets cleared when the slider is hovered (i.e. the slider stopts moving). I would also like the timer to be cleared when the slider (or, rather, its parent container) is out of view. With the plugin inview I can check if an element is in the viewport or not. So when I see that the parent element is not in the viewport anymore, I clear the timer. However, this is not working and I can't figure out why. Clearing the timer on hover does work. Here is a fiddle.
The part that is not working:
$("body > .section").bind('inview', function (event, isInView) {
var $this = $(this);
if (isInView) {
// Päuse Twitter slider if it's not in the viewport
if (!$this.is(".twitter")) {
clearInterval(timer);
console.log("Timer cleared");
$(".twitter .article.focus").addClass("pause");
} else {
$(".twitter .article").removeClass("pause");
startTimer();
console.log("Timer restart");
}
}
});
As you can see, the events are logged in console, so they are triggered, but the slider does not stop (as you can see in console: classes are still assigned and remove to the .articles inside .twitter. This means that the timer isn't cleared. But why not? I can't figure it out. The timer is set globally, so that should not be a problem.
EDIT: oh apparently the clearing of the timer on hover doesn't work either... It is strange, because all the console.logs do work. AND timer is set as a global variable.
The key is not to start the timer more times. The inview jQuery plugin fires the inview event anytime you reach top or bottom of the watched element and in your example you start new timer everytime this happens. And since the new timer replaces the timer you already had set up, you lose track of that old timer and cannot clear it afterwards.
Try abstracting the start & pause code and everytime you start, check if the timer is started. For example like this:
function startSlider() {
if (!timer) {
startTimer();
}
}
function pauseSlider() {
clearInterval(timer);
timer = null;
}
I have updated the jsfiddle where you can see it working in action.

Fade in or fade out based on scroll

$(document).scroll(function () {
var y = $(this).scrollTop();
if (y > 397) {
$('#aboutNav.fixed').fadeIn(500);
} else {
$('#aboutNav.fixed').hide();
}
});
As you can tell, this shows a fixed navigation. The CSS is fine, the positioning is great. However I want the navigation to become visible above 397px which it does fine.
However I want the navigation to fade in when I start scrolling:
.fadeIn(500);
When the user starts stops to look at content or whatever, I want the element to fade out
.delay(3000).fadeOut(350);
I believe this is something that can be done by doing an if statement within the first if statement. However a script to check if the user is scrolling and the working script above seem to collide.
Ideas, anyone?
If I understand you correctly. You want the nav to fade in if its above 397px and only when its scrolling... So this function will do that. If I misunderstood your question please clarify in the comments
$(window).scroll(function() {
clearTimeout($.data(this, 'scrollTimer'));//Lets the timer know were scrolling
//Hide/Show nav based on location
var y = $(this).scrollTop();
if (y > 397) {
$('#aboutNav.fixed').fadeIn(500);
} else {
$('#aboutNav.fixed').hide();
}
//TimeOut function that is only hit if we havent scrolled for 3 Seconds
//In here is where you fade out the nav
$.data(this, 'scrollTimer', setTimeout(function() {
$('#aboutNav.fixed').fadeOut();
console.log("Haven't scrolled in 3s!");
}, 3000));
});
JAN 23 UPDATE based on your comment
You can add this to you $(document).ready() function
$("#elementID").hover(function(){
//show here (mouse over)
$("#elementToShow").show();
},function(){
//Start timeout here, (mouse out)
setTimeout(function() {
$("#elementToHide").hide();
}, 3000);
}
Expanding on what Kierchon's answer a bit:
Since there's no real way to tell when the user is done scrolling (i.e. no event for 'finished scrolling') you'll have to use a event-delaying method called debouncing.
Debouncing is basically setting a timeout to run some code (a function) in the future, and if the event calling the debounced function get called again, you clear and reset the timeout, doing this repeatedly until the event finally stops being called. This method is to prevent events that fire repeatedly (such as scroll and resize) to only execute things after the final event fires and your delayed (debounced) code finally executes.
Here is a nice article on use of debouncing methods in JS.
As long as I understand what you need (which I think I do) - Here's a JSBin with some working code

Javascript setInterval functionality to onmousedown event

I am trying to create a Virtual Keyboard using Javascript and an SVG keyboard image.
I have been able to access the onmousedown property of a 'button' element and make a call to myFunction when that button is pressed.
button.onmousedown = (function(self) {
return function() { self.myFunction(); };
})(this);
I was hoping to add a repeat key feature and want to incorporate setInterval so that myFunction repeats every second or so. I am having trouble incorporating the setInterval into the onmousedown functionality. Should I try to add setInterval to above code or add it to myFunction? I want to use just basic Javascript. Thanks in advance.
var interval;
button.addEventListener('mousedown', function() {
interval = setInterval(doSomething, 20);
});
button.addEventListener('mouseup', function () {
clearInterval(interval);
});
function doSomething()
{
//your code here
}
Something like this?
Live example: http://cssdeck.com/labs/cbpb6qqm

jQuery - stop animation in progress (fadeOut) and show again when mouse enters/leaves quickly

I have a <div> that when hovered over, will show some text. When the mouse leaves, the text fades out. However, if the mouse enters the <div> again before the fadeOut is complete, the text never shows again.
I am aware of hoverintent, but I'd prefer not to use it because of the slight perceived delay it gives to the mouseEnter/mouseLeave events.
Is there no way that, upon mouseEnter, it simply clears the fadeOut and shows the text again?
My current attempt using timeouts:
var timeouts = {};
$(document).ready(function(){
$('#wrapper').hover(function(){
clearTimeout(timeouts['test_hover']);
$('#text').show();
}, function(){
timeouts['test_hover'] = setTimeout(function(){
$('#text').fadeOut('slow');
});
});
});
jsbin: http://jsbin.com/upotuw/5
video: http://www.youtube.com/watch?v=7RLrz1bEQuU
--
EDIT: Issue was needing to pass both parameters to the stop() function: stop(true,true)
Final working code is as follows:
var timeouts = {};
$(document).ready(function(){
$('#wrapper').hover(function(){
clearTimeout(timeouts['test_hover']);
$('#text').stop(true,true).show();
}, function(){
timeouts['test_hover'] = setTimeout(function(){
$('#text').fadeOut('slow');
});
});
});
http://jsbin.com/upotuw/7
You want to look into the JQuery stop() function:
http://api.jquery.com/stop/

jQuery continuously scales a div element using hover()

I recently tried to use jQuery's effect('scale') function with the hover() function in jQuery. The idea is to enlarge the div element on mouseenter, and shrink it back to normal on mouseleave. The code is as follows:
$('.boxgrid').hover(function(){
$(this).effect('scale', {percent:125}, 1000);
}, function() {
$(this).effect('scale', {percent:80}, 1000);
});
I tried testing this in a jsfiddle, but instead of upscaling and downscaling once when a mouse enters the element, it keeps enlarging it. You can see the jsfiddle here. My question is how do I fix it? My understanding was that the mouseenter event was fired only once, and reset when the mouseleaves event is fired, but this seems to say otherwise? Am I missing something? Any help is greatly appreciated.
It calls the hover function every time the animation finishes. I modified it as follows and it appears to work:
window.boxScaled = false;
$('.boxgrid').hover(function(){
if(!window.boxScaled) {
window.boxScaled = true;
$(this).effect('scale', {percent:125}, 1000);
}
}, function() {
if(window.boxScaled) {
window.boxScaled = false;
$(this).effect('scale', {percent:80}, 1000)
}
});
I think you need to force the animation to stop if you leave the box before it has finished scaling (or reenter the box before it has shrunk):
$('.boxgrid').hover(function(){
$(this).stop().effect('scale', {percent:125}, 1000);
}, function() {
$(this).stop().effect('scale', {percent:80}, 1000);
});
http://jsfiddle.net/magicaj/9GLEy/10/
Your understanding of hover (mouseenter/mouseleave) is correct, they should only fire once upon entering/leaving.

Categories