Loading localStorage is not updating my variables - javascript

I got these variables
var moneycount = 0;
var b1 = document.createElement("IMG");
function update() {
document.getElementById('money').innerHTML = moneycount;
}
And functions for saving/loading
function save() {
localStorage.setItem("moneycount", moneycount);
};
function load() {
moneycount = localStorage.getItem("moneycount");
moneycount = parseInt(moneycount);
update();
};
This function works as intended but wont update with localStorage
function add() {
moneycount = moneycount + 1
if (moneycount >= 1) {
document.getElementById('badge1').appendChild(b1);
}
update();
}
It seems like var moneycount = 0 still is 0 after I load localStorage because if (moneycount >= 1) is not working. The document element is still displaying a bigger number after loading localStorage. Any ideas on how I can store my add() function?
Edit:
Found a temporary solution with setting setInterval(save, 5000); and adding <body onload="load();"> and calling it on refresh.

that is because you do not update the localStorage instead you just update the html element: should do it as followed:
var moneycount = 0;
var b1 = document.createElement("IMG");
function update() {
document.getElementById('money').innerHTML = moneycount;
localStorage.setItem("moneycount", moneycount);
}
function save() {
localStorage.setItem("moneycount", moneycount);
};
function add() {
localStorage.getItem("moneycount")+= 1;
if (moneycount >= 1) {
document.getElementById('badge1').appendChild(b1);
}
update();
}

The reason is (like mentioned in the comments) that your load() function also saves the localStorage instead of retrieving the value.
Your load() function should look like this:
function load() {
moneycount = localStorage.getItem("moneycount");
update();
};

Related

javascript interval in Object

i've wrote a snippet which should start counting a number from 1 to 1000 or pre defined.
Because of needing the script mulitple times i thought it would be a great idea to write it as an object and use it mulitiple times. But i get an error:
Uncaught ReferenceError: root is not defined
(anonymous function)
What did i wrong?
var time = function() {
var root = this;
var i=0;
root.max = 1000;
root.elm = false;
root.runTime = function() {
if(root.elm != false) {
if (i < root.max) {
i++;
root.elm.text(i);
} else {
clearInterval(root.interval);
}
}
this.interval = setInterval('root.runtTime()', 5);
};
};
if($(document).ready(function() {
var countUp= new time();
countUp.max = 1526;
countUp.elm = $("#elm");
countUp.runTime();
});
This is because of the following line:
this.interval = setInterval('root.runtTime()', 5);
Because it's a string it has to be evaluated as a global object.
Change to the following to ensure the same scope:
this.interval = setInterval(root.runtTime, 5);
Also there's a typo (runtTime should be runTime), so change to the following:
this.interval = setInterval(root.runTime, 5);
Finally you're using setInterval which will repeatedly call root.runTime every 5ms. Change to setTimeout if you wish to call this recursively:
this.interval = setTimeout(root.runTime, 5);
Alternatively set up the interval outside of your runTime function:
root.runTime = function() {
if(root.elm != false) {
if (i < root.max) {
i++;
root.elm.text(i);
} else {
clearInterval(root.interval);
}
}
};
this.interval = setInterval(root.runTime, 5);
Also you don't need the if statement around document.ready. This is a callback function which is triggered when the DOM has loaded, and therefore doesn't require an if statement.
$(document).ready(function() {
var countUp= new time();
countUp.max = 1526;
countUp.elm = $("#elm");
countUp.runTime();
});

Running a function for each element

I am using the Peity js plugin to create donut charts on my page. I am trying to animate the chart for each of the .foo elements:
<span class="foo" data-value="10"></span>
$('.foo').each(function () {
var updateChart = $(this).peity('donut');
var text = "";
var i = 0;
function myLoop() {
setTimeout(function () {
text = i + "/12";
updateChart.text(text)
.change()
i = i + 0.2;
var maxValue = $(this).data("value");
if (i <= maxValue) myLoop();
}, 0.5)
}
myLoop();
});
However it won't work for some reason with no errors in console. If I remove the $('.foo').each(function () { ... } part (and all "this" instances) the code will work. Thanks in advance for any help.
The problem is the context inside the timer handler, the easiest fix here is to use a closure variable
$('.foo').each(function () {
var $this = $(this);
var updateChart = $this.peity('donut');
var text = "";
var i = 0;
function myLoop() {
setTimeout(function () {
text = i + "/12";
updateChart.text(text)
.change()
i = i + 0.2;
var maxValue = $this.data("value");
if (i <= maxValue) myLoop();
}, 0.5)
}
myLoop();
});
When the timeout callback is executed, the this context refer to window, because you are actually calling window.setTimeout method.
Try this:
$('.foo').each(function () {
var updateChart = $(this).peity('donut');
var text = "";
var i = 0;
function myLoop() {
setTimeout($.proxy(function () {
text = i + "/12";
updateChart.text(text)
.change()
i = i + 0.2;
var maxValue = $(this).data("value");
if (i <= maxValue) myLoop();
},this), 0.5)
}
myLoop();
});

Can't call a method by using 'this' [duplicate]

This question already has answers here:
JavaScript setInterval and `this` solution
(9 answers)
Closed 8 years ago.
I'm trying to call my method Move(); inside the object MySnake using setInterval:
function Snake()
{
this.Start = function(Speed)
{
this.Movement = setInterval(function(){
this.Move();
},Speed);
}
}
var MySnake = new Snake();
MySnake.Start(400); //Doesn't work
and this isn't working. But when I call the method through the instance 'MySnake':
function Snake()
{
MySnake.Start = function(Speed)
{
this.Movement = setInterval(function(){
MySnake.Move();
},Speed);
}
}
var MySnake = new Snake();
MySnake.Start(400); //Works
I wan't the one whit 'this' keyword to work
This is because this is defined by the caller in JavaScript. The easiest solution is to store it in another variable:
function Snake()
{
this.Start = function(Speed)
{
var that = this;
this.Movement = setInterval(function(){
that.Move();
},Speed);
}
}
var MySnake = new Snake();
MySnake.Start(400); //Work
Here is a working jsfiddle. In your example, the inner this is the global window.
Another solution would be to bind this in the function to the local this, as shown in this second jsfiddle:
function Snake()
{
this.Move = function() { document.body.innerHTML += '.'; };
this.Start = function(Speed)
{
this.Movement = setInterval((function(){
this.Move();
}).bind(this),Speed);
}
}
var MySnake = new Snake();
MySnake.Start(400); //Work
But this one is harder to read.
when you do this.move(); "this" is inside anonymous function passed into the setInterval method, hence you will get an error.
function Snake()
{
this.Start = function(Speed)
{
var _this = this;
this.Movement = setInterval(function(){
_this.Move();
},Speed);
}
}
var MySnake = new Snake();
MySnake.Start(400)
This will work since the reference to the object is captured by closure created by the callback for setInterval.

Clear interval from within a closure

I'm trying to clear an interval when the user hovers over an element and then start it up again when they hover off an element. I think this is a closure but I'm not sure, hopefully my code will make sense what I'm trying to do.
var rotatorInterval = function(elem){
var interval = setInterval(function(){
var active = elem.find('.dot.active');
if(active.is('.dot:last-of-type',elem)){
elem.find('.dot').first().click();
}else{
active.next().click();
}
},6000);
interval;
return interval;
};
if($('.rotator').length){
$('.rotator').each(function(){
var self = $(this);
rotatorInterval(self);
self.find('.slide, .dot').on('mouseenter',function(){
console.log('hovered');
clearInterval(interval);
});
});
}
I tried returning the interval from that closure but when I hovered it said interval (the name of the variable I returned) is not defined, so it's like it didn't return it or something.
You just have to actually return the interval reference somewhere
var rotatorInterval = function (elem) {
var interval = setInterval(function () {
var active = elem.find('.dot.active');
if (active.is('.dot:last-of-type', elem)) {
elem.find('.dot').first().click();
} else {
active.next().click();
}
}, 6000);
return interval;
};
if ($('.rotator').length) {
$('.rotator').each(function () {
var self = $(this);
var return_interval = rotatorInterval(self);
self.find('.slide, .dot').on('mouseenter', function () {
clearInterval(return_interval);
});
});
}

Javascript variable doesn't update outside of loop, inside OK

I hope I'm not missing something obvious here.
function renderViews(containerId) {
var root = '../Views/';
var viewsDomStr = '';
for (var i = 0; i < bundles.views.length; i++) {
$.get(root + bundles.views[i], function (data) {
viewsDomStr = viewsDomStr.concat(data);
});
}
console.log(viewsDomStr);
$('#' + containerId).append(viewsDomStr);
}
The problem is that the viewsDomStr is updated according to data from server only inside the for loop. For console.log(viewsDomStr); all I get is a reset to ''.
The function you are calling is asynchron.
Try with
function renderViews(containerId) {
var root = '../Views/';
var viewsDomStr = '';
function cb(){
console.log(viewsDomStr);
$('#' + containerId).append(viewsDomStr);
}
for (var i = 0; i < bundles.views.length; i++) {
$.get(root + bundles.views[i], function (data) {
viewsDomStr = viewsDomStr.concat(data);
cb();
});
}
}
The problem is the $.get request is asynchronous so the program continues on and doesn't wait for it. You want to use viewsDomStr inside the $.get function.
function renderViews(containerId) {
var root = '../Views/';
for (var i = 0; i < bundles.views.length; i++) {
$.get(root + bundles.views[i], function (data) {
console.log(data);
$('#' + containerId).append(data);
});
}
// This section runs before $.get is finished
}
EDIT: I've found that viewsDomStr is actually redundant. You are just adding text to the element so you can just add it to the $.get.
Since get method sends asynchronous request, you can check response every 1 sec using setInterval:
function renderViews(containerId) {
var root = '../Views/';
var viewsDomStr = '';
var success = false;
for (var i = 0; i < bundles.views.length; i++) {
$.get(root + bundles.views[i], function (data) {
viewsDomStr = viewsDomStr.concat(data);
success = true;
});
}
var t = setInterval(function(){
if(success) {
console.log(viewsDomStr);
$('#' + containerId).append(viewsDomStr);
clearInterval(t);
}
},1000);
}
The anonymous function of the get method will be asynchronous (as per the execution of get itself).
In short, it all happens too fast.

Categories