For whatever reason, I can't get this function repeat. Once it gets the setTimeout, it spits out the "uncaught referenceerror: getnumbers is not defined (where getnumbers is just the name of the variable.
$(document).ready(function(){
var getnumbers = {
countDigit: function(){
if (sessionStorage.counter=="NaN"){
sessionStorage.counter="0";
}
else {
sessionStorage.counter=Number(sessionStorage.counter)+1;
}
$("#result").text("counter: " +sessionStorage.counter);
setTimeout("getnumbers.countDigit()",3000);
},
_init: function(){
getnumbers.countDigit();
}
};
getnumbers._init();
})
Ironically, if I refresh the page the counter works, so I know it's just getting stuck on that one line. What could I be missing?
Thanks!
setTimeout with a string argument is just a global eval. When it tries to evaluate getnumbers.countDigit(), it is evaluated in the global scope, and no longer has access to getnumbers.
Solution: Don't pass in a string. Instead, try this:
setTimeout(getnumbers.countDigit, 3000);
Related
So, I want to run this script when button A is clicked. The script is stored in an Object as a string. When button A is clicked, I use eval, like: eval(Object[script]). This works fine, unless I have functions within the script, when I do, it breaks because they are not getting defined. Is there a way to get around this? I tried putting the function definition in a var and putting it at the top of the script. Now, if I simply copy my script to the console, it executes perfectly. Is there a way to execute a script as if it were typed into the console?
FYI: This is a simplification of my problem, I realize there are better ways to do what I describe here.
The best fix is to stop storing code as strings. Use functions instead.
buttonA.script = function() {
do whatever you were doing in your eval
};
// then, instead of `eval(buttonA['script'])`, say...
buttonA.script();
// or, if the name is in a variable...
var foo = 'script'; // for example
buttonA[foo]();
About the only time eval makes sense is when you have code that by its very nature has to be dynamically generated or interpreted. For the vast majority of cases, that is not true. I can only think of a case where it would be true, in fact: the textarea script testing thing mentioned in the comments.
For every other case...
obj = {
first: function() {
function test() { alert('hi'); }
test();
}
};
obj['first']();
// or simply
obj.first();
// and what's more...`test` doesn't escape and trample on stuff.
try { test(); }
catch (ex) { alert("" + ex); } says `test` is not defined
This works:
var oFunc = function (value) {
alert(value)
}
var obj = { code: "oFunc('hello')" }
eval(obj["code"]);
Or am I missing something?
Update
This also works
var obj = { code: "var oFunc = function (value) {alert(value)}; oFunc('hello')" }
eval(obj["code"]);
In your code alert(hi) should be alert("hi")
obj = {
first: 'function test() { alert("hi") } test();'
}
eval(obj["first"]);
DEMO.
$(document).ready(function () {
function EndSession() {
window.close();
};
setTimeout("EndSession()", 10000);
});
Shown above is the code in a child page opened using window.open().
The problem is after ten seconds when it tries to call EndSession, it throws an error
"Microsoft JScript runtime error: 'EndSession' is undefined"
What is going on here?
Maybe the problem of the old way "string" is that it was looking for the method in the global scope, while the method was defined inside the function used for jQuery ready.
We can explicitly pass the function we really want to, if we have a proper reference to it.
Let's try:
$(document).ready(function () {
var endSession = function() {
window.close();
};
setTimeout(endSession, 10000);
});
Although I haven't tried it, maybe even this will work:
$(document).ready(function () {
setTimeout(window.close, 10000);
});
I'm not sure if you need the jQuery ready at all too, unless you intentionally want to start counting time after the document is fully loaded (which I'd expect to be very quick for a pop-up that closes soon).
When the timeout event triggers, the code you specified is run in the global namespace.
Your code is "EndSession()", so the browser tries to find a global function with the name EndSession. There is no such function, because you defined EndSession() inside an anonymous function that you passed to $(document).ready().
So, defining EndSession as global will suffice.
function EndSession() {
window.close();
};
$(document).ready(function () {
setTimeout("EndSession()", 10000);
});
Also, functions that are not constructors should, by convention, start with lowercase letter ;)
that should be like this,
setTimeout(EndSession, 10000);
DEMO
I have this code:
$(document).ready(function(){
var callPage = function(){
$.post('/pageToCall.php');
};
setInterval('callPage()', 60000);
});
and it gives me the error ReferenceError: Can't find variable: callPage. Why?
Try setInterval(callPage, 60000);.
If you pass a string to setInterval, then this string is evaluated in global scope. The problem is that callPage is local to the ready callback, it is not global.
There is hardly ever a reason to pass a string to setInterval (setTimeout). Always pass a function (to avoid exactly this kind of errors).
I suspect it's because callPage is a variable scoped to the anonymous function you're creating in the document.ready event. If you move the callPage definition outside that, does it work?
function callPage()
{
$.post('/pageToCall.php');
};
$(document).ready(function()
{
setInterval('callPage()', 60000);
});
It happens because callPage's scope is the anonymous function
var ObjectLiteral = {
myName:function() {
}
}
I want to call the myName function immeditetly when the page is
loaded.
I am not sure hot to write a self calling function inside an
ObjectLiteral...
You can't assign a function while simultaneously calling it (since calling it means that its return value gets assigned instead). You have to do this in two steps.
var ObjectLiteral = {
myName:function() {
}
};
ObjectLiteral.myName();
Just because no one mentioned it:
var ObjectLiteral = {
myName: function() {
console.log('myName was called!');
return arguments.callee;
}()
}
Since arguments.callee is deprecated in ES5, we would need to give the method a name:
var ObjectLiteral = {
myName: function _myName() {
console.log('myName was called!');
return _myName;
}()
}
Done. The method would get called at pageload and would still be callable later on. The caveat of doing it that way is the this context value which is replaced with window or undefined (strict) on the self-executing method. But you could apply some magic to solve that aswell. For instance, invoking .call(ObjectLiteral) in es3 or .bind(ObjectLiteral) in es5.
var ObjectLiteral = {
myName: function _myName() {
console.log('myName was called!');
return _myName;
}.call(ObjectLiteral)
}
Looks like I was wrong (damn!). The idea ok, but the assignment to ObjectLiteral is not done on the first invocation of myName. Therefore, the above code will only run from the second call on, which of course makes it useless anyway. You would need to invoke another context, but that would be just overkill.
It still does work after all, but it screws up if you need to access this, otherwise its a fine solution I think.
For your first question:
The simplest possible answer is to add this line to your script:
window.onload = ObjectLiteral.myName();
A better answer is to include that line somewhere in a larger function assigned to window.onload:
window.onload = function () {
....
ObjectLiteral.myName();
}
An even better answer is to scope things properly in case window has been reassigned.
For the second question, what to you mean by self-calling? (EDIT: n/m, Quentin answered)
Taking into account you want to execute your code after page load, jQuery is very suitable for that:
$(function() {
// called then page loaded..
var ObjectLiteral = {
myName:function() {
}
};
ObjectLiteral.myName();
});
At the very beginning of the javascript file, I have:
var lbp = {};
lbp.defaults = {
minLength: 40
};
I can successfully alert it afterwards, with:
alert(lbp.defaults.minLength);
But as soon as I put it inside a function, when I alert, I get "Undefined". What gives, and how do I avoid this? Is it absolutely necessary to pass this variable into each function, for example, by doing:
function(lbp) { alert(lbp.defaults.minLength); }
I would have thought that defining it first, it would attain global scope and not be required to be passed in?
Thanks in advance for enlightening me :)
====================================
EDIT:
The problem seems like it might be my initialize function is itself defined within lbp. Is there any way to use this function var, and still use lbp vars inside it?
lbp.initialize = function() {
alert(lbp.defaults.minLength);
};
The full bit of code looks like this:
<script type="text/javascript">
var lbp = {
defaults: {
minLength: 40
}
};
lbp.initialize = function() {
alert(lbp.defaults.minLength);
};
window.onload = lbp.initialize;
</script>
Are you actually passing lbp as the argument? Otherwise the parameter with the same name will hide the global variable.
Use this.
var lbp = {
defaults: {
minLength: 40
}
};
lbp.initialize = function() {
alert(this.defaults.minLength);
};
window.onload = function() { lbp.initialize(); };
If you call initialize as a method of lbp, this will point to lbp. When you assign a function to an event handler, such as window.onload, you are essentially copying the body of that function to the object on which the event handler is defined. So,
window.onload = lbp.initialize
is the same as
window.onload = function() {
alert(this.defaults.minLength);
};
Now, this is pointing to window, which is obviously not what we want. By wrapping the call to lbp.initialize() in a function, we preserve the context of this within that function and we can make sure that it always points to lbp. Check out this for a more complete explanation.
This works for me from javascript console in Firefox:
javascript:var lbp={}; lbp.defaults={minLength: 40};function xx() { alert(lbp);alert(lbp.defaults);alert(lbp.defaults.minLength); }; xx();
Gives output [object Object], [object Object], 40.
So, it seems there might be some problem with some associated code, which is not shown?
In the original code where you are trying to use lbp in a function. You are passing lbp in as an argument. This would hide the lbp from the global scope with a local (to the function) variable of the same name (unless when calling the function you passed lbp in again).
//this is what you have and will not alert a thing other
//and will probably throw an error
function(lbp) { alert(lbp.defaults.minLength; }
//should just be this with no argument. this will allow
//the function to see lbp in the global scope.
function() { alert(lbp.defaults.minLength; }
by passing lbp as a parameter in the first function it is not seen inside the function as the global object, but the local argument.