Trying to Override JS Timer - javascript

I am a newbie to JS - I've looked for different solutions on how to override a button timer but haven't found any solutions that worked for this application. I'm not even sure if I'm looking in the right place.
jQuery.timers = [];
jQuery.fx.tick = function() {
var timer,
i = 0,
timers = jQuery.timers;
fxNow = Date.now();
for ( ; i < timers.length; i++ ) {
timer = timers[ i ];
// Run the timer and safely remove it when done (allowing for external removal)
if ( !timer() && timers[ i ] === timer ) {
timers.splice( i--, 1 );
}
}
if ( !timers.length ) {
jQuery.fx.stop();
}
fxNow = undefined;
};
jQuery.fx.timer = function( timer ) {
jQuery.timers.push( timer );
jQuery.fx.start();
};
jQuery.fx.interval = 13;
jQuery.fx.start = function() {
if ( inProgress ) {
return;
}
inProgress = true;
schedule();
};
jQuery.fx.stop = function() {
inProgress = null;
};
jQuery.fx.speeds = {
slow: 600,
fast: 200,
// Default speed
_default: 400
};
This is what I'm looking at in the sources - is this even the right place? If so, what could I enter into the console to override?

Related

Javascript Slideshow Speed

I have this Code with a Slideshow for Images. I Would like to set the time the images are fixed. (Image one rest for 10min and then fade out). All the Images should rest about 10min. I like to use this for a Infoscreen in my company. Please help :)
(function() {
function Slideshow( element ) {
this.el = document.querySelector( element );
this.init();
}
Slideshow.prototype = {
init: function() {
this.wrapper = this.el.querySelector( ".slider-wrapper" );
this.slides = this.el.querySelectorAll( ".slide" );
this.previous = this.el.querySelector( ".slider-previous" );
this.next = this.el.querySelector( ".slider-next" );
this.index = 0;
this.total = this.slides.length;
this.timer = null;
this.action();
this.stopStart();
},
_slideTo: function( slide ) {
var currentSlide = this.slides[slide];
currentSlide.style.opacity = 1;
for( var i = 0; i < this.slides.length; i++ ) {
var slide = this.slides[i];
if( slide !== currentSlide ) {
slide.style.opacity = 0;
}
}
},
action: function() {
var self = this;
self.timer = setInterval(function() {
self.index++;
if( self.index == self.slides.length ) {
self.index = 0;
}
self._slideTo( self.index );
}, 3000);
},
stopStart: function() {
var self = this;
self.el.addEventListener( "mouseover", function() {
clearInterval( self.timer );
self.timer = null;
}, false);
self.el.addEventListener( "mouseout", function() {
self.action();
}, false);
}
};
document.addEventListener( "DOMContentLoaded", function() {
var slider = new Slideshow( "#main-slider" );
});
})();
Well, there is only on thing that controls anything timing related in your code, so its a pretty safe bet that's what you want to change.
You have a setInterval() in action with its time set to 3000. Change that to 600000 (10m * 60s * 1000ms) and you should be all set.
action: function() {
var self = this;
self.timer = setInterval(function() {
self.index++;
if( self.index == self.slides.length ) {
self.index = 0;
}
self._slideTo( self.index );
}, 1000*60*10);
This function uses setInterval, which expects interval in ms as the second parameter. In this example its set to 3000 which is 3 seconds.
Change it to what I wrote above (1000ms is 1 second * 60 = 1 minute * 10 = 10 minutes).

First load a page with ajax then with increasing intervals

I am currently using this code on one of my sites,
I want the test.php to load immediately, however it waits till after the interval.
Then if continues every minute untill the page closes. This can cause very large bandwith useage.
$(document).ready(function () {
setInterval(function() {
$.get("test.php", function (result) {
$('#id').html(result);
});
}, 60000);
});
What I would like to achieve is.
Load the test.php on pageload.
Then load the page every 60 seconds
If the page has been open for 10 minutes double the intervals to 120sec.
20mins increase to 180 second intervals
30mins increase to 240 second intervals
And so on.
Thanks for any help
You could use setInterval to manage the increase in interval every 10 minutes, and use setTimeout to use that interval. To get the code executed immediately on page load, just rearrange the code a bit:
$(document).ready(function () {
var interval = 60000;
setInterval(function () {
interval += 60000;
}, 600000); // every 10 minutes
(function loop() {
$.get("test.php", function (result) {
$('#id').html(result);
});
setTimeout(loop, interval); // repeat after interval
})(); // execute immediately
});
Generic Approach
chainable factory function
Create custom timer functions "on the fly".
var timer1 = timerFactory( fnCallback, iRepeats, iDelay, iSteps );
While runtime one can set all parameters.
timer1
.setContext( { foo: true, bar: 'wow' } )
.setCallback( function() { alert(this.bar) } )
.setDelay( 10000 );
And destroy the timer when obsolete.
timer1.destroy()
var timerFactory = function( _fnCallback, _iRepeat, _iDelay, _iSteps, _oContext ) {
// sanitize arguments and set default values
if ( typeof _fnCallback != 'function' ) {
_fnCallback = function() {};
}
if ( typeof _iRepeat != 'number' || _iRepeat < 1 ) {
_iRepeat = 10;
}
if ( typeof _iDelay != 'number' || _iDelay < 0 ) {
_iDelay = 60000;
}
if ( typeof _iSteps != 'number' || _iSteps < 0 ) {
_iSteps = _iDelay;
}
if ( typeof _oContext != 'object' ) {
_oContext = this;
}
var i = _iRepeat,
_getInterval = function() {
if ( --i ) {
return _iDelay;
}
i = _iRepeat;
return _iDelay += _iSteps;
},
_handle = function() {
_fnCallback.call( _oContext );
_setTimeout = setTimeout(_handle, _getInterval())
};
_handle();
// public methods (chainable)
this.destroy = function() {
clearTimeout( _setTimeout );
_fnCallback = _iRepeat = _iDelay = _iSteps =
_oContext = i = _getInterval = _handle = undefined;
return this;
}
this.setCallback = function( fnCallback ) {
_fnCallback = fnCallback;
return this;
}
this.setRepeats = function( iRepeat ) {
_iRepeat = iRepeat;
return this;
}
this.setDelay = function( iDelay ) {
_iDelay = iDelay;
return this;
}
this.setSteps = function( iSteps ) {
_iSteps = iSteps;
return this;
}
this.setContext = function( oContext ) {
_oContext = oContext;
return this;
}
// deploy public methods
return this;
};
$(document).ready(function () {
/* actual question
timerFactory(
function(){ $.get("test.php", function (result) { $('#id').html(result); }) }
)
*/
// examples
timerFactory( function() {$('#_0').append('ajax default: 10, 6000, 6000<br>')} );
timerFactory( function() {$('#_1').append('1, 0, 250<br>')}, 1, 0, 250 );
timerFactory( function() {$('#_2').append('3, 1500<br>')}, 3, 1500 );
timerFactory( function() {$('#_3').append('1, 3000, ->destroy<br>')}, 1, 3000 ).destroy();
// example with context and alternative syntax
myClass = { // context example
methFOO : function() {$('#_4').append('ALT meth1<br>')},
methBAR : function() {$('#_4').append('ALT meth2<br>')}
}
timerFactory( myClass.methFOO, 1, 1, 1 )
.setCallback( function() {this.methBAR()} )
.setRepeats( 3 )
.setDelay( 1000 )
.setSteps( 500 )
.setContext( myClass );
});
html, body {
height: 100%;
margin: 0;
padding: 0;
width: 100%;
}
div {
border: 1px solid #999;
box-sizing: border-box;
float: left;
height: 100%;
width: 20%;
}
<div id="_0"></div>
<div id="_1"></div>
<div id="_2"></div>
<div id="_3"></div>
<div id="_4"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

javascript, setInterval function starts counting not from 0

I have noticed, that my setInterval function starts counting from 1, and sometimes even from 10. But if i increase the interval to some 20 seconds, it starts counting correctly from 0. Subsequent counting is correct - adds one in every step, but the initial cnt value, if i reduce to internval to some 5 seconds, becomes wrong.
var stepProt = function () {
console.log('started stepProt constructor');
this.step = 20; //seconds
this.cnt = 0; //init counter, pointer to rtArr
};
stepProt.prototype.countingFnc = function () {
console.log('started stepFnc.prototype.countingFnc');
var msec = this.step*1000;
var that = this;
that.cnt=0;
this.nameToStop = window.setInterval( function () {
that.stepFnc(); }, msec );
}
stepProt.prototype.stepFnc = function() {
console.log (' 132 startedFnc rtG.prototype.stepFnc, this.cnt='+this.cnt ); //if interval is 5seconds, this.cnt usually starts from 1, but sometimes from 10, instead of starting from 0. All other steps are correct, +1 each time.
/* here there is some logics, which takes time */
this.cnt++;
};
var stepIn = new stepProt(); //instance
stepIn.stepFnc();
What could be the reason and how to resolve?
p.s.
Actually, i use this function before window onload. Maybe this is the reason?
I include many scripts before window.onload.
Later i make single script for window.onload functionality.
I put
var stepIn = new stepFnc(); //instance
stepIn.stepFnc();
before window onload, because if i use it in window.onload, for some reason, other functions does not understand stepIn instance as a global variable accessable everythere. Maybe it is because i use php template.
You should call stepIn.countingFnc(); to start the process. Another thing is that I'd change the name of the function stepFnc so it doesn't match with the constructor name for readability.
var stepFnc = function () {
console.log('started stepFnc constructor');
this.step = 20; //seconds
this.cnt = 0; //init counter, pointer to rtArr
};
stepFnc.prototype.countingFnc = function () {
console.log('started stepFnc.prototype.countingFnc');
var msec = this.step*1000;
var that = this;
that.cnt=0;
this.nameToStop = setInterval( function () {
that.triggerFnc(); }, msec );
}
stepFnc.prototype.triggerFnc = function() {
console.log (' 132 startedFnc rtG.prototype.stepFnc, this.cnt='+this.cnt ); //if interval is 5seconds, this.cnt usually starts from 1, but sometimes from 10, instead of starting from 0. All other steps are correct, +1 each time.
/* here there is some logics, which takes time */
this.cnt++;
};
var stepIn = new stepFnc();
stepIn.countingFnc();
Hope this helps. ;)
var stepFnc = function () {
console.log('started stepFnc constructor');
this.step = 1; //seconds
this.cnt = 0; //init counter, pointer to rtArr
};
stepFnc.prototype.countingFnc = function () {
console.log('started stepFnc.prototype.countingFnc');
var msec = this.step*1000;
var that = this;
that.cnt=0;
this.nameToStop = window.setInterval( function () {
that.stepFnc(); }, msec );
};
stepFnc.prototype.stepFnc = function() {
console.log (' 132 startedFnc rtG.prototype.stepFnc, this.cnt='+this.cnt ); //if interval is 5seconds, this.cnt usually starts from 1, but sometimes from 10, instead of starting from 0. All other steps are correct, +1 each time.
/* here there is some logics, which takes time */
this.cnt++;
};
var stepIn = new stepFnc();
stepIn.countingFnc();
Seems the reason is that i use setInterval in script not in window.onload, thus the first counter is wrong. I created function to check if javascript is loaded, and than i use boolen in setInterval to start counting only after the all javascript is loaded.
var loadIn - checks if javascript is loaded ,and sets loadIn.jsLoad =true.
if(loadIn.jsLoad) { that.stepFnc(); }
Code checking if
javascript is loaded : this.jsLoad = true (mainly i need this),
html is loaded : this.htmlLoad= true,
both js and html are loaded: this.bLoaded =true
console.log('loading check started' );
var loadProt = function () {
this.bLoaded = "";
this.checkLoadInt="";
this.jsLoadFnc="";
this.bDomainCheckPass = false; //assumes that domain is wrong
this.beforeunload = ""; //event
this.jsLoad = false;
this.htmlLoad = false;
this.bLoaded =false;
};
loadProt.prototype.checkLoadFnc = function() {
console.log('startedFnc checkLoadFnc');
this.htmlLoad = false;
this.jsLoad = false;
if(document.getElementById("bottomPreloadSpan")) { this.htmlLoad =true; }
this.jsLoad = this.jsLoadFnc();
console.log( 'htmlLoad='+this.htmlLoad +', jsLoad=' +this.jsLoad ) ;
this.bLoaded = this.htmlLoad && this.jsLoad;
if( this.bLoaded ) {
this.stopIntervalFnc();
}
};
loadProt.prototype.stopIntervalFnc = function() {
console.log('startedFnc stopIntervalFnc');
document.getElementById("preloadSpan").style.visibility = "hidden";
var preloadImg = document.getElementById('preloadImage');
preloadImg.parentNode.removeChild(preloadImg);
clearInterval(this.checkLoadInt);
this.bDomainCheckPass = this.checkAllowedDomains(); // i do not give it here
//this.evalStep();
if(this.bDomainCheckPass) {
console.log('ERROR right domain');
} else {
console.log('ERROR Wrong domain');
//window.location.assign loads a new document - to login page, saying you was redirected ....
}
}
var loadIn = new loadProt();
loadIn.checkLoadInt = window.setInterval(
function() { loadGIn.checkLoadFnc(); }, 1000 );
loadIn.jsLoadFnc = document.onreadystatechange = function () { return (document.readyState=='complete') ? true : false ; }
Counter function:
var stepProt = function () {
console.log('started stepFnc constructor');
this.step = 20; //seconds
this.cnt = 0; //init counter, pointer to rtArr
};
stepProt.prototype.countingFnc = function () {
console.log('started stepFnc.prototype.countingFnc');
var msec = this.step*1000;
var that = this;
that.cnt=0;
this.nameToStop = window.setInterval( function () {
if(loadIn.jsLoad) { that.stepFnc(); }
}, msec );
}
stepProt.prototype.stepFnc = function() {
console.log (' 132 started stepFnc, this.cnt='+this.cnt );
/* here there is some logics, which takes time */
this.cnt++;
};
var stepIn = new stepProt(); //instance
stepIn.countingFnc();

Javascript Incrementing Numbers

What I'm after:
There are 5 counters on my page, they should all start from 0 and count upwards (increment) at the same time to different values that are set at different speeds. So for example I set 10, 25, 1500, 400, 500 in my variables I would like them all to reach these values.
• start at the same time
• all increment at different speeds
• stop at value set for each
My Problem
I can't figure out a good way to write some simple very efficient javascript to do this (going to be used on a mobile), currently I'm using setinterval which seems to start all the counters at different times and jerks/not smooth..
how far I've got so far
http://jsfiddle.net/95smH/
setInterval(f1,500);
setInterval(f2,1500);
setInterval(f3,500);
setInterval(f4,50);
var v1 = 0
, v2 = 0
, v3 = 0
, v4 = 0;
function f1() {
$('.count.v1').text(v1);
if ( v1 < 450 )
{
v1 ++;
}
}
function f2() {
$('.count.v2').text(v2);
if ( v2 < 50 )
{
v2 ++;
}
}
function f3() {
$('.count.v3').text(v3);
if ( v3 < 23 )
{
v3 ++;
}
}
function f4() {
$('.count.v4').text(v4);
if ( v4 < 4 )
{
v4 ++;
}
}
This would be my shot at a slightly more general way. It will also kill the setInterval once every counter has finished. Of course this will still have the typical inaccuracy of Javascript intervals.
var counter = new (function () {
'use strict';
var counters = [],
handler = null,
precision = 50;
this.addCounter = function (maxValue, interval, selector) {
counters.push({
maxValue: maxValue,
currentValue: 0,
interval: interval / precision,
intervalCounter: 0,
$output: $(selector)
});
return this;
};
this.start = function () {
handler = setInterval(function () {
var stillRunning = false;
for (var i = 0; i < counters.length; i++) {
var counter = counters[i];
counter.intervalCounter++;
if (counter.intervalCounter === counter.interval) {
counter.intervalCounter = 0;
counter.currentValue++;
if (counter.currentValue <= counter.maxValue) {
stillRunning = true;
counter.$output.val(counter.currentValue);
}
} else {
stillRunning = true;
}
}
if (!stillRunning) {
clearInterval(handler);
}
}, precision);
};
return this;
})();
counter
.addCounter(50, 250, '.v1')
.addCounter(25, 500, '.v2')
.start();
Demo fiddle: http://jsfiddle.net/s9AYz/1/
Note that precision must be set such that the interval of each counter is a multiple of it (Boris solution has the same requirement).
This is based on your own code style:
setInterval(tick,50);
var cusers = 0
, cawardshows = 0
, ccountries = 0
, cregions = 0;
var susers = 500
, sawardshows = 1500
, scountries = 500
, sregions = 50;
var i = 0;
function tick() {
$('.count.users').text(cusers);
if ( cusers < 450 && i % susers == 0)
{
cusers ++;
}
$('.count.awardshows').text(cawardshows);
if ( cawardshows < 50 && i % sawardshows == 0 )
{
cawardshows ++;
}
$('.count.countries').text(ccountries);
if ( ccountries < 23 && i % scountries == 0 )
{
ccountries ++;
}
$('.count.regions').text(cregions);
if ( cregions < 4 && i % sregions == 0)
{
cregions ++;
}
i += 50;
}
The idea is to have only one timer, so all updates will be synchronized to the same clock. Since values have different "speeds", you update some of them only every nth step.
Here is a solution quite cpu-friendly :
- you only have one setInterval using a base period that you decide.
- On each interval you iterate through your all counters doing very little work each time.
(i even avoided to use % ).
- The elements are cached.
jsbin is here :
http://jsbin.com/urUxojo/2/edit?html,js,console,output
window.onload=function() {
// this is the period of the base Interval in ms.
// The counters will be aligned on this base period
Counter.basePeriod = 50 ;
// constructor of a Counter
// ! initializes the counter display.
function Counter(id, period_ms, max, initialValue) {
this.element = document.getElementById(id);
this.period = Math.ceil(period_ms / Counter.basePeriod) || 1;
this.max = max ;
this.value = initialValue || 0 ;
this.last = 0;
this.element.value = (this.value);
return this;
};
// called on each basePeriod tick
// updates the element every period until it reaches its max value.
Counter.prototype.tick = function() {
this.last++;
if (this.last == this.period &&
this.value != this.max ) {
this.value++;
this.element.value = (this.value);
this.last=0;
}
};
Counter.counters = [];
Counter.start= function () {
function handleCounters() {
for (var i=0; i< Counter.counters.length; i++) { Counter.counters[i].tick(); }
}
Counter._interval = setInterval(handleCounters, Counter.basePeriod);
};
Counter.add = function() {
var newCounter = Object.create(Counter.prototype);
Counter.counters.push( Counter.apply(newCounter, arguments) );
}
// -------------------------------
Counter.add('cnt1' , 500 , 450 );
Counter.add('cnt2' , 400 , 40 );
Counter.add('topCounter', 1000 , 5 );
Counter.start();
}
Well, you always want to get rid of duplicity, so you can do:
function IntervalClass(selector, sleepTime, maxValue, startValue) {
var curValue = startValue;
this.tick = function () {
if (curValue < maxValue) {
curValue++;
}
$(selector).html(curValue);
};
this.start = function () {
setInterval(this.tick, sleepTime);
};
}
new IntervalClass(".count.users", 1000, 35, 0).start();
new IntervalClass(".count.awardshows", 500, 20, 0).start();
new IntervalClass(".count.countries", 1500, 15, 0).start();
new IntervalClass(".count.regions", 200, 100, 0).start();
JSFIDDLE

stand-alone lazy loading images (no framework based)

I look after a site which by nature has to load quite a lot of images and content on the page. We have decreased the number of elements and graphical layout images as much as we can, so we are now looking at ways to increase the page load in the browser.
Does anyone know any code for lazy loading images that doesn't require a framework such as jQuery?
Here is my own. Have Fun.
Tested: IE 5.5+, FF 2+, Chrome, Opera 9.6+
Usage:
your lazyloaded images should have their real src in a thumb attribute
Just include the javascript file inline or externally.
If you don't want to use it on your entire page, you can do:
LazyImg().destroy(); // stop global fetching
LazyImg("watch-only-this-div");
Note: when you include the file a global instance is already created watchin the whole document. You need to stop that first and start you own instance.
set a custom offset for prefetching (how far below the fold the image should be fetched)
// watch the whole document
// prefetch offset: 300px
LazyImg(document, 300);
Code:
//
// LAZY Loading Images
//
// Handles lazy loading of images in one or more targeted divs,
// or in the entire page. It also keeps track of scrolling and
// resizing events, and removes itself if the work is done.
//
// Licensed under the terms of the MIT license.
//
// (c) 2010 Balázs Galambosi
//
(function(){
// glocal variables
var window = this,
instances = {},
winH;
// cross browser event handling
function addEvent( el, type, fn ) {
if ( window.addEventListener ) {
el.addEventListener( type, fn, false );
} else if ( window.attachEvent ) {
el.attachEvent( "on" + type, fn );
} else {
var old = el["on" + type];
el["on" + type] = function() { old(); fn(); };
}
}
// cross browser event handling
function removeEvent( el, type, fn ) {
if ( window.removeEventListener ) {
el.removeEventListener( type, fn, false );
} else if ( window.attachEvent ) {
el.detachEvent( "on" + type, fn );
}
}
// cross browser window height
function getWindowHeight() {
if ( window.innerHeight ) {
winH = window.innerHeight;
} else if ( document.documentElement.clientHeight ) {
winH = document.documentElement.clientHeight;
} else if ( document.body && document.body.clientHeight ) {
winH = document.body.clientHeight;
} else { // fallback:
winH = 10000; // just load all the images
}
return winH;
}
// getBoundingClientRect alternative
function findPos(obj) {
var top = 0;
if (obj && obj.offsetParent) {
do {
top += obj.offsetTop || 0;
top -= obj.scrollTop || 0;
} while (obj = obj.offsetParent); //
return { "top" : top };
}
}
// top position of an element
var getTopPos = (function() {
var dummy = document.createElement("div");
if ( dummy.getBoundingClientRect ) {
return function( el ) {
return el.$$top || el.getBoundingClientRect().top;
};
} else {
return function( el ) {
return el.$$top || findPos( el ).top;
};
}
})();
// sorts images by their vertical positions
function img_sort( a, b ) {
return getTopPos( a ) - getTopPos( b );
}
// let's just provide some interface
// for the outside world
var LazyImg = function( target, offset ) {
var imgs, // images array (ordered)
last, // last visible image (index)
id, // id of the target element
self; // this instance
offset = offset || 200; // for prefetching
if ( !target ) {
target = document;
id = "$document";
} else if ( typeof target === "string" ) {
id = target;
target = document.getElementById( target );
} else {
id = target.id || "$undefined";
}
// return if this instance already exists
if ( instances[id] ) {
return instances[id];
}
// or make a new instance
self = instances[id] = {
// init & reset
init: function() {
imgs = null;
last = 0;
addEvent( window, "scroll", self.fetchImages );
self.fetchImages();
return this;
},
destroy: function() {
removeEvent( window, "scroll", self.fetchImages );
delete instances[id];
},
// fetches images, starting at last (index)
fetchImages: function() {
var img, temp, len, i;
// still trying to get the target
target = target || document.getElementById( id );
// if it's the first time
// initialize images array
if ( !imgs && target ) {
temp = target.getElementsByTagName( "img" );
if ( temp.length ) {
imgs = [];
len = temp.length;
} else return;
// fill the array for sorting
for ( i = 0; i < len; i++ ) {
img = temp[i];
if ( img.nodeType === 1 && img.getAttribute("thumb") ) {
// store them and cache current
// positions for faster sorting
img.$$top = getTopPos( img );
imgs.push( img );
}
}
imgs.sort( img_sort );
}
// loop through the images
while ( imgs[last] ) {
img = imgs[last];
// delete cached position
if ( img.$$top ) img.$$top = null;
// check if the img is above the fold
if ( getTopPos( img ) < winH + offset ) {
// then change the src
img.src = img.getAttribute("thumb");
last++;
}
else return;
}
// we've fetched the last image -> finished
if ( last && last === imgs.length ) {
self.destroy();
}
}
};
return self.init();
};
// initialize
getWindowHeight();
addEvent( window, "load", LazyImg().fetchImages );
addEvent( window, "resize", getWindowHeight );
LazyImg();
window.LazyImg = LazyImg;
}());
"thumb" does not validate when using XHTML. I changed it to "title" and it seems to be working ok.

Categories

Resources