javascript setInterval on an object's function only calls 2x - javascript

var focus = true;
function z() {
this.t = 0;
this.p = function (t) {
if (focus == true) {
this.t = t;
alert(this.t);
}
}
}
var zp = new z();
setTimeout('zp.p(0)', 100);
window.setInterval('zp.p(1)', 2000);
var ftimer = setTimeout('focus=false', 2000);
document.addEventListener('mousemove', function (e) {
clearTimeout(ftimer);
focus = true;
ftimer = setTimeout('focus=false', 2000);
}, false);
I have this code. but for some reason it only alerts twice even with continuous mouse movements. I have been working at this and investigating in firebug and focus is true when I am moving my mouse. I have been trying to figure out what is going on.. even if I do this:
function z() {
this.t = 0;
this.p = function (t) {
if (focus == true) {
this.t = t;
}
alert(this.t);
}
}
It still only alerts twice.
I have tried using a looping setTimeout function too but that doesnt work either. It is driving me crazy.

Good that you found your bug.
I would write your code using a bit more functions-as-first-class-objects and less eval logic:
var focus = true;
function z() {
var that = this; // we won't always have the correct value of "this"
this.focus = true;
this.t = 0;
this.p = function (t) {
if (that.focus == true) {
that.t = t;
alert(t);
}
}
this.fade = ( function(obj){ return function(){ obj.focus = false; } } )(this); // Using self-invokation
}
var zp = new z();
setTimeout(zp.p, 100, 0);
window.setInterval(zp.p, 2000, 1);
var ftimer = setTimeout(zp.fade, 2000);
document.addEventListener('mousemove', function (e) {
clearTimeout(ftimer);
zp.focus = true;
ftimer = setTimeout(zp.fade, 2000);
}, false);
I used a self-invoking function on line 10: ( function(obj){ return function(){...} })(this);, and set this to a different variable.

I found out that it was just related to firefox and that firefox choked on a line of code so that is why it wouldn't run. So I fixed that and now everything is all good.

Related

variable changing to true before setInterval is finished

showMoves is a function made to show flashing for a simon game.
When the flashing lights are over I clear the interval to stop it and then I set game.playerTurn to true so I can click on colors, but game.playerTurn is changing to true as soon as showMoves is activated.
I want game.playerTurn to stay false until the showMoves function is finished showing flashing.
Here are the functions I'm using game.playerTurn in -
game.playerTurn = false;
//for flashing lights
function showMoves() {
let i = 0;
const start = setInterval(function () {
if (i >= game.computerMoves.length) {
clearInterval(start);
game.playerTurn = true;
return;
}
const move = game.computerMoves[i];
setLight(move, true);
setTimeout(setLight.bind(null, move, false), 1000); //Using bind to preset arguments
i++;
}, 2000);
}
function setLight(color, isOn) {
if (isOn) {
sounds[color.id].play();
}
color.style.backgroundColor = isOn ? colors[0].get(color) : colors[1].get(color);
}
//compareMoves is fired everytime I click on a color
function compareMoves(e) {
if (e === game.computerMoves[game.counter]) {
game.counter++;
//This is if all the moves were chosen correctly
if (game.playerMoves.length === game.computerMoves.length && e === game.computerMoves[game.computerMoves.length - 1]) {
simonHTML.displayScore.textContent = ++game.score;
game.playerTurn = false;
resetMoves();
randomMoves(++game.turn);
showMoves();
game.counter = 0;
}
} else if (game.strict) {
//if your move was wrong do this
} else {
game.playerMoves = [];
game.counter = 0;
game.playerTurn = false;
showMoves();
return false;
}
}
I'd appreciate any help with this. Here is a link to the game and all the code https://codepen.io/icewizard/pen/JLBpNQ
Where are you setting game.playerTurn back to false?
function showMoves() {
game.playerTurn = false;
let i = 0;
const start = setInterval(function() {
if (i >= game.computerMoves.length) {
clearInterval(start);
game.playerTurn = true;
return;
}
const move = game.computerMoves[i];
setLight(move, true);
setTimeout(setLight.bind(null, move, false), 1000); //Using bind to preset arguments
i++;
}, 2000);
}
Seems to work for me in the codepen example you provided

Javascript binding issue not resolved by calling bind

I am trying to recursively call a function until the game has ended, however, during the execution "this" gets reset to 'window', which causes the following error: "cannot read property 'step' of undefined."
I have tried rewriting the offending line as
this.game.bind(this).step();
as well as
this.game.step.bind(this);
Neither are working. For context, step is just a function that calls two helpers in Game that move objects and look for collisions, when I used those instead of step, the error remained.
/* globals key */
const Game = require('./game.js');
let speed = 1;
function GameView(ctx) {
this.ctx = ctx;
this.game = new Game();
}
GameView.prototype.start = function (callback) {
// let that = this
this.bindKeyHandlers();
this.animate(0);
};
GameView.prototype.animate = function(time) {
speed += 1;
if (speed >= 605) {
speed = 0;
};
this.game.step();
this.game.draw(this.ctx, speed);
if(!this.game.lose()){
requestAnimationFrame(this.animate());
}
else {
this.ctx.fillStyle = "white";
this.ctx.font = "italic "+24+"pt Arial ";
this.ctx.fillText(`Game Over \n Press Enter to restart`, 100,200 );
key('enter', ()=>{
this.game = new Game();
this.start();
});
}
};
GameView.prototype.bindKeyHandlers = function() {
key('d', () => {
this.game.ship.power([2, 0]);
});
key('a', () => {
this.game.ship.power([-2, 0]);
});
key('s', () => {
this.game.ship.power([0, 2]);
});
key('w', () => {
this.game.ship.power([0, -2]);
});
key('l', () => {
this.game.ship.fireBullet();
});
};
module.exports = GameView;
Your problem is that this of the animate function does not refer to the context you wish it to. So your offending line (or lack thereof) is completely elsewhere.
Function.bind returns a function and you need to this new bound functions somewhere and the perfect place for this is the constructor. Here's an example:
function GameView(ctx) {
this.ctx = ctx;
this.game = new Game();
this.animate = this.animate.bind(this)
}
See this jsfiddle for more, remember to open your developer console to witness the error from calling notBound
Hope this helps!

setTimeOut + window.onblur+ window.onfocus

I´m trying to use setTimeout to recall a function. When window is not on focus so we will set that function to take a pause until window is on focus again. Let see my script
(function() {
var time = 10000,
delta = 100,
tid;
tid = setInterval(function() {
if ( window.blurred ) { return; }
time -= delta;
if ( time <= 0 ) {
clearInterval(tid);
dosomething (user_id); // function to do something
}
}, delta);
})();
window.onblur = function() { window.blurred = true; };
window.onfocus = function() { window.blurred = false; };
Actually it work as I expected BUT
My question is :
I'm trying to change the method to-----> setTimeout and clearTimeout Why it doesn't work ?
After many test I found that this function doesn't work in IE, do we have any solution ?

jquery conflict with js script

welcome all ,
i have a problem with my images slider , it runs successfuly until poll script excuted then it stops , tried to combine both scripts didn't work also tried to use noConflict but in stops both of them .
this is the slider
(function ($) {
$.fn.s3Slider = function (vars) {
var element = this;
var timeOut = (vars.timeOut != undefined) ? vars.timeOut : 4000;
var current = null;
var timeOutFn = null;
var faderStat = true;
var mOver = false;
var items = $("#sliderContent .sliderImage");
var itemsSpan = $("#sliderContent .sliderImage span");
items.each(function (i) {
$(items[i]).mouseover(function () {
mOver = true
});
$(items[i]).mouseout(function () {
mOver = false;
fadeElement(true)
})
});
var fadeElement = function (isMouseOut) {
var thisTimeOut = (isMouseOut) ? (timeOut / 2) : timeOut;
thisTimeOut = (faderStat) ? 10 : thisTimeOut;
if (items.length > 0) {
timeOutFn = setTimeout(makeSlider, thisTimeOut)
} else {
console.log("Poof..")
}
};
var makeSlider = function () {
current = (current != null) ? current : items[(items.length - 1)];
var currNo = jQuery.inArray(current, items) + 1;
currNo = (currNo == items.length) ? 0 : (currNo - 1);
var newMargin = $(element).width() * currNo;
if (faderStat == true) {
if (!mOver) {
$(items[currNo]).fadeIn((timeOut / 6), function () {
if ($(itemsSpan[currNo]).css("bottom") == 0) {
$(itemsSpan[currNo]).slideUp((timeOut / 6), function () {
faderStat = false;
current = items[currNo];
if (!mOver) {
fadeElement(false)
}
})
} else {
$(itemsSpan[currNo]).slideDown((timeOut / 6), function () {
faderStat = false;
current = items[currNo];
if (!mOver) {
fadeElement(false)
}
})
}
})
}
} else {
if (!mOver) {
if ($(itemsSpan[currNo]).css("bottom") == 0) {
$(itemsSpan[currNo]).slideDown((timeOut / 6), function () {
$(items[currNo]).fadeOut((timeOut / 6), function () {
faderStat = true;
current = items[(currNo + 1)];
if (!mOver) {
fadeElement(false)
}
})
})
} else {
$(itemsSpan[currNo]).slideUp((timeOut / 6), function () {
$(items[currNo]).fadeOut((timeOut / 6), function () {
faderStat = true;
current = items[(currNo + 1)];
if (!mOver) {
fadeElement(false)
}
})
})
}
}
}
};
makeSlider()
}
})(jQuery);
and this is the poll script
window.onload = function() {
$(".sidePollCon").load("ar_poll.html", function(r, s, xhr) {
if (s == "error") {
$(".sidePollCon").load("poll.html");
} else {
$(".vote_booroo").html("صوت الان");
$(".viewresults").html("شاهد النتيجة");
$("fieldset p").html("");
$(".results_booroo p").html("");
$(".result_booroo").attr("src", "../images/poll_color.jpg");
}
});
};
One potential problem could be the window.onload assignment. It is very prone to conflict.
Every time you do window.onload = the previous assignemnt will be overridden. See demo here:
The output shows that the first window.onload assignment never gets called, while the jQuery alternative does get called.
jQuery.noConflict does little in this regard. All it does is to prevent override the $ symbol so that another lib can use it.
So if you are also using the window.onload event to invoke the slider, then you have conflict. You can easily solve this problem by using the jquery format:
$(window).load(function() {
...
});
However usually you would tie the event to $(document).load(function(){...}); or in short form: $(function(){...}).
So for your poll that would be:
$(function(){
$(".sidePollCon").load("ar_poll.html", function(r, s, xhr) {
if (s == "error") {
$(".sidePollCon").load("poll.html");
} else {
$(".vote_booroo").html("صوت الان");
$(".viewresults").html("شاهد النتيجة");
$("fieldset p").html("");
$(".results_booroo p").html("");
$(".result_booroo").attr("src", "../images/poll_color.jpg");
}
});
});
Hope that helps.
resolving conflicts in jquery (possibly with another JS library .. like script.aculo.us) can be resolved using noconflict()
http://api.jquery.com/jQuery.noConflict/
$.noConflict();
but make sure that u have no error in your javascript code itself. use firebug and
console.log('') to test your script.

How to know browser idle time?

How can I track the browser idle time? I am using IE8.
I am not using any session management and don't want to handle it on server side.
Here is pure JavaScript way to track the idle time and when it reach certain limit do some action:
var IDLE_TIMEOUT = 60; //seconds
var _idleSecondsTimer = null;
var _idleSecondsCounter = 0;
document.onclick = function() {
_idleSecondsCounter = 0;
};
document.onmousemove = function() {
_idleSecondsCounter = 0;
};
document.onkeypress = function() {
_idleSecondsCounter = 0;
};
_idleSecondsTimer = window.setInterval(CheckIdleTime, 1000);
function CheckIdleTime() {
_idleSecondsCounter++;
var oPanel = document.getElementById("SecondsUntilExpire");
if (oPanel)
oPanel.innerHTML = (IDLE_TIMEOUT - _idleSecondsCounter) + "";
if (_idleSecondsCounter >= IDLE_TIMEOUT) {
window.clearInterval(_idleSecondsTimer);
alert("Time expired!");
document.location.href = "logout.html";
}
}
#SecondsUntilExpire { background-color: yellow; }
You will be auto logged out in <span id="SecondsUntilExpire"></span> seconds.
​This code will wait 60 seconds before showing alert and redirecting, and any action will "reset" the count - mouse click, mouse move or key press.
It should be as cross browser as possible, and straight forward. It also support showing the remaining time, if you add element to your page with ID of SecondsUntilExpire.
The above code should work fine, however has several downsides, e.g. it does not allow any other events to run and does not support multiply tabs. Refactored code that include both of these is following: (no need to change HTML)
var IDLE_TIMEOUT = 60; //seconds
var _localStorageKey = 'global_countdown_last_reset_timestamp';
var _idleSecondsTimer = null;
var _lastResetTimeStamp = (new Date()).getTime();
var _localStorage = null;
AttachEvent(document, 'click', ResetTime);
AttachEvent(document, 'mousemove', ResetTime);
AttachEvent(document, 'keypress', ResetTime);
AttachEvent(window, 'load', ResetTime);
try {
_localStorage = window.localStorage;
}
catch (ex) {
}
_idleSecondsTimer = window.setInterval(CheckIdleTime, 1000);
function GetLastResetTimeStamp() {
var lastResetTimeStamp = 0;
if (_localStorage) {
lastResetTimeStamp = parseInt(_localStorage[_localStorageKey], 10);
if (isNaN(lastResetTimeStamp) || lastResetTimeStamp < 0)
lastResetTimeStamp = (new Date()).getTime();
} else {
lastResetTimeStamp = _lastResetTimeStamp;
}
return lastResetTimeStamp;
}
function SetLastResetTimeStamp(timeStamp) {
if (_localStorage) {
_localStorage[_localStorageKey] = timeStamp;
} else {
_lastResetTimeStamp = timeStamp;
}
}
function ResetTime() {
SetLastResetTimeStamp((new Date()).getTime());
}
function AttachEvent(element, eventName, eventHandler) {
if (element.addEventListener) {
element.addEventListener(eventName, eventHandler, false);
return true;
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, eventHandler);
return true;
} else {
//nothing to do, browser too old or non standard anyway
return false;
}
}
function WriteProgress(msg) {
var oPanel = document.getElementById("SecondsUntilExpire");
if (oPanel)
oPanel.innerHTML = msg;
else if (console)
console.log(msg);
}
function CheckIdleTime() {
var currentTimeStamp = (new Date()).getTime();
var lastResetTimeStamp = GetLastResetTimeStamp();
var secondsDiff = Math.floor((currentTimeStamp - lastResetTimeStamp) / 1000);
if (secondsDiff <= 0) {
ResetTime();
secondsDiff = 0;
}
WriteProgress((IDLE_TIMEOUT - secondsDiff) + "");
if (secondsDiff >= IDLE_TIMEOUT) {
window.clearInterval(_idleSecondsTimer);
ResetTime();
alert("Time expired!");
document.location.href = "logout.html";
}
}
The refactored code above is using local storage to keep track of when the counter was last reset, and also reset it on each new tab that is opened which contains the code, then the counter will be the same for all tabs, and resetting in one will result in reset of all tabs. Since Stack Snippets do not allow local storage, it's pointless to host it there so I've made a fiddle:
http://jsfiddle.net/yahavbr/gpvqa0fj/3/
Hope this is what you are looking for
jquery-idletimer-plugin
Too late to reply, but this might help someone to write clean and practical solution. This is an ideal solution, when you do not need to display time left for session expire. Good to ignore setInterval(), which keeps on running the script through out the application running time.
var inactivityTimeOut = 10 * 1000, //10 seconds
inactivitySessionExpireTimeOut = '';
setSessionExpireTimeOut();
function setSessionExpireTimeOut () {
'use strict';
clearSessionExpireTimeout();
inactivitySessionExpireTimeOut = setTimeout(function() {
expireSessionIdleTime();
}, inactivityTimeOut);
}
function expireSessionIdleTime () {
'use strict';
console.log('user inactive for ' + inactivityTimeOut + " seconds");
console.log('session expired');
alert('time expired');
clearSessionExpireTimeout();
document.location.href = "logout.html";
}
function clearSessionExpireTimeout () {
'use strict';
clearTimeout(inactivitySessionExpireTimeOut);
}
Running example: Timeout alert will be popped up in 10 seconds
Here's an approach using jquery as I needed to preserve existing keyboard events on the document.
I also needed to do different things at different idle times so I wrapped it in a function
var onIdle = function (timeOutSeconds,func){
//Idle detection
var idleTimeout;
var activity=function() {
clearTimeout(idleTimeout);
console.log('to cleared');
idleTimeout = setTimeout(func, timeOutSeconds * 1000);
}
$(document).on('mousedown mousemove keypress',activity);
activity();
}
onIdle(60*60,function(){
location.reload();
});
onIdle(30,function(){
if(currentView!=='welcome'){
loadView('welcome');
}
});
I needed a similar thing and created this :https://github.com/harunurhan/idlejs
It simple, configurable and powerful in a way, without any dependencies. Here's an example.
import { Idle } from 'idlejs/dist';
// with predefined events on `document`
const idle = new Idle()
.whenNotInteractive()
.within(60)
.do(() => console.log('IDLE'))
.start();
You can also use custom event targets and events
const idle = new Idle()
.whenNot([{
events: ['click', 'hover'],
target: buttonEl,
},
{
events: ['click', 'input'],
target: inputEl,
},
])
.within(10)
.do(() => called = true)
.start();
(Written in typescript and compiled to es5)

Categories