I was trying to make an image rotate in time after it got loaded, but it seemed that setInterval wasn't working properly. Therefore, I replaced the original function with test() in order to see if that worked.
Now, I would have expected that test() would be called ten times,
but test() wouldn't get called, even once.
I'd been struggling to find out the answer, in vain...
and searched through stock overflow, but all the problems seemed
irrelevant to the phenomenon I was experiencing.
I would really appreciate it if some code-guru can explain to me what is going on!
var testnum=0;
var testTimer;
function test()
{
alert(testnum);
if(++testnum>10)
clearInterval(testTimer);
}
function r_help2(rot_obj)
{
//rot_obj.rotTimer = setInterval( function(){r_helper(rot_obj);}, 20);
testTimer = setInterval(function(){test()},20);
}
function rotate(name, x,y)
{
var rot_obj={angle:0,lim:180};
rot_obj.img = new Image();
rot_obj.x = x;
rot_obj.y = y;
rot_obj.img.src = "rot_"+name+".png"; //rot_1.png, ...etc
rot_obj.img.addEventListener("load",function(){r_help2(rot_obj);});
}
Related
I am trying to work with closures to speed up my script code in Google Scripts. The concept is new to me but I am wondering if the closure is applied correctly in the code below. (the code works)
Background: the code is to calculate how much a month has progressed in percentages.
I don't want the now and month variables to update every time the function is called but only once if the document is opened. What I essentially want is that all variables are set only once and that the function will deliver an answer if it's called multiple times.
Is this a good reason to use a closure and am I using it correctly?
Thanks for your advice and patience.
// calculate progress with second precision
var progressCalc = (function() {
const stMonth = SpreadsheetApp.getActive()
.getRangeByName("pStartdate")
.getValue();
const eoMonth = SpreadsheetApp.getActive()
.getRangeByName("pEndOfMonthDate")
.getValue();
const now = new Date();
var unixProgressEoMonth = unixTime(eoMonth)-unixTime(stMonth)
var unixProgressNow = unixTime(now)-unixTime(stMonth)
return function () { return unixProgressNow/unixProgressEoMonth;};
})();
function progress() {
Logger.log(progressCalc());
return progressCalc();
}
I am trying to work with closures to speed up my script code in Google Scripts.
Then you should not evaluate the calculation every time progressCalc is called.
Is this a good reason to use a closure?
No. In fact, your calculation has a constant result, so there's no point in putting it in a function and executing it multiple times at all. Instead of storing a function, just store the result value right away:
var progressValue = (function() {
const stMonth = SpreadsheetApp.getActive()
.getRangeByName("pStartdate")
.getValue();
const eoMonth = SpreadsheetApp.getActive()
.getRangeByName("pEndOfMonthDate")
.getValue();
const now = new Date();
var unixProgressEoMonth = unixTime(eoMonth)-unixTime(stMonth)
var unixProgressNow = unixTime(now)-unixTime(stMonth)
return unixProgressNow/unixProgressEoMonth;
})();
function progress() {
Logger.log(progressValue);
}
The code isn't doing anything at all, the images are just staying still
Here's the code, I commented where the function that isn't running is
If the question is too vague ask me for details, I don't know how to explain this more simple than it already is
var Car=function(x,y) {
this.x=x;
this.y=y;
};
Car.prototype.draw=function() {
var carHtml='<img src="http://nostarch.com/images/car.png">';
this.carElement=$(carHtml);
this.carElement.css({
position:"absolute",
left:this.x,
top:this.y,
});
$("body").append(this.carElement);
};
Car.prototype.moveRight=function() { // Function that isn't working
this.x+=5;
this.carElement.css({
left:this.x,
top:this.y
});
};
var tesla=new Car(20,20);
var nissan=new Car(100,200);
tesla.draw();
nissan.draw();
var ID=setInterval(nissan.moveRight(),1500);
The issue seems to be with this line
var ID=setInterval(nissan.moveRight(),1500);
The first argument of setInterval is a function or a callback function. So you either need to pass only nissan.moveRight or put it inside a function
var ID=setInterval(function(){nissan.moveRight()},2500);
JSFIDDLE
I need to call a function every 100ms, which is easy enough, but what if I need that function to accept a parameter?
The problem is that I create an object, and periodically need to update it. I have tried setting the object reference to a global, that didn't work. I tried setting it to a function variable, still no luck. Apparently I need to pass in the object, which I cant't figure out how to do using setInterval. There has to be a trick to this?
The code below works on forst call, but after that it fails at:
setCounterText.segment.DisplayText("AAABBB");
And complains that setCounterText.segment.DisplayText() is not a function...
Thanks...
window.onload = function ()
{
setInterval(setCounterText, 1000);
}
function setCounterText()
{
//"use strict";
var num;
if(!setCounterText.isInit)
{
num = 0;
setCounterText.isInit=true;
var canvas = document.getElementById('c');
var container = document.getElementById('container');
canvas.width = container.clientWidth;
canvas.height = container.clientHeight;
// Create a new sixteen segment display
setCounterText.segment = new SixteenSegment(1, canvas);
update(setCounterText.segment);
setCounterText.segment.DispayText("T-000:00:00.0");
}
num++;
setCounterText.segment.DisplayText("AAABBB");
}
You can create another function to act as a clojure for the setCounterText function and pass that as a parameter to setInterval.
setInterval(function() {
setCounterText(anotherParameter);
}, 1000);
That will capture your parameter and call the setCounterText function whenever the interval triggers.
Regarding the error you are getting, it's impossible to say without knowing the code in the SixteenSegment function but it should have a property set on it called DisplayText.
I make a simple quiz game. Here is some relevan methods that i have inside one object.
But doesn't work. I always get an error within 'rightAnswerGot' function. Console drops
"uncaught typeerror undefined is not a function for object methods" for this.addVariantsHtml(this.updateCharacter());
BasicGame.Game.prototype = {
actionOnClick: function (button) {
var log;
if(button.value==this.char_bubble.text) {
setTimeout(this.rightAnswerGot,1000);
} else {
// wrong
swoshsound.play();
}
console.log(log);
},
rightAnswerGot: function (){
this.addVariantsHtml(this.updateCharacter());
},
addVariantsHtml: function(id) {
this.answer = this.getAnswersVariants(id);
for (var i = 0; i < 6; i++) {
this.button[i].value = this.answer[i]['trans'];
this.button[i].char_id = this.answer[i]['id'];
this.ans_text[i].setText(this.answer[i]['trans']);
}
},
updateCharacter: function() {
var i = this.getRandomCharacter();
console.log("updateCharacter: "+i + " " +this.chars[i]);
this.char_bubble.setText(this.chars[i].getPath());
return i;
}
}
The aim is to froze the game for a second, when user choose the right answer, and than go to next question. Any ideas why does it happens?
Thanks
Looks like a classic JavaScript scope issue to me. However as you've tagged this question as using Phaser, I would suggest you use a Phaser Timer event to avoid scope problems. Specifically:
setTimeout(this.rightAnswerGot,1000);
replace it with:
this.game.time.events.add(Phaser.Timer.SECOND, this.rightAnswerGot, this);
Which will create a single 1 second timer that fires only once, calling your function at the end of it. You can use 1000 instead of Phaser.Timer.SECOND of course.
I would image that whats happening is that its trying to call the this.addVariantsHtml method, before its calling this.updateCharacter and getting the ID.
So your probably expecting that when it runs, for it to be something like:
this.addVariantsHtml(1);
But its actually trying to run
this.addVariantsHtml(this.updateCharacter());
So just do this:
var id = this.updateCharacter();
this.addVariantsHtml(id);
Either that or you need to look into method chaining/piping, which is just complicated and doesnt need to be used for this situation, but is interesting :)
Ok I found something that made it work!!
Here is a solution:
actionOnClick: function (button) {
var log;
if(button.value==this.char_bubble.text) {
var context=this;
setTimeout(function() {
context.addVariantsHtml(context.updateCharacter());
},1000);
} else {
// wrong
swoshsound.play();
}
console.log(log);
},
I'm very new on my quest for learning JavaScript(only two weeks) so be nice and surprised how far I got.
What I’m trying to do is hit a button and the button will evoke a random image or div to come to the front. I as you see I use the z-index by moving elements from back to front.
I have got far enough to create an alert that tells me it does find the random function just cant get it to activate this function (the changeCombined functions do work fine when I assign it to a button but just can’t get the getImage to run).
I’m unsure if it is possible, and I know there might be a hundred better ways to do this but one step at a time.
function changeZIndex(i,id) {
document.getElementById(id).style.zIndex=i;
};
var changeCombined1 = function() {
changeZIndex(-5,"scene1");
changeZIndex(5,"scene2");
};
var changeCombined2 = function() {
changeZIndex(-5,"scene2");
changeZIndex(5,"scene1");
};
function get_random(){
var ranNum= Math.floor(Math.random()*2);
return ranNum;
}
function getImage(){
var whichImage=get_random();
var image=new Array()
image[0]=changeCombined2;
image[1]=changeCombined1;
alert(quote[whichImage]);
}
Try this:
function changeZIndex(i,id) {
document.getElementById(id).style.zIndex=i;
};
function getImage(){
var whichImage=Math.floor(Math.random()*2);
var image=new Array()
image[0]=function() {
changeZIndex(-5,"scene2");
changeZIndex(5,"scene1");
};
image[1]=function() {
changeZIndex(-5,"scene1");
changeZIndex(5,"scene2");
};
image[whichimage]();
alert(quote[whichImage]);
}
To invoke a function you should use either apply or call methods.
Have you tried image[whichImage].apply(undefined) instead of your alert ?
You are not calling the changeCombined() functions at all.
If you are trying to call the functions, you have to use ()
image[0]=changeCombined2();
image[1]=changeCombined1();
What you have just the functions themselves to image[0] and image[1].
So after
x = changeCombined2;
x will hold a reference to the changeCombined2 function itself. So now if you say x() (or in your case image[0]()), it will call changeCombined2.
() will call the functions and will put the return value of the function into the array elements.
Note: since the functions do not explicitly return anything, image[0] and image[1] will hold undefined.
Thanks for all the help to get past my road block, the rookie mistake of not calling my funcions was the biggest issue. I was able montage the comments to create this version that works as expected.
function changeZIndex(i,id) {
document.getElementById(id).style.zIndex=i;};
function getImage(){
var whichImage=Math.floor(Math.random()*2);
var image=new Array()
image[0]=function() {
changeZIndex(-5,"scene2");
changeZIndex(5,"scene1");
};
image[1]=function() {
changeZIndex(-5,"scene1");
changeZIndex(5,"scene2");
};
image[whichImage].apply(undefined);};