var cnt1 = 0;
function initOctoView(){
var newcnt1 = printAdsBox1(cnt1, imgPerBox1); // first time on first load
var totalBoxes8 = setInterval(function() {
newcnt1 = printAdsBox1(newcnt1, imgPerBox1); // all 5 sec
}, 5000);
}
This function get called by this:
if($('.octoView').length > 0){
initOctoView();
}
And works fine so far.
Later on I have:
$(document).on('click', 'a.windowXL', function () {
window.clearInterval(totalBoxes8);
}
But this returns that totalBoxes8 is not defined.
What is my mistake? Please advice!
You declare totalBoxes8 with var inside function - totalBoxes8 is local variable accesable in this function only. You may make it global:
var cnt1 = 0;
var totalBoxes8;
function initOctoView(){
var newcnt1 = printAdsBox1(cnt1, imgPerBox1); // first time on first load
totalBoxes8 = setInterval(function() {
newcnt1 = printAdsBox1(newcnt1, imgPerBox1); // all 5 sec
}, 5000);
}
Try this;
$(function(){
var cnt1 = 0, totalBoxes8 ;
function initOctoView(){
var newcnt1 = printAdsBox1(cnt1, imgPerBox1); // first time on first load
totalBoxes8 = setInterval(function() {
newcnt1 = printAdsBox1(newcnt1, imgPerBox1); // all 5 sec
}, 5000);
}
$(document).on('click', 'a.windowXL', function () {
window.clearInterval(totalBoxes8);
}
});
totalBoxes8 is undefined because it is declared locally within the scope of the function initCotoView(), and is thus unavailable to the global scope
you can declare a global from within the function by explicitly attaching it to the global window object. Something like:
function foo() {
window.myVar = 1; // declares a global
}
foo(); // call the function to actually make the declaration
console.log(window.myVar); // the variable is accessible globally
Related
I want to be able to increment/change the value of a parameter inside an object. I want the value to change by accessing the value of a variable that is incrementing inside another function.
The example code below shows what I am trying to do. I would like options.number to increase as i inside masterLoop increases.
I know that i isn't defined in the scope of function calc(), but I can't think of a way to retrieve the value of i while maintaining this general code structure.
(function masterLoop(i) {
setTimeout(function() {
++i;
masterLoopStage = i;
console.log('Stage is: ' + i);
masterLoop(i);
}, 5000)
})(1);
function calc() {
number = i; // I know i isn't defined in this scope, but I can't figure out how access the incrementing value of i inside this function
return number;
}
var options = {
number: calc() // I want this vale to increase along with i inside masterLoop()
};
setInterval(function() {
console.log(options.number);
}, 5000);
Typically, in cases like this, I would try to use a return to retrieve a value, but I wasn't able to find a solution with that either since the incrementing value is inside a setInterval and thus its scope isn't available to the return.
Here is an example of that:
function calc() {
var foo = 1;
setInterval(function() {
var foo = foo + 1;
}, 1000);
return foo; // the incrementing value of foo is not available outside the scope of setIterval, so this won't work. The return also won't work inside setInterval.
}
var optionsConstant = {
maxVolume: 10
};
var options = {
maxVolume: optionsConstant.maxVolume + calc() // I want calc() to be able to increment along with foo in the setInterval above.
};
setInterval(function() {
var maxVolume = options.maxVolume;
console.log('maxVolume: ' + maxVolume);
}, 5000);
Taking your second attempt, you could make calc an immediately invoked function expression -- providing a closure -- and in it return a function that has access to foo.
Then, to keep the final syntax of options.maxVolume, you should define that property as a getter, so that in fact it will execute some code when accessed, calling calc():
var calc = (function () { // create closure for foo
var foo = 1;
setInterval(function() {
foo = foo + 1; // remove var!
}, 100);
return function calc() { // return a function
return foo;
}
})();
var optionsConstant = {
maxVolume: 10
};
var options = {
get maxVolume() { // make it a getter
return optionsConstant.maxVolume + calc();
}
};
setInterval(function() {
var maxVolume = options.maxVolume;
console.log('maxVolume: ' + maxVolume);
}, 500);
Can you declare the increment variable outside the masterloop function scope so the other functions can access it and read its' value when needed?
You'll need to make sure to re-initialize it's value when appropriate.
I think you need to use a closure. Here's one example:
let returnI = (function masterLoop(i) {
setTimeout(function() {
++i;
masterLoopStage = i;
console.log('Stage is: ' + i);
return masterLoop(i);
}, 5000)
})(1);
function calc() {
number = returnI;
return number;
}
var options = {
number: calc()
};
setInterval(function() {
console.log(options.number);
}, 5000);
As below code, I make an object named "test", and give it properties and method.
The property came from its argument.
And I try to call the method every 2 sec after onload, and the result shows undefined.
But if I only call the method not using setInterval(), like this
window.onload = function() {
giveword.showWord();
}
I'll be able to show the text "Hi".. Why is that?
var giveword = new test("Hi");
function test(word) {
this.word = word;
}
test.prototype.showWord = function() {
document.getElementById("msg_box").innerHTML = this.word;
}
window.onload = function() {
setInterval(giveword.showWord, 2000);
}
Thanks for help...
The reason is because in your test.prototype.showWord function your this object is referring to the context in which the function is called, which is the window object when called from setInterval.
I think what you want to do is use a closure to make the context of showWord() be the giveword instance like this:
var giveword = new test("Hi");
function test(word) {
this.word = word;
}
test.prototype.showWord = function() {
document.getElementById("msg_box").innerHTML = this.word;
}
window.onload = function(){
setInterval(function(){giveword.showWord();}, 2000); // <<-- here's the closure
}
The difference is that with the closure you're telling the setInterval function to call a function within the context as it was when the setInterval was declared. When setInterval was declared there was a variable in scope called giveword that had a method showWord() that returns the value of your initial input. (Closures are hard to explain, and I'm afraid you'd be best served by someone else explaining them if you need more info.)
This solution this now so easy, use an arrow function in setInterval. Here is an example using setInterval inside of an object method.
const mobile = {
make: 'iPhone',
model: 'X',
battery: 10,
charging: false,
charge: function() {
if(this.battery < 100) {
this.charging = true;
console.info('Battery is charging...');
let interval = setInterval(() => {
this.battery = this.battery + 10;
console.info(mobile.battery);
if( this.battery === 100){
this.charging = false;
clearInterval(interval);
console.info('Battery has finished charging.');
}
}, 100);
}
else {
console.info('Battery does not need charging.');
}
}
}
How do I call the inner function from outside in the following code ?
(function (){
var funOne = {
funTwo : function (){
var funFour = function(){
console.log('inner function working');
}
},
funThree : function () {
console.log('working');
}
}
funOne.funTwo(); // works
funOne.funThree(); // works again
funOne.funTwo.funFour(); // throwing exception
})();
You have a scoping issue with funFour compounded by trying to define funTwo act as a function (funOne.funTwo()) and an object (funOne.funTwo.funFour()).
Here are 2 options to get access to funFour:
Let funTwo make funFour accessible at the more accessible level (for example, via funOne).
Have funTwo return funFour within an object. You still have to add the parenthesis to actually call funTwo() in your output.
How to change funTwo:
funTwo : function (){
var funFour = function(){
console.log('inner function working');
};
funOne.funFour = funFour; // Option 1
return { 'funFour': funFour }; // Option 2
},
How to call each option:
funOne.funFour(); // Option 1
funOne.funTwo().funFour(); // Option 2
There is no way to access Local variable (var funFour) of function funTwo from outside. If you want to use funFour at outside of function funTwo, you need to declare funFour as Global variable.
Edited code is here.
(function (){
var funFour;
var funOne = {
funTwo : function (){
funFour = function(){
console.log('inner function working');
}
},
funThree : function () {
console.log('working');
}
}
funOne.funTwo(); // works
funOne.funThree(); // works again
funFour(); // Call function funFour here
})();
I can't figure out why when I call the reset method of the object, the timer is still null. I simplified version of my object is below, followed by the jQuery that constructs a new object and runs the code. See UPPERCASE comments for my specific question points. Thanks!
var countdownTimer = {
// Default vars
milliseconds: 120000,
interval: 1000,
timer: false,
/* ... stuff ... */
countdown: function () {
var root = this;
var originalTime = root.milliseconds;
/* ... stuff */
// IN MY MIND THIS NEXT LINE SETS THE INSTANCE OF THIS OBJECT'S TIMER PROPERTY TO THE setIterval's ID. BUT DOESN'T SEEM TO BE CORRECT. WHY?
root.timer = setInterval(function () {
if (root.milliseconds < 1) {
clearInterval(root.timer); // THIS LINE SEEMS TO WORK
root.countdownComplete(); // callback function
return false;
}
root.milliseconds = root.milliseconds - root.interval;
/* .... stuff ... */
}, root.interval);
},
start: function (ms) {
if (ms) {
this.milliseconds = ms;
}
if(this.timer) {
clearInterval(this.timer); // NOT SURE IF THIS WORKS OR NOT
}
this.countdown();
},
reset: function (ms) {
var root = this;
if(root.timer) {
clearInterval(root.timer); // THIS DOES NOT WORK
} else {
console.log('timer not exist!!!!'); // ALWAYS END UP HERE. WHY?
}
/* .... stuff ... */
},
countdownComplete: function() { }
};
// Setting up click events to create instances of the countdownTimer
$(function () {
var thisPageCountdown = 4000;
$('[data-countdown]').on('click', '[data-countdown-start], [data-countdown-reset]', function () {
var $this = $(this);
var $wrap = $this.closest('[data-countdown]');
// create instance of countdownTimer
var myCountdown = Object.create(countdownTimer);
if ($this.is('[data-countdown-start]')) {
$this.hide();
$('[data-countdown-reset]', $wrap).css('display', 'block');
myCountdown.$wrap = $wrap;
myCountdown.start(thisPageCountdown);
// myCountdown.countdownComplete = function() {
// alert("Updated Callback!");
// };
}
if ($this.is('[data-countdown-reset')) {
$this.hide();
$('[data-countdown-start]', $wrap).css('display', 'block');
// RESET CALLED HERE BUT DOESN'T WORK RIGHT. SAYS myCountdown.timer IS STILL null. WHY?
myCountdown.reset(thisPageCountdown);
}
});
});
When you use var myCountdown = Object.create(countdownTimer); inside of your click function callback you are scoping it only to that callback and once the callback has executed it is garbage collected. You need to only create one instance of the countdownTimer, and it should be outside of your click event handler.
var thisPageCountdown = 4000;
// create instance of countdownTimer
var myCountdown = Object.create(countdownTimer);
$('[data-countdown]').on('click', '[data-countdown-start], [data-countdown-reset]', function () {
var $this = $(this);
var $wrap = $this.closest('[data-countdown]');
TL;DR You can fix your issue by avoiding use of the keyword this in static methods.
When you use the keyword this in a static javascript method, it refers to the item before the last dot from the call point. Example:
foo.bar(); // inside, this will refer to foo
foo.bar.foobar(); //inside, this will refer to foo.bar
var a = foo.bar.foobar();
a(); //this will refer to either null or window - oops
To prevent this behavior, you should always use the fully qualified name reference in static methods instead of relying on the this keyword.
Example from above:
reset: function (ms) {
//var root = this; // don't do this
if(countdownTimer.timer) {
clearInterval(countdownTimer.timer);
} else {
console.log('timer not exist!!!!');
}
/* .... stuff ... */
}
I have an input which when im clicking - i want to see alert with '1,2,3,4...' (each press)
<input type='button' value='press' onclick='Clicked();' />
<script>
var t
function Clicked()
{
t=func;
t();
}
function func()
{
var count=0;
return new function () // <=== new or not new ???
{
count++;
alert(count);
}
}
</script>
If im adding the 'new' in the return and click , it says : '1,1,1,1,...'
If im removing the 'new' it doesnt work...
My goal is to use this to get : '1,2,3,4...'
Can someone explain to me what happens ?
You need to use the returned function:
var t = func()
function Clicked() {
t();
}
function func() {
var count=0;
return function () {
count++;
alert(count);
}
}
Example
You have to put the count declaration out of the "func" function and into the global namespace. Like this:
var count=0;
function func() {
count++;
alert(count);
}
You're creating a new var count every time the clickevent fires.. You should place the var count = 0 outside the function as a global variable..
oh and btw, throw out the return stuff please this will work properly:
var count = 0;
function func()
{
count++;
alert(count);
}
And call this method like this: func();
You are getting 1,1,1,1 because you are redefining count every time you call func().
In your case you will need to either put the count variable in the global scope:
var t;
var count = 0;
or change the way you are doing things a little:
var t = 0;
function Clicked(){
t = func(t);
}
function func(count){
count++;
alert(count)
return count;
}
Personally I like the second one. You have less global variables, one less function declaration, and it is cleaner
var t
function Clicked()
{
t=func;
t();
}
var count=0;
function func()
{
return new function () // <=== new or not new ???
{
count++;
alert(count);
}
}