I get the error: too much recursion. Why is that? - javascript

I have a function to refresh graphs on a page. The idea is that it loops constantly and refreshes a variable called salt. Variables are defined in a separate file and are called path, displayTimeFrom, selectedTimeRangeType and target. Here is the looping code which also responds to changes in the GUI:
$(function () {
refreshGraphs();
});
var refreshGraphs = function () {
d = new Date();
var graphiteUrl = graphs.path + "render/?_salt" + d.getTime()
+ "&from=-" + graphs.displayTimeFrom
+ graphs.selectedTimeRangeType
+ "&minXStep=0"
+ "&until=now&height=800&";
$('#graph-middle').prop("src", graphiteUrl + graphs.target);
setIntervalAndExecute(refreshGraphs, 30000); // refresh every 30000 milliseconds aka every 30 seconds
// Execute immediately and after the interval (setInterval only starts after certain amount of time)
function setIntervalAndExecute(fn, t) {
fn();
return (setInterval(fn, t));
}
// Change graph to chosen value
$('#graph-middle').on('click', '#displayTimeFrom', function () {
graphs.displayTimeFrom = $(this).text();
refreshGraphs();
});
$('#graph-middle').on('click', '#selectedTimeRangeType', function () {
graphs.selectedTimeRangeType = $(this).text();
refreshGraphs();
});
};
When I run it it says "too much recursion". Why is that and how can I solve it?

Your refreshGraphs() function calls itself immediately (via setIntervalAndExecute()) every time it runs.

Two things to note:
1. You're invoking refreshGraphs() recursively.
2. You have placed click handlers in the refreshGraphs() function.
So whenever this refreshGraphs() are invoked it is binding the click events again without unbinding the previous one. You have to either unbind the previous one or you can place them in $(function () {}).
Try any of these.
$(function () {
refreshGraphs();
// Change graph to chosen value
$('#graph-middle').on('click', '#displayTimeFrom', function () {
graphs.displayTimeFrom = $(this).text();
refreshGraphs();
});
$('#graph-middle').on('click', '#selectedTimeRangeType', function () {
graphs.selectedTimeRangeType = $(this).text();
refreshGraphs();
});
});
var refreshGraphs = function () {
d = new Date();
var graphiteUrl = graphs.path + "render/?_salt" + d.getTime()
+ "&from=-" + graphs.displayTimeFrom
+ graphs.selectedTimeRangeType
+ "&minXStep=0"
+ "&until=now&height=800&";
$('#graph-middle').prop("src", graphiteUrl + graphs.target);
setIntervalAndExecute(refreshGraphs, 30000); // refresh every 30000 milliseconds aka every 30 seconds
// Execute immediately and after the interval (setInterval only starts after certain amount of time)
function setIntervalAndExecute(fn, t) {
fn();
return (setInterval(fn, t));
}
};
Or
$(function () {
refreshGraphs();
});
var refreshGraphs = function () {
d = new Date();
var graphiteUrl = graphs.path + "render/?_salt" + d.getTime()
+ "&from=-" + graphs.displayTimeFrom
+ graphs.selectedTimeRangeType
+ "&minXStep=0"
+ "&until=now&height=800&";
$('#graph-middle').prop("src", graphiteUrl + graphs.target);
setIntervalAndExecute(refreshGraphs, 30000); // refresh every 30000 milliseconds aka every 30 seconds
// Execute immediately and after the interval (setInterval only starts after certain amount of time)
function setIntervalAndExecute(fn, t) {
fn();
return (setInterval(fn, t));
}
// Change graph to chosen value
$('#graph-middle').off('click').on('click', '#displayTimeFrom', function () {
graphs.displayTimeFrom = $(this).text();
refreshGraphs();
});
$('#graph-middle').off('click').on('click', '#selectedTimeRangeType', function () {
graphs.selectedTimeRangeType = $(this).text();
refreshGraphs();
});
};

Solution is to call the jQuery in the anonymous function instead of the refreshGraps namespace. Issue solved.

Related

flaws in second's field increment in stop watch

<script>
var s=0;
var ms=0;
function timeDisp()
{
var d = new Date();
ms = d.getMilliseconds();
if(ms==999 && s<60)
{
s=s+1;
ms=0;
}
var r = (((s <10)?"0":":") + s + (":") + ms);
return r;
}
function display()
{
var t = timeDisp();
document.getElementById("time").value=t; //time is id of input text field
m=setTimeout('display()',1);
}
function stop()
{
clearTimeout(m);
}
</script>
I have written this code to create simple stop watch but there is flaw in increment in seconds field.Sometimes second do not increase as it should and sometime it skip one or two seconds while running.

Time Interval seconds run fast on tab changed Javascript

I have an issue that hold my neck with time interval. I am calculating my time/clock one second at a time with the function below.
Header.prototype= {
time_changed : function(time){
var that = this;
var clock_handle;
var clock = $('#gmtclock');
that.time_now = time;
var increase_time_by = function(interval) {
that.time_now += interval;
};
var update_time = function() {
clock.html(moment(that.time_now).utc().format("YYYY-MM-DD HH:mm") + " GMT");
};
update_time();
clearInterval(clock_handle);
clock_handle = setInterval(function() {
increase_time_by(1000);
update_time();
}, 1000);
},
};
The above works fine and increase my time a second at a time correctly . However. I added another event that fires on web changed or tab navigated.
var start_time;
var tabChanged = function() {
if(clock_started === true){
if (document.hidden || document.webkitHidden) {
start_time = moment().valueOf();
time_now = page.header.time_now;
}else {
var tnow = (time_now + (moment().valueOf() - start_time));
page.header.time_changed(tnow);
}
}
};
if (typeof document.webkitHidden !== 'undefined') {
if (document.addEventListener) {
document.addEventListener("webkitvisibilitychange", tabChanged);
}
}
The above fires when ever user leave the page and comes back . It add the delay to the time. However, i notice the second increase rapidly . and very past my timer does not fire very second any more as specified in the clock hand. It add second every milliseconds and fats. Please why this and how do i fix this ? My time run fast and ahead when ever i change tab and returned . Any help would be appreciated
Update
Below is my WS request function.
Header.prototype = {
start_clock_ws : function(){
var that = this;
function init(){
clock_started = true;
WS.send({ "time": 1,"passthrough":{"client_time" : moment().valueOf()}});
}
that.run = function(){
setInterval(init, 900000);
};
init();
that.run();
return;
},
time_counter : function(response){
var that = this;
var clock_handle;
var clock = $('#gmt-clock');
var start_timestamp = response.time;
var pass = response.echo_req.passthrough.client_time;
that.time_now = ((start_timestamp * 1000) + (moment().valueOf() - pass));
var increase_time = function() {
that.time_now += (moment().valueOf() - that.time_now);
};
var update_time = function() {
clock.html(moment(that.time_now).utc().format("YYYY-MM-DD HH:mm") + " GMT");
};
update_time();
clearInterval(clock_handle);
clock_handle = setInterval(function() {
increase_time();
update_time();
}, 500);
},
};
and in my WS open event
if(isReady()=== true){
if (clock_started === false) {
page.header.start_clock_ws();
}
}
In my WS onmessage event
if(type ==='time'){
page.header.time_counter(response);
}
Base on your suggestion, i modified my increase_time_by to
var increase_time_by = function() {
that.time_now += (moment().valueOf() - that.time_now);
};
It seems fine now. Would test further and see.
Instead of incrementing the clock by the value of the interval, just update the clock to the current time with each pass. Then it won't matter if you fire exactly 1000 ms apart or not.
You actually may want to run more frequently, such as every 500 ms, to give a smoother feel to the clock ticking.
Basically, it comes down to the precision of the timer functions, or lack thereof. Lots of questions on StackOverflow about that - such as this one.
Based on your comments, I believe you are trying to display a ticking clock of UTC time, based on a starting value coming from a web service. That would be something like this:
var time_from_ws = // ... however you want to retrieve it
var delta = moment().diff(time_from_ws); // the difference between server and client time
// define a function to update the clock
var update_time = function() {
clock.html(moment.utc().subtract(delta).format("YYYY-MM-DD HH:mm") + " GMT");
};
update_time(); // set it the first time
setInterval(update_time, 500); // get the clock ticking

Image animation with speed control

We have some problem with our image animation with speed control.
It make use of a timeout to change the image, but we want to change the timeout value with a slider, but for some sort of reason, it doesn't work. Can someone help us out ?
We have a Jfiddle here: http://jsfiddle.net/Kbroeren/fmd4xbew/
Thanks! Kevin
var jArray = ["http://www.parijsalacarte.nl/images/mickey-mouse.jpg", "http://www.startpagina.nl/athene/dochters/cliparts-disney/images/donad%20duck-106.jpg", "http://images2.proud2bme.nl/hsfile_203909.jpg"];
var image_count = 0;
function rollover(image_id, millisecs) {
var image = document.getElementById(image_id);
image.src = jArray[image_count];
image_count++;
if (image_count >= jArray.length) {
image_count = 0;
}
var timeout = setTimeout("rollover('" + image_id + "'," + millisecs + ");", millisecs);
}
rollover("img1", 200);
$(function () {
var value;
var $document = $(document),
$inputRange = $('input[type="range"]');
// Example functionality to demonstrate a value feedback
function valueOutput(element) {
var value = element.value,
output = element.parentNode.getElementsByTagName('output')[0];
output.innerHTML = value;
}
for (var i = $inputRange.length - 1; i >= 0; i--) {
valueOutput($inputRange[i]);
};
$document.on('change', 'input[type="range"]', function (e) {
valueOutput(e.target);
rollover("img1", 200);
});
// end
$inputRange.rangeslider({
polyfill: false
});
});
You keep creating more and more infinite function calls without stopping them.
After you call your function the first time, it keeps calling itself.
then you call it again with different interval (millisecs) and it will also start call itself....
You can try two different approach.
1.Use setInterval instead of setTimeout. Use clearInterval to clear the interval before setting it with a new value.
/// Call animation() every 200 ms
var timer = setInterval("Animation()",200);
function ChageSpeed(miliseces){
///Stop calling Animation()
clearInterval(timer);
/// Start calling Animation() every "miliseces" ms
timer = setInterval("Animation()",miliseces);
}
function Animation(){
/// Animation code goes here
}
2.Or, Instead, Set your interval as a global variable (not cool) and just change it value when the user want to change the animation speed.
var millisecs = 200;
function rollover(image_id) {
var image = document.getElementById(image_id);
image.src = jArray[image_count];
image_count++;
if (image_count >= jArray.length) {
image_count = 0;
}
var timeout = setTimeout("rollover('" + image_id + "'," + millisecs + ");", millisecs);
}
$document.on('change', 'input[type="range"]', function (e) {
valueOutput(e.target);
millisecs = YourNewValue;
});

How to check mouse holded some sec on a element

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);
}

only the last setInterval run

I have the following javascript code
function RefreshElastic() {
Elastic.refresh();
}
function ShowTime() {
var Sekarang = new Date();
var Waktu = Sekarang.getDate() + "/" +
Sekarang.getMonth() + " - " +
Sekarang.getHours() + ":" +
Sekarang.getMinutes();
$("#jam").html(Waktu);
Elastic.refresh();
}
var IntervalElastic = setInterval(function () {
RefreshElastic();
}, 500);
var IntervalTime = setInterval(function () {
ShowTime();
}, 1000 * 30);
I want to have 2 intervals, each has a function to call.
The RefreshElastic called only twice.
The ShowTime always called every 30 seconds.
Why is that?
Additional note:
I changed the millis for RefreshElastic to a larger value, like 5000. And RefreshElastic never called.

Categories

Resources