setInterval not working as expected with javascript oops - javascript

Js Fiddle : check here
I have setInterval() inside a method of a class. It works properly when single instance is created but fails when many instance created. When more than one instance created , only the last created instance work and other stops.
My script is as below :
function timer() {
this.ran = Math.floor(Math.random() * 100) + 1;
this.cls = this.ran + '_ocar';
this.div = '<div class="' + this.cls + '">' + this.cls + '</div>';
$('body').append(this.div);
this.run = function() {
thi = this;
thi.k = 0;
setInterval(function() {
console.log(thi.cls);
$('.' + thi.cls).html(thi.k++);
}, 1000);
}
}
one = new timer();
one.run();
setInterval(function() {
new timer().run();
}, 5000);

thi = this; is being created in the global namespace, so is being overwritten each time you initialise a new timer().
Change it to var thi = this;.
https://jsfiddle.net/daveSalomon/h5e8LLg3/`
I don't like thi as a var name - it looks like a typo. I usually use _this or _scope.

Try this:
function timer(){
var thi = this;
this.ran = Math.floor(Math.random() * 100) + 1;
this.cls = this.ran+'_ocar';
this.div = '<div class="'+this.cls+'">'+this.cls+'</div>';
$('body').append(this.div);
this.run = function(){
thi.k = 0;
setInterval(function(){
console.log(thi.cls);
$('.'+thi.cls).html(thi.k++);
},1000);
}
}
one = new timer();
one.run();
setInterval(function(){
new timer().run();
},5000)
Your variable thi need to be declared locally and moved.

Related

trying to reach function inside a class javascript

Good evening, If someone could help me , I would be glad.I am trying to reach some functions in my Car class. Firstly I am trying to assign inpSpeed input value to Car class function Drive and then I wanna print out to console all cars info when I press the button: btnRace and the problem is I dont really know how to call them , because everytime I call them it says:"undefined".
here is my code so far:
carsArray = [];
btnCarName.onclick = function(){
carsArray.push({/*obj.element1, obj.element2, obj.element3*/});
}
btnRace.onclick = function(){
for(j in carsArray)
{
console.log(Car(carsArray[j]));
}
}
function Car(name,speed)
{
this.carBrand = name;
this.speed = speed;
this.distance = 0;
this.Drive = function(time)
{
if(time > 0)
return this.distance = (this.speed * (time/10));
}
this.printData = function()
{
for(var i = 0; i < Car.length; i++)
{
console.log('Car brand: ' + this.carBrand);
console.log('Speed: ' + this.speed);
console.log('distance: ' + this.Drive());
console.log('---------------------------');
}
}
}
For the this keyword to work, you must instantiate Car() with the new keyword:
var toyota = new Car('toyota', 100)
console.log(toyota.speed);
There may however be a couple other issues. What exactly is expected from Car.length?

Javascript will not update or display the system time< how come?

This is my javascript code, I checked it in Chrome and its not giving me an error
window.onload = function() {
var timeClock = function (){
setTimeout("timeClock()", 1000);
var timeObj = new Date();
var currTime = timeObj.getHours(); + " : " + timeObj.getMinutes(); + " : " + timeObj.getSeconds();
document.getElementById("#clock-container").innerHTML = "asd";
}
}
I am trying to update this div with the current system time
<div id="clock-container"></div>
You have multiple logic and other mistakes.
You are attempting to register the callback, but your setTimeout is in the callback itself. Move setTimeout("timeClock()", 1000); outside the callback.
Presumably you also want to replace setTimeout with setInterval to have the clock continuously update, and also avoid having to call setTimeout in the callback.
There's also no reason to use a string to call timeClock, so use setInterval(timeClock, 1000); instead and avoid the evil that is code evaluation.
document.getElementById("#clock-container") should be document.getElementById("clock-container").
Your currTime expression has several ; where they don't belong, fix those and you can use this variable instead of your string.
You can also call timeClock immediately after load, to avoid waiting for the first interval.
Working Example:
window.onload = function() {
var timeClock = function (){
var timeObj = new Date();
var currTime = timeObj.getHours() + " : " + timeObj.getMinutes() + " : " + timeObj.getSeconds();
document.getElementById("clock-container").innerHTML = currTime;
}
setInterval(timeClock, 1000);
timeClock();
}
<div id="clock-container"></div>
I am not sure what you're trying to do but The script should be
window.onload = function() {
var timeClock = function (){
var timeObj = new Date();
var currTime = timeObj.getHours() + " : " + timeObj.getMinutes() + " : " + timeObj.getSeconds();
document.getElementById("clock-container").innerHTML = currTime;
setTimeout(timeClock, 1000);
}
timeClock();
}

Object constructor - managing loop animation

I am doing a website wich has a lot of animations managed by JavaScript, when i started i just defined a function and some variables for the animation and repeat the process, like this. And a think is not the good way.
//BRIGHT ANIMATION
var frameWidth1 = 386;
var frameHeight1 = 100;
var spriteWidth1 = 20067;
var spriteHeight1 = 100;
var spriteElement1 = document.getElementById("bright");
var curPx1 = 0;
var ti1;
function animateSpriteB() {
spriteElement1.style.backgroundPosition = "-" + curPx1 + 'px 0px';
curPx1 = curPx1 + frameWidth1;
if (curPx1 >= spriteWidth1) {
curPx1 = 0;
}
ti1 = setTimeout(animateSpriteB, 70);
}
animateSpriteB();
// PAPIRO ANIMATION
var frameWidth = 56;
var frameHeight = 218;
var spriteWidth = 2016;
var spriteHeight = 218;
var spriteElement = document.getElementById("roll-off");
var curPx = 0;
var ti;
function animateSprite() {
spriteElement.style.backgroundPosition = "-" + curPx + 'px 0px';
curPx = curPx + frameWidth;
ti = setTimeout(animateSprite, 27.7);
if (curPx === spriteWidth) {
clearTimeout(ti);
}
}
function slideMask(){
var mask = $("#paper-mask");
var paper = $("#paper");
mask.animate({
width: 450
},{
duration: 1000,
complete: function(){
$("#paper-content").fadeIn();
}
});
}
var ti = setTimeout(function(){
animateSprite();
slideMask();
}, 3000);
So know, I decided to use a constructor to re use the same code and manage all the animations in the website. i came with Something like this:
// CONSTRUCTOR WHO MANAGE THE ANIMATIONS FOR THE WEBSITE
function SpriteAnimation(frameWidth, spriteWidth, spriteElement, isLoop){
this.frameWidth = frameWidth;
this.spriteWidth = spriteWidth;
this.spriteElement = spriteElement;
this.isLoop = isLoop;
this.curPx = 0;
this.ti;
}
SpriteAnimation.prototype.start = function(){
var selector = document.getElementById(this.spriteElement);
selector.style.backgroundPosition = "-" + this.curPx + "px 0px";
this.curPx = this.curPx + this.frameWidth;
this.ti = setTimeout(this.start, 2000);
if (this.curPx === this.spriteWidth){
clearTimeout(this.ti);
}
this.start();
}
var letter = new SpriteAnimation(935.4, 17774, "letter", true);
letter.start();
I am having problems in performance, every time i run the code my browser just crash i also think im not doing good the loop. So here comes my question: how can i do to manage the animations with an object constructor in wich i can pass parameters like if it is loop animation and the sprite parameters?... I appreciate the help you guys can bring me :)
#Tibos Your code has been from great help for me i just spent almost 4 hours trying to achieve this, and then yo came out and make it really easy, this is how my code looks now, i added another parameter: frame rate. so every animation can have a different frame rate. Also modified a bit the if statement because the animation was running untill the sprite dissapear and i need them to stay in the last frame, let me know if this is the correct form.
// CONSTRUCTOR WHO MANAGE THE ANIMATIONS FOR THE WEBSITE
function SpriteAnimation(frameWidth, spriteWidth, spriteElement, shouldLoop, frameRate){
this.frameWidth = frameWidth;
this.spriteWidth = spriteWidth;
this.selector = document.getElementById(spriteElement);
this.shouldLoop = shouldLoop ;
this.curPx = 0;
this.frameRate = frameRate;
this.ti;
}
SpriteAnimation.prototype.start = function(){
this.selector.style.backgroundPosition = "-" + this.curPx + "px 0px";
this.curPx += this.frameWidth;
if (this.curPx < (this.spriteWidth - this.frameWidth)){
setTimeout(this.start.bind(this), this.frameRate);
} else if (this.shouldLoop) {
this.curPx = 0;
this.start();
}
};
var letter = new SpriteAnimation(935.4, 17774, "letter", true, 60);
letter.start();
You have a few problems in your code, presented here in order of impact:
recursively calling start
losing the reference to this
clearing timeout as soon as it's set
unused variables
selecting the element at each iteration
Here is some better code (that works):
function SpriteAnimation(frameWidth, spriteWidth, spriteElement, shouldLoop){
this.frameWidth = frameWidth;
this.spriteWidth = spriteWidth;
this.selector = document.getElementById(spriteElement);
this.curPx = 0;
this.shouldLoop = shouldLoop;
}
SpriteAnimation.prototype.start = function(){
this.selector.style.backgroundPosition = "-" + this.curPx + "px 0px";
this.curPx += this.frameWidth;
if (this.curPx <= this.spriteWidth){
setTimeout(this.start.bind(this), 2000);
} else if (this.shouldLoop) {
this.curPx = 0;
this.start();
}
};
var letter = new SpriteAnimation(935.4, 17774, "letter", true);
letter.start();
DEMO: http://jsbin.com/oJIYoRU/1/edit
This function calls itself recursively with no base case. As soon as you invoke it you will lock the UI and overflow the call-stack.
SpriteAnimation.prototype.start = function(){
... some code ...
this.start();
}

Javascript setInterval not making it into function

Ok Im trying to do a setInterval into a sub function and its not making it in there...my alert is not firing off because of this:
var doneVar= 0;
var groupsVar= 4;
var interval = setInterval(process_chunk, 1000);
var $myTree= $("#myTree");
var chunkLength = myArray.length / groupsVar;
process_chunk = function() {
alert("we are after chunk");
var arrayChunk = myArray.slice(doneVar*chunkLength, (doneVar + 1)*chunkLength);
//alert("we are in function!!");
$.each(arrayChunk, function(key, item){
$myTree.jstree("uncheck_node", "#"+item);
});
doneVar += 1;
if (doneVar === groupsVar) {
interval.clearInterval();
}
}
process_chunk has not been assigned a value yet, when you pass it into setInterval. Move the line:
var interval = setInterval(process_chunk, 1000);
To right before (and right after the anonymous function is assigned to process_chunk):
doneVar += 1;
Or if you are looking for hoisting the function then use a function declaration rather than an expression:
function process_chunk() {
Both versions will solve your problem.
You need to declare the function before using it.
Put
process_chunk = function() { ... });
Before
var interval = setInterval(process_chunk, 1000);
If you are only using the function from the interval use this (my preferred method, your way is not wrong)
var doneVar= 0;
var groupsVar= 4;
var $myTree= $("#myTree");
var chunkLength = myArray.length / groupsVar;
var interval = setInterval(function() {
alert("we are after chunk");
var arrayChunk = myArray.slice(doneVar*chunkLength, (doneVar + 1)*chunkLength);
//alert("we are in function!!");
$.each(arrayChunk, function(key, item){
$myTree.jstree("uncheck_node", "#"+item);
});
doneVar += 1;
if (doneVar === groupsVar) {
interval.clearInterval();
}
},1000);
that should do it, doing it this way and defining the function within the interval prevents many problems, like in this case you need to defined the function before you set it in an interval. Here is another version keeping your style.
var doneVar= 0;
var groupsVar= 4;
var $myTree= $("#myTree");
var chunkLength = myArray.length / groupsVar;
var process_chunk = function() {
alert("we are after chunk");
var arrayChunk = myArray.slice(doneVar*chunkLength, (doneVar + 1)*chunkLength);
//alert("we are in function!!");
$.each(arrayChunk, function(key, item){
$myTree.jstree("uncheck_node", "#"+item);
});
doneVar += 1;
if (doneVar === groupsVar) {
interval.clearInterval();
}
}
var interval = setInterval(process_chunk, 1000);
I guess one other thing I noticed just now, you use process_chuck and not var process_chuck witch can cause problems too. Fixed in second answer, not applicable in first.

Cookie Code not removing opened element of cookie

var openClose = $('.openClose');
openClose.on('click', function() {
var cook = ReadCookie('slideHide'),
miniParent = $(this).parent().parent().parent().children('.main-content'),
miniDisp = miniParent.css('display');
if (miniDisp ==="block") {
KillCookie('slideHide');
$(this).parent().parent().parent().children('.main-content').slideUp();
var slide = cook + "," + "#"+$(this)
.parent()
.parent()
.parent()
.parent().attr("id") +
" #"+$(this).parent()
.parent().parent().attr("id");
SetCookie('slideHide', slide, 100);
}
else
{
$(this).parent().parent().parent().children('.main-content').slideDown();
var newCookie=[];
var a= $('.module').children('.main-content').filter(":hidden");
for(var i=0;i<a.length;i++){
var d = $(a[i++]);
var c = "#"+d.parent('.module').attr('id');
}
newCookie= c;
console.log(newCookie);
KillCookie('slideHide');
SetCookie('slideHide',d, 100);
}
});
These are my cookie functions:
function SetCookie(cookieName,cookieValue,nDays) {
var today = new Date();
var expire = new Date();
if (nDays==null || nDays==0) nDays=1;
expire.setTime(today.getTime() + 3600000*24*nDays);
document.cookie = cookieName+"="+escape(cookieValue)
+ ";expires="+expire.toGMTString(),';path = /';
}
function KillCookie(cookieName) {
SetCookie(cookieName,"", - 1);
}
function ReadCookie(cookieName) {
var theCookie=""+document.cookie;
var ind=theCookie.indexOf(cookieName+"=");
if (ind==-1 || cookieName=="") return "";
var ind1=theCookie.indexOf(";",ind);
if (ind1==-1) ind1=theCookie.length;
return unescape(theCookie.substring(ind+cookieName.length+1,ind1));
}
Setting the cookie to make it slideUp and stay hidden works, but when I try to open it, it slidesDown, then I refresh the page it doesn't stay open like it should.
To sort of get the picture - http://jsfiddle.net/zRT9u/
If you need to know more please ask me I am willing to provide more!
I edited the javascript it almost works but I am not getting all the objects that I need
NEW EDIT- Tried the $.map() function but when I open one, and refresh all of them are now open?
else {
$(this).parent().parent().parent().children('.main-content').slideDown();
KillCookie('slideHide');
var newCookie=[];
var a= $('.module').children('.main-content').filter(":hidden");
var c = $.map(a,function(n,i){
return $(n).parent().attr('id');
});
newCookie= c;
SetCookie('slideHide',newCookie, 100);
}
Fixed it by using $.map and .join()
var openClose = $('.openClose');
openClose.on('click', function() {
var cook = ReadCookie('slideHide'),
miniParent = $(this).parent().parent().parent().children('.main-content'),
miniDisp = miniParent.css('display');
if (miniDisp ==="block") {
KillCookie('slideHide');
$(this).parent().parent().parent().children('.main-content').slideUp();
var slide = cook+","+ "#"+$(this).parent().parent().parent().attr("id");
SetCookie('slideHide', slide, 100);
} else {
$(this).parent().parent().parent().children('.main-content').slideDown();
KillCookie('slideHide');
var newCookie=[],
a= $('.module').children('.main-content').filter(":hidden"),
c = $.map(a,function(n,i){
return "#"+$(n).parent().attr('id');
});
newCookie= c.join(',');
SetCookie('slideHide',newCookie, 100);
}
});
By creating a "global" array and then using the $.map function as well as adding "#"+ to the map function I was able to get the actual ID names. Then I set newCookie to c.join(',') and everything works perfectly after that!

Categories