Function to modify a variable not working - Javascript - javascript

My issue concern 3 variables :
var modifyForce = 2;
var forceBase = 15;
var Force = (forceBase + modifyForce);
It display 17 Force
The first function which is working is :
{
Force++;
document.getElementById("Force").innerHTML = Force;
}
It adds +1 to Force each time I call it
But the second function :
{
forceBase++;
document.getElementById("Force").innerHTML = Force;
}
Does not add +1 to Force. Since it should add +1 to forceBase and Force = forceBase + modifyForce then it should add 1 to Force... I think.
My goal is to have a "forceBase" statistic + a "modifyForce" in order to get a total of "Force"
I am probably missing something simple but I can't find what. :/
Thank you :)

The problem is you're not updating Force to be equal to the new forceBase + modifyForce. Beyond declaration, Force doesn't keep any connection to forceBase or modifyForce, and you have to manually assign the new value to it. You should change your code as such:
{
forceBase++;
Force = forceBase + modifyForce;
document.getElementById("Force").innerHTML = Force;
}
Keep in mind that if Force is changed in another function (such as the first one you posted), this will reset those changes.

No one seems to have suggested this yet...
If you want Force to always be forceBase + modifyForce then make it a function.
function Force(){
return forceBase + modifyForce
}
Which now makes this work (note Force is now called with ():
{
forceBase++;
document.getElementById("Force").innerHTML = Force();
}

var modifyForce = 2;
var forceBase = 15;
var Force = (forceBase + modifyForce);
Force is one time calculated with forceBase + modifyForce
After the declaration you just have the number saved in Force
If you would like to use Force as a function to add modifyForce to forceBase use something like
var Force = function () {
return forceBase + modifyForce;
}
but you can't increment it like Force++ :P

The code-block where you edit forceBase does not re-calculate the updated value of Force.
To make this simple I recommend you move the re-calcultation and output into a distinct function like this:
var modifyForce = 2;
var forceBase = 15;
function updateForce() {
var Force = (forceBase + modifyForce);
document.getElementById("Force").innerHTML = Force;
}
// Output the current value of Force
updateForce(); // output is 17
forceBase++;
updateForce(); // output is 18
modifyForce++;
updateForce(); // output is 19

The best thing might be to create a class:
var objForce = {
modifyForce: 2,
forceBase: 15,
Force: 17,
reCalculate: function() {
this.Force = this.modifyForce + this.forceBase;
}
};
objForce.forceBase++;
objForce.reCalculate();
document.getElementById("Force").innerHTML = objForce.Force;

Related

The output from SetTimeout function is inconsistent

I am trying to create something like a Grid-Image-Box-Slider. Now what I am trying to achieve is that after a period of time (e.g 5 seconds) one of the images will be changed randomly. So, my script follows:
var currentImages = [1, 2];
(function imgCarousel() {
var min = 1;
var max = 6;
currentImgSlot = pickImageSlot();
var pickedImage = pickImage();
setTimeout(function () {
console.log("Image Slot: " + currentImgSlot + "<br> Image: " + pickedImage);
//var bgImgElem = document.getElementsByClassName('bg1');
var sheet = new CSSStyleSheet();
sheet.replaceSync('.bg' + currentImgSlot + ' {background-image: url("assets/img/' + pickedImage + '.jpg") !important}');
document.adoptedStyleSheets = [sheet];
return imgCarousel();
}, 5000)
})()
function pickImageSlot() {
var min = 1;
var max = 2;
var generatedImgSlot = generateRandomNumber(max, min);
if (generatedImgSlot == currentImgSlot) {
return pickImageSlot();
}
return generatedImgSlot;
}
function pickImage() {
var min = 1;
var max = 6;
var generatedImg = generateRandomNumber(max, min);
if (currentImages[currentImgSlot] == generatedImg) {
return pickImage();
}
currentImages[currentImgSlot] = generatedImg;
return generatedImg;
}
function generateRandomNumber(max, min) {
return Math.round(Math.random() * (max - min) + min)
}
So, here you can see that inside the imgCarousel() function I am using the setTimeout to change the background-image randomly after 5 seconds and then calling the same function again recursively. So, according to this code after each five seconds only one image should be changed. But, in reality, sometimes both of the images get changed at the same time. I don't know what is causing this issue.
Any help would be much appreciated. For your convenience I am sharing my code repo here:
Git Repo
Live Demo
It's a bit difficult to notice, but if you pay attention, in your live demo you'll actually see that each time they both change, one returns to the default. This is because you're actually just overriding the adoptedStyleSheets property with a new array consisting only of the latest override, so your other image will simultaneously return to the primary style sheet's image (the default).
There is no problem with the setTimeout, the issue is just that you need to be able to support both images being different from the default, instead of exactly one. You already keep both images in currentImages, so each time the timeout runs you can iterate over them and set each one's image in the new adopted style sheet.
Naively, something like this might work:
setTimeout(function () {
console.log("Image Slot: " + currentImgSlot + "<br> Image: " + pickedImage);
//var bgImgElem = document.getElementsByClassName('bg1');
var sheet = new CSSStyleSheet();
for(var i = 1; i < 2; i++) {
sheet.replaceSync('.bg' + i + ' {background-image: url("assets/img/' + currentImages[i]+ '.jpg") !important}');
}
document.adoptedStyleSheets = [sheet];
return imgCarousel();
}, 5000)
Your currentImages seems to be used with a random number between 1 and 2, but arrays are 0-based, so I'm not sure what your intended usage is there, but this should get you on the right track.

do something when function executes Jquery

So I have a function that is recursive for inverting colors. Here is the code:
function invert(id,what){
var color = $(id).css(what);
var matchColors = /rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/;
var match = matchColors.exec(color);
var r = (255 - match[1]).toString() + ",";
var g = (255 - match[2]).toString() + ",";
var b = (255 - match[3]).toString();
answer = 'rgb(' + r + g + b + ')' ;
$(id).css(what,answer);
};
So essentially I have a function that can be called in many instances (clicks of specific ids, hover on specific classes, etc.) and I do not know them all. But I need to know every single time this function gets called. How can I have an outside line of code that sets a variable equal to the amount of times the function has been called?
Wrap your function.
var wrapped = (function wrapper(present) {
function wrapping() {
++wrapping.count; // increment invocation count
return present.apply(this, arguments);
}
wrapping.count = 0; // counter, avaliable from outside too
return wrapping;
}(invert));
If you need to call it invert too, re-assign invert after.
invert = wrapped;
invert.count; // 0
invert();
invert.count; // 1
invert();
invert.count; // 2
I am not sure what your exact scenario is, but maybe you could override the function with a wrapper:
var invertOriginal = invert;
var counter = 0;
var invert = function(id, what, max) {
invertOriginal(id, what, max);
// do counter stuff here, e.g.
counter++;
};

jQuery - setInterval issue

I am using jQuery to generate and add a random amount of Clouds to the Header of the page and move them left on the specified interval. Everything is working fine, execpt the interval only runs once for each Cloud and not again. Here is my code:
if(enableClouds) {
var cloudCount = Math.floor(Math.random() * 11); // Random Number between 1 & 10
for(cnt = 0; cnt < cloudCount; cnt++) {
var cloudNumber = Math.floor(Math.random() * 4);
var headerHeight = $('header').height() / 2;
var cloudLeft = Math.floor(Math.random() * docWidth);
var cloudTop = 0;
var thisHeight = 0;
var cloudType = "one";
if(cloudNumber == 2) {
cloudType = "two";
}else if(cloudNumber == 3) {
cloudType = "three";
}
$('header').append('<div id="cloud' + cnt + '" class="cloud ' + cloudType + '"></div>');
thisHeight = $('#cloud' + cnt).height();
headerHeight -= thisHeight;
cloudTop = Math.floor(Math.random() * headerHeight);
$('#cloud' + cnt).css({
'left' : cloudLeft,
'top' : cloudTop
});
setInterval(moveCloud(cnt), 100);
}
function moveCloud(cloud) {
var thisLeft = $('#cloud' + cloud).css('left');
alert(thisLeft);
}
}
Any help is appreciated!
This is the way to go:
setInterval((function(i){
return function(){
moveCloud(i);
};
})(cnt), 100);
Engineer gave you the code you need. Here's what's happening.
The setInterval function takes a Function object and an interval. A Function object is simply an object that you can call, like so:
/* Create it */
var func = function() { /* ... blah ... */};
/* Call it */
var returnVal = func(parameters)
The object here is func. If you call it, what you get back is the return value.
So, in your code:
setInterval(moveCloud(cnt), 100);
you're feeding setInterval the return value of the call moveCloud(cnt), instead of the the function object moveCloud. So that bit is broken.
An incorrect implementation would be:
for(cnt = 0; cnt < cloudCount; cnt++) {
/* ... other stuff ... */
var interval = setInterval(function() {
moveCloud(cnt);
}, 100);
}
Now, you're feeding it a function object, which is correct. When this function object is called, it's going to call moveCloud. The problem here is the cnt.
What you create here is a closure. You capture a reference to the variable cnt. When the function object that you passed to setInterval is called, it sees the reference to cnt and tries to resolve it. When it does this, it gets to the variable that you iterated over, looks at its value and discovers that it is equal to cloudCount. Problem is, does not map on to a Cloud that you created (you have clouds 0 to (cloudCount -1)), so at best, nothing happens, at worst, you get an error.
The right way to go is:
setInterval((function(i){
return function(){
moveCloud(i);
};
})(cnt), 100);
This uses an 'immediate function' that returns a function. You create a function:
function(i){
return function(){
moveCloud(i);
};
}
that returns another function (let's call it outer) which, when called with a value i, calls moveCloud with that value.
Then, we immediately call outer with our value cnt. What this gives us is a function which, when called, calls moveCloud with whatever the value of cnt is at this point in time. This is exactly what we want!
And that's why we do it that way.

How to hide/show multiple square at different time

I'm still struggling with my simple javascript game. Here is my previous question: Simple javascript game, hide / show random square
Some square show and hide randomely for a few seconds and you have to click on them. I use RaphaelJS to draw the square and a few of JQuery ($.each() function)
I can't make the hide/show with the setInterval working for each square. The function made by Mishelle looks good but I get a "This is not a function" error.. I've test different stuff but it's not as obvious as I thought :/
window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
// random function to for the x and y axis of the square
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var rectanglemain = paper.rect(0, 0, 500, 500).attr({fill: "white",});
var win_click = 0; // set the var to count the click on the square
var recs = [];
for(var i = 0; i < 50; i++) {
var x = random(1,450);
var y = random(1,450);
var rec = paper.rect(x, y, 50, 50).attr({fill: 'blue'});
recs.push(rec); // add the square in an array
recs[i].click(function () {
//counting the clicks
win_click = win_click + 1;
})
function hideSquare() {recs[i].hide();}
hideSquare();
}
rectanglemain.click(function () {
alert('you click on ' + win_click + ' squares');
});
/* here is a function made by Mishelle on my previous question, unfortunately I can't make it work (this is not a function error).
function showBriefly (timeFromNow, duration) {
window.setTimeout(this.rec.show, timeFromNow);
window.setTimeout(this.rec.hide, timeFromNow + duration);
}
recs[2].showBriefly(1000, 3000); to test the function
*/
}
Thanks for the help :)
try
window.setTimeout(function(){this.rec.show();}, timeFromNow )
Just came across your problem, just in case you read this and you want to know what was the problem. this is undefined within the callback, thus you need to store which rectangle you were referring to in a variable (I've called it square), see my code:
showBriefly: function(timeFromNow, duration) {
square = this.box;
setTimeout(function(){square.show();}, timeFromNow )
setTimeout(function(){square.hide();}, timeFromNow + duration )
}
Cheers

Incrementing a number smoothly with a variable time period in JS

I have a really simple JS counter which I display on a dashboard like screen which does the following:
Every 5 minutes it makes an jsonp call and retrieves a "total" number
It then displays this number to the screen by incrementing the last total displayed till it is equal to the new total. (the number can only ever increase)
I'm having some trouble with making the number increment smoothly. What I would like to do is find a delta (i.e. New total - old total) and increment the number gradually over the 5 minutes till the next call so it looks like a nice smooth transition.
Any ideas on how I can do this?
Currently some of my code looks like this (This block get's called every 5mins. And yes, it's in dire need of a refactor...)
var LAST_NUMBER_OF_SESSIONS = null;
var five_minutes_in_seconds = 300;
var new_number_of_sessions;
$.getJSON('http://blah.com/live_stats/default_jsonp.aspx?callback=?', function(data) {
if(LAST_NUMBER_OF_SESSIONS === null){
LAST_NUMBER_OF_SESSIONS = data.total_sessions;
}
new_number_of_sessions = data.total_sessions;
var delta = Math.floor(new_number_of_sessions - LAST_NUMBER_OF_SESSIONS);
var time_interval = (five_minutes_in_seconds / delta) * 1000;
var old_value = LAST_NUMBER_OF_SESSIONS;
var new_value = null;
sessions_interval = setInterval(function (){
new_value = parseInt(old_value, 10) + 1;
$('#stats').text(new_value);
old_value = new_value;
if(new_value >= new_number_of_sessions){
clearInterval(sessions_interval);
}
}, time_interval);
LAST_NUMBER_OF_SESSIONS = new_value;
});
}
This code it seems to increment the number very quickly at the start of the 5min period and then stop so it's not exactly right...
Try this:
var total = 0,
delta = 0,
stats = $('#stats').text( total );
function increment() {
var v = +stats.text();
if ( v < total ) {
stats.text( v + 1 );
} else {
$.getJSON('http://...', function(data) { // added data here
delta = Math.floor( 300000 / ( data.total_sessions - total ) );
total = data.total_sessions;
});
}
setTimeout(increment, delta);
}
Update:
In order to test my code, I had to simulate the JSON reponse - I used an array of numbers. See here: http://jsfiddle.net/simevidas/MwQKM/
(In the demo, I use an interval of 5 seconds instead of 5 minutes.)
I am not exactly sure why your code doesn't work as expected, although I suspect that it has to do with line LAST_NUMBER_OF_SESSIONS = new_value;. I wrote something similar and it works fine. It's not that different from what you have, minus that last line of code.

Categories

Resources