How to check mouse holded some sec on a element - javascript

How we can check mouse holed some seconds on an element.
Means that the function should execute only if the user holds the mouse more than minimum seconds(eg:3 sec) on an element.
Many of the answers found in the stack, but that solutions are delaying the execution, but I want to check mouse holed or not, If yes, execute the function else don't make any action.
Already asked same question before, but not yet get the answer exactly what I looking
Is it possible?

I think you are looking for this, here if a div gets hover and hold mouse for at least 3 seconds then do your stuff like below
var myTimeout;
$('div').mouseenter(function() {
myTimeout = setTimeout(function() {
alert("do your stuff now");
}, 3000);
}).mouseleave(function() {
clearTimeout(myTimeout);
});

here's a custom jquery function for that
$.fn.mouseHover = function(time, callback){
var timer;
$(this).on("mouseover", function(e){
timer = setTimeout(callback.bind(this, e), time);
}.bind(this)).on("mouseout", function(e){
clearTimeout(timer);
})
};
$('#my-element').mouseHover(3000, function(){ alert("WHOOPWhOOP");});
just in case OP meant click and hold.
$.fn.mouseHold = function(time, callback) {
var timer;
$(this).on("mousedown", function(e){
e.preventDefault();
timer = setTimeout(callback.bind(this, e), time);
}.bind(this)).on("mouseup", function(e){
clearTimeout(timer);
})
}
jsfiddle: http://jsbin.com/huhagiju/1/

Should be easy enough:
$('.your-element').on('mousedown', function(event) {
var $that = $(this);
// This timeout will run after 3 seconds.
var t = setTimeout(function() {
if ($that.data('mouse_down_start') != null) {
// If it's not null, it means that the user hasn't released the click yet
// so proceed with the execution.
runMouseDown(event, $that);
// And remove the data.
$(that).removeData('mouse_down_start');
}
}, 3000);
// Add the data and the mouseup function to clear the data and timeout
$(this)
.data('mouse_down_start', true)
.one('mouseup', function(event) {
// Use .one() here because this should only fire once.
$(this).removeData('mouse_down_start');
clearTimeout(t);
});
});
function runMouseDown(event, $that) {
// do whatever you need done
}

Checkout
Logic
The mousedown handler records the click start time
The mouseup handler records the mouse up time and calculate time difference if it exceeds 3 secs then alerts the time else alerts less than 3 seconds
HTML
<p>Press mouse and release here.</p>
Jquery
var flag, flag2;
$( "p" )
.mouseup(function() {
$( this ).append( "<span style='color:#f00;'>Mouse up.</span>" );
flag2 = new Date().getTime();
var passed = flag2 - flag;
if(passed>='3000')
alert(passed);
else
alert("left before");
console.log(passed); //time passed in milliseconds
})
.mousedown(function() {
$( this ).append( "<span style='color:#00f;'>Mouse down.</span>" );
flag = new Date().getTime();
});

This is all about logic.
You just have a variable to tell you if you have been listening on this for some time like 3 seconds.
If you are listening for more than that, which is not possible since you should had reset it, so then reset it. Else you do your work.
var mySpecialFunc = function() { alert("go go go..."); };
var lastTime = 0;
var main_id = "some_id" ;// supply the id of a div over which to check mouseover
document.getElementById(main_id).addEventListener("mouseover",function(e) {
var currTime = new Date().getTime();
var diffTime = currTime - lastTime;
if(diffTime > 4000) {
// more than 4 seconds reset the lastTime
lastTime = currTime;
alert("diffTime " + diffTime);
return ;
}
if(diffTime > 3000) {
// user had mouseover for too long
lastTime = 0;
mySpecialFunc("info");
}
// else do nothing.
});
This is a basic code, i think you can improve and adjust according to your requirements.

Here's some code (with a fiddle) that does what you want...
(it also shows how bored I am tonight)
var props = {
1000: { color: 'red', msg: 'Ready' },
2000: { color: 'yellow', msg: 'Set' },
3000: { color: 'green' , msg: 'Go!' }
};
var handles = [];
var $d = $('#theDiv');
$d.mouseenter(function () {
$.each(props, function (k, obj) {
handles[k] = setTimeout(function () {
changeStuff($d, obj);
}, k);
});
}).mouseleave(function () {
$.each(handles, function (i, h) {
clearTimeout(h);
});
reset($d);
});
function reset($d) {
$d.css('backgroundColor', 'orange');
$d.text('Hover here...');
}
function changeStuff($node, o) {
$node.css('backgroundColor', o.color);
$node.text(o.msg);
}

Related

Can't use variable as setInterval delay? [duplicate]

I have written a javascript function that uses setInterval to manipulate a string every tenth of a second for a certain number of iterations.
function timer() {
var section = document.getElementById('txt').value;
var len = section.length;
var rands = new Array();
for (i=0; i<len; i++) {
rands.push(Math.floor(Math.random()*len));
};
var counter = 0
var interval = setInterval(function() {
var letters = section.split('');
for (j=0; j < len; j++) {
if (counter < rands[j]) {
letters[j] = Math.floor(Math.random()*9);
};
};
document.getElementById('txt').value = letters.join('');
counter++
if (counter > rands.max()) {
clearInterval(interval);
}
}, 100);
};
Instead of having the interval set at a specific number, I would like to update it every time it runs, based on a counter. So instead of:
var interval = setInterval(function() { ... }, 100);
It would be something like:
var interval = setInterval(function() { ... }, 10*counter);
Unfortunately, that did not work. It seemed like "10*counter" equals 0.
So, how can I adjust the interval every time the anonymous function runs?
You could use an anonymous function:
var counter = 10;
var myFunction = function(){
clearInterval(interval);
counter *= 10;
interval = setInterval(myFunction, counter);
}
var interval = setInterval(myFunction, counter);
UPDATE: As suggested by A. Wolff, use setTimeout to avoid the need for clearInterval.
var counter = 10;
var myFunction = function() {
counter *= 10;
setTimeout(myFunction, counter);
}
setTimeout(myFunction, counter);
Use setTimeout() instead. The callback would then be responsible for firing the next timeout, at which point you can increase or otherwise manipulate the timing.
EDIT
Here's a generic function you can use to apply a "decelerating" timeout for ANY function call.
function setDeceleratingTimeout(callback, factor, times)
{
var internalCallback = function(tick, counter) {
return function() {
if (--tick >= 0) {
window.setTimeout(internalCallback, ++counter * factor);
callback();
}
}
}(times, 0);
window.setTimeout(internalCallback, factor);
};
// console.log() requires firebug
setDeceleratingTimeout(function(){ console.log('hi'); }, 10, 10);
setDeceleratingTimeout(function(){ console.log('bye'); }, 100, 10);
I like this question - inspired a little timer object in me:
window.setVariableInterval = function(callbackFunc, timing) {
var variableInterval = {
interval: timing,
callback: callbackFunc,
stopped: false,
runLoop: function() {
if (variableInterval.stopped) return;
var result = variableInterval.callback.call(variableInterval);
if (typeof result == 'number')
{
if (result === 0) return;
variableInterval.interval = result;
}
variableInterval.loop();
},
stop: function() {
this.stopped = true;
window.clearTimeout(this.timeout);
},
start: function() {
this.stopped = false;
return this.loop();
},
loop: function() {
this.timeout = window.setTimeout(this.runLoop, this.interval);
return this;
}
};
return variableInterval.start();
};
Example use
var vi = setVariableInterval(function() {
// this is the variableInterval - so we can change/get the interval here:
var interval = this.interval;
// print it for the hell of it
console.log(interval);
// we can stop ourselves.
if (interval>4000) this.stop();
// we could return a new interval after doing something
return interval + 100;
}, 100);
// we can change the interval down here too
setTimeout(function() {
vi.interval = 3500;
}, 1000);
// or tell it to start back up in a minute
setTimeout(function() {
vi.interval = 100;
vi.start();
}, 60000);
I had the same question as the original poster, did this as a solution. Not sure how efficient this is ....
let interval = 5000; // initial condition
let run = setInterval(request, interval); // start setInterval as "run"
function request() {
console.log(interval); // firebug or chrome log
clearInterval(run); // stop the setInterval()
// dynamically change the run interval
if (interval > 200) {
interval = interval * .8;
} else {
interval = interval * 1.2;
}
run = setInterval(request, interval); // start the setInterval()
}
This is my way of doing this, i use setTimeout:
var timer = {
running: false,
iv: 5000,
timeout: false,
cb : function(){},
start : function(cb,iv){
var elm = this;
clearInterval(this.timeout);
this.running = true;
if(cb) this.cb = cb;
if(iv) this.iv = iv;
this.timeout = setTimeout(function(){elm.execute(elm)}, this.iv);
},
execute : function(e){
if(!e.running) return false;
e.cb();
e.start();
},
stop : function(){
this.running = false;
},
set_interval : function(iv){
clearInterval(this.timeout);
this.start(false, iv);
}
};
Usage:
timer.start(function(){
console.debug('go');
}, 2000);
timer.set_interval(500);
timer.stop();
A much simpler way would be to have an if statement in the refreshed function and a control to execute your command at regular time intervals . In the following example, I run an alert every 2 seconds and the interval (intrv) can be changed dynamically...
var i=1;
var intrv=2; // << control this variable
var refreshId = setInterval(function() {
if(!(i%intrv)) {
alert('run!');
}
i++;
}, 1000);
This can be initiated however you want. timeout is the method i used to keep it on the top of the hour.
I had the need for every hour to begin a code block on the hour. So this would start at server startup and run the interval hourly. Basicaly the initial run is to begin the interval within the same minute. So in a second from init, run immediately then on every 5 seconds.
var interval = 1000;
var timing =function(){
var timer = setInterval(function(){
console.log(interval);
if(interval == 1000){ /*interval you dont want anymore or increment/decrement */
interval = 3600000; /* Increment you do want for timer */
clearInterval(timer);
timing();
}
},interval);
}
timing();
Alternately if you wanted to just have something happen at start and then forever at a specific interval you could just call it at the same time as the setInterval. For example:
var this = function(){
//do
}
setInterval(function(){
this()
},3600000)
this()
Here we have this run the first time and then every hour.
I couldn't synchronize and change the speed my setIntervals too and I was about to post a question. But I think I've found a way. It should certainly be improved because I'm a beginner. So, I'd gladly read your comments/remarks about this.
<body onload="foo()">
<div id="count1">0</div>
<div id="count2">2nd counter is stopped</div>
<button onclick="speed0()">pause</button>
<button onclick="speedx(1)">normal speed</button>
<button onclick="speedx(2)">speed x2</button>
<button onclick="speedx(4)">speed x4</button>
<button onclick="startTimer2()">Start second timer</button>
</body>
<script>
var count1 = 0,
count2 = 0,
greenlight = new Boolean(0), //blocks 2nd counter
speed = 1000, //1second
countingSpeed;
function foo(){
countingSpeed = setInterval(function(){
counter1();
counter2();
},speed);
}
function counter1(){
count1++;
document.getElementById("count1").innerHTML=count1;
}
function counter2(){
if (greenlight != false) {
count2++;
document.getElementById("count2").innerHTML=count2;
}
}
function startTimer2(){
//while the button hasn't been clicked, greenlight boolean is false
//thus, the 2nd timer is blocked
greenlight = true;
counter2();
//counter2() is greenlighted
}
//these functions modify the speed of the counters
function speed0(){
clearInterval(countingSpeed);
}
function speedx(a){
clearInterval(countingSpeed);
speed=1000/a;
foo();
}
</script>
If you want the counters to begin to increase once the page is loaded, put counter1() and counter2() in foo() before countingSpeed is called. Otherwise, it takes speed milliseconds before execution.
EDIT : Shorter answer.
(function variableInterval() {
//whatever needs to be done
interval *= 2; //deal with your interval
setTimeout(variableInterval, interval);
//whatever needs to be done
})();
can't get any shorter
Here is yet another way to create a decelerating/accelerating interval timer. The interval gets multiplied by a factor until a total time is exceeded.
function setChangingInterval(callback, startInterval, factor, totalTime) {
let remainingTime = totalTime;
let interval = startInterval;
const internalTimer = () => {
remainingTime -= interval ;
interval *= factor;
if (remainingTime >= 0) {
setTimeout(internalTimer, interval);
callback();
}
};
internalTimer();
}
Make new function:
// set Time interval
$("3000,18000").Multitimeout();
jQuery.fn.extend({
Multitimeout: function () {
var res = this.selector.split(",");
$.each(res, function (index, val) { setTimeout(function () {
//...Call function
temp();
}, val); });
return true;
}
});
function temp()
{
alert();
}
This piece of code below accelerates (acceleration > 1) or decelerates (acceleration <1) a setInterval function :
function accelerate(yourfunction, timer, refresh, acceleration) {
var new_timer = timer / acceleration;
var refresh_init = refresh;//save this user defined value
if (refresh < new_timer ){//avoid reseting the interval before it has produced anything.
refresh = new_timer + 1 ;
};
var lastInter = setInterval(yourfunction, new_timer);
console.log("timer:", new_timer);
function stopLastInter() {
clearInterval(lastInter);
accelerate(yourfunction, new_timer, refresh_init, acceleration);
console.log("refresh:", refresh);
};
setTimeout(stopLastInter, refresh);
}
With :
timer: the setInterval initial value in ms (increasing or decreasing)
refresh: the time before a new value of timer is calculated. This is the step lenght
acceleration: the gap between the old and the next timer value. This is the step height
Inspired by the internal callback above, i made a function to fire a callback at fractions of minutes. If timeout is set to intervals like 6 000, 15 000, 30 000, 60 000 it will continuously adapt the intervals in sync to the exact transition to the next minute of your system clock.
//Interval timer to trigger on even minute intervals
function setIntervalSynced(callback, intervalMs) {
//Calculate time to next modulus timer event
var betterInterval = function () {
var d = new Date();
var millis = (d.getMinutes() * 60 + d.getSeconds()) * 1000 + d.getMilliseconds();
return intervalMs - millis % intervalMs;
};
//Internal callback
var internalCallback = function () {
return function () {
setTimeout(internalCallback, betterInterval());
callback();
}
}();
//Initial call to start internal callback
setTimeout(internalCallback, betterInterval());
};
This is my idea for times when you do not want loops like setInterval to overlap.
You also want to be able to set the loop execution delay and start and stop the loop, instansly on the fly.
I am using a loop_flag variable and a setTimeout function.
I set the main function to async so that you can call other functions in the body by calling await. When the main body of your code is running, the main loop waits and does not repeat itself. (which is not the case with setInterval)
An example of a simple code is:
//#NabiKAZ
document.getElementById("btn_start").addEventListener("click", function() {
console.log("Starting...");
loop_flag = true;
loop_func();
});
document.getElementById("btn_stop").addEventListener("click", function() {
console.log("Stoping...");
loop_flag = false;
});
var n = 0;
var loop_flag = false;
var loop_func = async function() {
if (!loop_flag) {
console.log("STOP.");
return;
}
//body main function inhere
n++;
console.log(n);
////
if (loop_flag) {
setTimeout(loop_func, document.getElementById("inp_delay").value);
} else {
console.log("STOP.");
}
}
<input id="inp_delay" value="1000">
<button id="btn_start">START</button>
<button id="btn_stop">STOP</button>
For a more complete code with a fetch request inside the loop, see here:
https://jsfiddle.net/NabiKAZ/a5hdw2bo/
You can use a variable and change the variable instead.
setInterval(() => function, variable)
You can do this by clearing the interval every iteration, changing the timer value and setting the interval again. Hope it helps ;)
For exemple:
const DOMCounter = document.querySelector(".counter")
let timer = 1000
const changeCounter = () => {
clearInterval(interval)
DOMCounter.innerHTML = timer
timer += 1000
timer == 5000 && timer == 1000
interval = setInterval(changeCounter, timer)
}
let interval = setInterval(changeCounter, timer)
<div class="container">
<p class="counter"></p>
</div>
var counter = 15;
var interval = function() {
setTimeout(function(){
// Write your code here and remove console.log, remember that you need declare yourDynamicValue and give it a value
console.log((new Date()).getTime())
window.counter = yourDynamicValue;
window.interval();
}, counter);
}
// It needs to run just once as init
interval();

Trigger different events based on how long mouse is held down

I want to trigger different events based on how long the mouse is held down. If the mouse is held less than a second trigger event 1. If it is held down for a second trigger event 2. If it is held down for two seconds trigger event 3, etc.
I have this JavaScript which displays messages showing how long the mouse is held down, but I am unsure of how to prevent the message shown after one second if the user continues to hold the mouse down for two seconds,
var mousedown = false;
var mousedown_timer = '';
$('#button').mousedown(function(e) {
mousedown = true;
$('#log').text('mousedown...');
mousedown_timer = setTimeout(function () {
if(mousedown) {
$('#log').text('1 second');
}
}, 1000);
mousedown_timer = setTimeout(function () {
if(mousedown) {
$('#log').text('2 second');
}
}, 2000);
}).mouseup(function(e) {
mousedown = false;
clearTimeout(mousedown_timer);
$('#log').text('aborted');
});
Is there maybe a way I could move my timer to detect the time elapsed in the mouseup function?
Here is a fiddle.
Here is how I would do it:
var mousedownTimestamp;
$('#button').mousedown(function(e) {
mousedownTimestamp = new Date();
}).mouseup(function(e) {
var mouseupTimestamp = new Date();
var difference = mouseupTimestamp - mousedownTimestamp;
if (difference < 1000) {
// event 1
} else if (difference >= 1000 && difference < 2000) {
// event 2
} else if (difference >= 2000) {
// event 3
}
});

timeout between clicks jquery

i have the following code to count clicks on a div
$('.ps-next').click(function () {
setTimeout($('#currentImage').html(parseInt($('#currentImage').html(), 10) - 1), 10000);
});
$('.ps-prev').click(function () {
setTimeout($('#currentImage').html(parseInt($('#currentImage').html(), 10) + 1), 10000);
});
i would like to count clicks but i want to put a delay of 1 second between clicks. or at least not count fast clicks can anyone help me.
I use a slightly different approach than most here.
The event object has a timeStamp property, so I compare that to the previous timestamp. Here's how I'd approach the situation...
var lastClick,
$count = $('.count');
$('.stepper').on('click', function(e){
// If we have a lastClick value or the current timeStamp
// minus lastClick is greater than 1000 ( 1 second ), go to work.
if ( !lastClick || lastClick && e.timeStamp - lastClick > 1000 ) {
var $stepper = $(this);
$count.text(function(i, txt){
var current = +txt;
return current + ( $stepper.is('.up') ? 1 : -1 );
});
lastClick = e.timeStamp;
}
});
Along with this HTML.
<div class="stepper up">Up</div>
<div class="count">5</div>
<div class="stepper down">Down</div>
Here is a quick demo: http://jsbin.com/iruXisOn/1/edit
you can use this jquery plugin
(function ($) {
$.fn.oneClickPerTime = function (callback,timeDelay) {
var __this = this;
flagOneClick = 1;
return this.each(function () {
$(__this).click(function() {
if (flagOneClick==0)
return;
flagOneClick = 0;
setTimeout(function() {
flagOneClick = 1;
},timeDelay);
callback(this);
});
});
}
})(jQuery);
then call function and must define the timeout, ex: 1000 (1 second)
$('.ps-prev').oneClickPerTime(function(){
//callback
},1000);

Jquery countup plugin using "jQuery Boilerplate"

I'm new to Jquery plugin creation. Following jquery plugin is created using jQuery Boilerplate. It just do a count-up and notify when count-up finished.
I want to have a function to restart count-up by setting counter to 0;
I dont understand how to call that reset function
;(function ( $, window, undefined ) {
var pluginName = 'countup',
document = window.document,
defaults = {
countSince: new Date(),
countUpTo:120,
notifyAfter:110,
onExpire:function() {
},
};
// The actual plugin constructor
function Plugin( element, options ) {
this.element = element;
this.options = $.extend( {counter:0}, defaults, options) ;
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype.init = function () {
this.tick();
};
Plugin.prototype.reset = function () {
this.options.counter = 0;
};
Plugin.prototype.tick = function () {
if (this.options.counter > this.options.countUpTo) {
//timer expired
this.options.onExpire($(this.element));
}
else {
if (this.options.counter > this.options.notifyAfter) {
$(this.element).find('span').html('<strong style="font-size: 15px; color:#ff0000;">' + this.options.counter+ ' seconds</strong>');
}
else {
$(this.element).find('span').html('<strong style="font-size: 15px; color:#3366ff">' + this.options.counter + ' seconds</strong>');
}
setTimeout(function() {
this.options.counter += 1;
this.tick();
}, 1000);//calling tick function again
}
};
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new Plugin( this, options ));
}
});
};
}(jQuery, window));
on document ready ::
$('#countdown').countup({
onExpire:function() {
alert('hi');
},
countSince:new Date(),//count from this
countUpTo:30,//seconds from the countSince to expire
notifyAfter:20
})
after that i want to call reset() function on $('#countdown'). how to do that? Or is there a better way to write above code? Please give me some help here.
The boiler-plate code you created is awfully complicated. The following HTML and JavaScript (along with jQuery) will accomplish an upward counter from 0 until a number of seconds defined by var countTo at which point it will print the message stored in var successMsg. The reset button restarts the counter at zero.
HTML:
<div id="countdown"></div>
<input id="countreset" value="Reset" type="button" />​
JavaScript:
var countTo = 5; // Time to count to
var successMsg = 'hi'; // Replace count with this message at max number of seconds
function countUp() {
var countdown = $('#countdown');
// Turn contents into integer
var current = parseInt(countdown.html());
// Increment seconds
var next = current+1;
if (next >= countTo) {
// If at max seconds, replace with message
countdown.html(successMsg);
} else {
// Replace seconds with next second
countdown.html(next);
setTimeout(countUp, 1000);
}
}
function startCountdown() {
var countdown = $('#countdown');
// Set to zero seconds
countdown.html('0');
// Start counting
setTimeout(countUp, 1000);
}
$(document).ready(function() {
// Start the countdown
startCountdown();
$('#countreset').click(function() {
// On reset button .click(), start countdown
startCountdown();
});
});​
I've put the solution up on jsFiddle: http://jsfiddle.net/TxVnS/2/
Update:
A solution to allow for variable counter ids is here: http://jsfiddle.net/TxVnS/6/

Scroll event firing too many times. I only want it to fire a maximum of, say, once per second

I have a page with "infinite scroll". It calculates the difference between the end of the page and the current page and loads more content if this difference is small enough. The code is soemthing like this using jQuery:
$(window).on('scroll', function() {
if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
# load more content via ajax
}
Now, the problem is that every time I scroll, this event fires multiple times per scroll. I would like fire at most every x milliseconds. How would I do this?
Check out the Underscore.js library's "throttle" method.
http://underscorejs.org/#throttle
The example it gives is exactly what you're asking about - limiting how often you have to handle scroll events.
One way to solve this problem is to define a time interval and only process a scroll event once within that time interval. If more than one scroll event comes in during that time interval, you ignore it and process it only when that time interval has passed.
var scrollTimer, lastScrollFireTime = 0;
$(window).on('scroll', function() {
var minScrollTime = 100;
var now = new Date().getTime();
function processScroll() {
console.log(new Date().getTime().toString());
}
if (!scrollTimer) {
if (now - lastScrollFireTime > (3 * minScrollTime)) {
processScroll(); // fire immediately on first scroll
lastScrollFireTime = now;
}
scrollTimer = setTimeout(function() {
scrollTimer = null;
lastScrollFireTime = new Date().getTime();
processScroll();
}, minScrollTime);
}
});
This will fire the first scroll event immediately and then get you a scroll event approximately once every 100ms while the scrollbar is being moved and then one final event after the scrollbar stops moving. You can adjust the frequency of the event by changing the argument to the setTimeout (what is currently set to 100).
There is a demo here: http://jsfiddle.net/jfriend00/EBEqZ/ which you need to open a debug console window, start moving the scrollbar in the content window and then watch the time of each scroll event in the debug console window. On my version of Chrome, they are set for a minimum spacing of 100ms and they seem to occur every 100-200ms.
There is a cool explanation from John Resig, the creator of jQuery to resolve this situation.
var outerPane = $details.find(".details-pane-outer"),
didScroll = false;
$(window).scroll(function() {
didScroll = true;
});
setInterval(function() {
if ( didScroll ) {
didScroll = false;
// Check your page position and then
// Load in more results
}
}, 250);
The source:
http://ejohn.org/blog/learning-from-twitter/
var isWorking = 0;
$(window).on('scroll', function()
{
if(isWorking==0)
{
isWorking=1;
if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
# load more content via ajax
setTimeout(function(){isWorking=0},1000);
}
}
var now = new Date().getTime();
$(window).scroll( function () {
if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
{
if (new Date().getTime() - now > 1000)
{
console.log("Task executed once per second");
now = new Date().getTime();
}
}
});
Or
You can use Throttling fonction calls:
throttling-function-calls
function throttle(fn, threshhold, scope) {
threshhold || (threshhold = 250);
var last,
deferTimer;
return function () {
var context = scope || this;
var now = +new Date,
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
};
}
You can call it like this:
$('body').on('mousemove', throttle(function (event) {
console.log('tick');
}, 1000));
Here is a solution that doesn't require the use of an extra JS library or plugin, that aims for simplicity. It might not be as efficient as other implementations but it is definitely a step up from firing your main event every time you scroll.
This was taken from this blog post by Danny Van Kooten. Which I have used in delaying my onscroll() events for my back-to-top button on my blog.
var timer;
$(window).scroll(function() {
if(timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout(function() {
// actual code here. Your call back function.
console.log( "Firing!" );
}, 100);
});
You can also further improve performance by moving out variables out of the callback function to avoid unnecessary recalculations, for example the value of $(window).height() or height of some static div element that won't change once the page is loaded.
Here's an example that is adapted from my use case.
var scrollHeight = $("#main-element").height(); //never changes, no need to recalculate.
$(window).on('scroll', function() {
if (timer)
window.clearTimeout(timer);
timer = window.setTimeout(function() {
var scrollPosition = $(window).height() + $(window).scrollTop();
if ($(window).scrollTop() < 500)
$(".toggle").fadeIn(800);
else
$(".toggle").fadeOut(800);
}, 150); //only fire every 150 ms.
});
This limits the actual function to only execute every 150ms, or else reset the timer back to 0 if 150ms has not passed. Tweak the value to suit what you need.
the scroll fire multiple times is correct and you should able to get the scroll position differently each time. I think you need to set a timer when you first get in the scroll event like you mentioned x milliseconds, and also record the time stamp, and then next time scroll event fire, check the last trigger time and ignore it if it's within x milliseconds, and do the real job in your Timer action.
One does not need a ton of local variables for a decent throttle function. The purpose of a throttle function is to reduce browser resources, not to apply so much overhead that you are using even more. As proof of evidence of this claim, I have devised a throttle function that has only 5 'hanging' variables referenes in its scope. Additionally, my different uses for throttle functions require many different circumstances for them. Here is my list of things that I believe 'good' throttle function needs.
Immediately calls the function if it has been more than interval MS since the last call.
Avoids executing function for another interval MS.
Delays excessive event firing instead of dropping the event altogether.
Updates the delayed event object on successive calls so that it doesn't become 'stale'.
And, I believe that the following throttle function satisfies all of those.
function throttle(func, alternateFunc, minimumInterval) {
var executeImmediately = true, freshEvt = null;
return function(Evt) {
if (executeImmediately) { // Execute immediatly
executeImmediately = false;
setTimeout(function(f){ // handle further calls
executeImmediately = true;
if (freshEvt !== null) func( freshEvt );
freshEvt = null;
}, minimumInterval);
return func( Evt );
} else { // Delayed execute
freshEvt = Evt;
if (typeof alternateFunc === "function") alternateFunc( Evt );
}
};
}
Then, to wrap this throttle function around DOM event listeners:
var ltCache = [];
function listen(obj, evt, func, _opts){
var i = 0, Len = ltCache.length, lF = null, options = _opts || {};
a: {
for (; i < Len; i += 4)
if (ltCache[i] === func &&
ltCache[i+1] === (options.alternate||null) &&
ltCache[i+2] === (options.interval||200)
) break a;
lF = throttle(func, options.alternate||null, options.interval||200);
ltCache.push(func, options.alternate||null, options.interval||200, lF);
}
obj.addEventListener(evt, lF || ltCache[i+3], _opts);
};
function mute(obj, evt, func, options){
for (var i = 0, Len = ltCache.length; i < Len; i += 4)
if (ltCache[i] === func &&
ltCache[i+1] === (options.alternate||null) &&
ltCache[i+2] === (options.interval||200)
) return obj.removeEventListener(evt, ltCache[i+3], options);
}
Example usage:
function throttle(func, alternateFunc, minimumInterval) {
var executeImmediately = true, freshEvt = null;
function handleFurtherCalls(f){
executeImmediately = true;
if (freshEvt !== null) func( freshEvt );
freshEvt = null;
};
return function(Evt) {
if (executeImmediately) { // Execute immediatly
executeImmediately = false;
setTimeout(handleFurtherCalls, minimumInterval);
return func( Evt );
} else { // Delayed execute
freshEvt = Evt;
if (typeof alternateFunc === "function") alternateFunc( Evt );
}
};
}
var ltCache = [];
function listen(obj, evt, func, _opts){
var i = 0, Len = ltCache.length, lF = null, options = _opts || {};
a: {
for (; i < Len; i += 4)
if (ltCache[i] === func &&
ltCache[i+1] === (options.alternate||null) &&
ltCache[i+2] === (options.interval||200)
) break a;
lF = throttle(func, options.alternate||null, options.interval||200);
ltCache.push(func, options.alternate||null, options.interval||200, lF);
}
obj.addEventListener(evt, lF || ltCache[i+3], _opts);
};
function mute(obj, evt, func, options){
for (var i = 0, Len = ltCache.length; i < Len; i += 4)
if (ltCache[i] === func &&
ltCache[i+1] === (options.alternate||null) &&
ltCache[i+2] === (options.interval||200)
) return obj.removeEventListener(evt, ltCache[i+3], options);
}
var numScrolls = 0, counter = document.getElementById("count");
listen(window, 'scroll', function whenbodyscrolls(){
var scroll = -document.documentElement.getBoundingClientRect().top;
counter.textContent = numScrolls++;
if (scroll > 900) {
console.log('Body scrolling stoped!');
mute(window, 'scroll', whenbodyscrolls, true);
}
}, true);
<center><h3>\/ Scroll Down The Page \/</h3></center>
<div style="position:fixed;top:42px"># Throttled Scrolls: <span id="count">0</span></div>
<div style="height:192em;background:radial-gradient(circle at 6em -5em, transparent 0px, rgba(128,0,0,.4) 90em),radial-gradient(circle at 10em 40em, rgba(255,255,255,.8) 0px, rgba(128,0,0,.02) 50em),radial-gradient(circle at 4em 80em, rgba(0,192,0,.75) 0px,rgba(0,128,0,.56) 10em,rgba(255,0,96,.03125) 30em),radial-gradient(circle at 86em 24em, rgba(255,0,0,.125) 0px,rgba(0,0,255,.0625) 60em,transparent 80em);"></div>
<style>body{margin:0}</style>
By default, this throttles the function to at most one call every 200ms. To change the interval to a different number of milliseconds, then pass a key named "interval" in the options argument and set it to the desired milliseconds.

Categories

Resources