javascript parsing - javascript

i have this block of code:
$(document).ready(function() {
//<![CDATA[
var who;
FB_RequireFeatures(["Api"], function(){
var who = api.get_session().uid;
alert(who);
});
alert("the uid is: "+who);
//]]>
});
the problem:
the code outside the FB_RequireFeatures block is executing before the one inside it.
due to which the value of who is coming out to be undefined.
what am i doing wrong?

The FB_RequireFeatures function appears to be making an asynchronous call, so you're not doing anything wrong, that's just the way it works - the alert is called before the request comes back.
You must design your code in a way that the code that depends on the result of the FB_RequireFeatures functions are called only after the request completes. You can call another function inside the callback, for example:
var who;
$(document).ready(function() {
FB_RequireFeatures(["Api"], function() {
who = api.get_session().uid;
doSomeOtherStuff();
});
});
function doSomeOtherStuff() {
alert("the uid is: " + who);
}
Now the doSomeOtherStuff function is called only after the FB_RequireFeatures function finishes, and you should do all following code inside the doSomeOtherStuff function – which you can name to be anything you want, obviously.
I moved the who variable out of the ready block to keep it in scope for the doSomeOtherStuff function, and removed the var from the inner function so that you're referencing the original variable instead of creating a new one, otherwise it's the same.

You're making a new local who variable. Remove the var from the place where you set who. Also, you can't reference who until the callback to the FB_RequireFeatures function is run.

Related

Differences when using functions for casper.evaluate

I'm using PhantomJS v2.0 and CasperJS 1.1.0-beta3. I want to query a specific part inside the page DOM.
Here the code that did not work:
function myfunc()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
}
var del=this.evaluate(myfunc());
this.echo("value: " + del);
And here the code that did work:
var del=this.evaluate(function()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
});
this.echo("value: " + del);
It seems to be the same, but it works different, I don't understand.
And here a code that did also work:
function myfunc()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
}
var del=this.evaluate(myfunc);
this.echo("value: " + del);
The difference here, I call the myfunc without the '()'.
Can anyone explain the reason?
The problem is this:
var text = this.evaluate(myfunc());
Functions in JavaScript are first class citizen. You can pass them into other functions. But that's not what you are doing here. You call the function and pass the result into evaluate, but the result is not a function.
Also casper.evaluate() is the page context, and only the page context has access to the document. When you call the function (with ()) essentially before executing casper.evaluate(), you erroneously try to access the document, when it is not possible.
The difference to casper.evaluate(function(){...}); is that the anonymous function is defined and passed into the evaluate() function.
There are cases where a function should be called instead of passed. For example when currying is done, but this is not applicable to casper.evaluate(), because it is sandboxed and the function that is finally run in casper.evaluate() cannot use variables from outside. It must be self contained. So the following code will also not work:
function myFunc2(a){
return function(){
// a is from outer scope so it will be inaccessible in `evaluate`
return a;
};
}
casper.echo(casper.evaluate(myFunc2("asd"))); // null
You should use
var text = this.evaluate(myfunc);
to pass a previously defined function to run in the page context.
It's also not a good idea to use reserved keywords like del as variable names.

Recognising variables while assigning a function to a variable in javascript

In my jQuery scripts, when the user closes a menu with an animation, I have to call a function after the closing animation is finished. I want to assign this function dynamically by calling a function openStrip() with a parameter. My code looks like:
var FUNCTION_JUST_AFTER_MENU_CLOSE = function(){};
function openStrip(stripId){
FUNCTION_JUST_AFTER_MENU_CLOSE = function(){
createStrip(stripId);
});
}
if I call openStrip("aStripId"), I expect FUNCTION_JUST_AFTER_MENU_CLOSE to be:
// #1
function(){
createStrip("aStripId");
}
whereas my current code gives:
//#2
function(){
createStrip(stripId);
}
i.e, the parameter passed to the function openStrip() is lost while assigning the function() to the variable FUNCTION_JUST_AFTER_MENU_CLOSE.
How can I avoid this.
EDIT: I discovered that my code is actually working. The problem was elsewhere. I got confused because when I looked at Chrome's debugger, it was showing me the function definition as is (#2 in above). But when it actually went down executing that function later in the code, it did evaluate the values of the passed argument, and endedup executing #1.
Thanks for the answer though. I am marking it correct because that is perhaps a better way of assigning the function.
The best way is to return a function, from openStrip like this
function openStrip(stripId) {
return function() {
createStrip(stripId);
};
}
For example,
function openStrip(stripId) {
return function() {
console.log(stripId);
};
}
openStrip("aStripId")();
# aStripId
openStrip("bStripId")();
# bStripId
You can even assign the function objects returned to different variables and use them later on
var aStrip = openStrip("aStripId");
aStrip();
# aStripId
aStrip();
# aStripId

Javascript Variable Not Changed Outside of Function Scope

I have the following function:
function loginStudent() {
var advisorKEY = "<dtml-var expr="py_get_alias()">";
var studentKEY = "<dtml-var SID>";
var URL = "py_logging_sessionOpen?AdvisorKEY=" + advisorKEY + "&StudentKEY=" + studentKEY;
key = "";
$j.get(URL, function(data) {
key = data;
});
alert(key);
}
The py_loggin_sessionOpen is just a python script running on my server.
It returns a single string. I need the response of that script to determine the next action. The script returns the value perfectly, and I can easily check the value by putting an alert within the function(data) in get.
My main question is: how to get the key value to be changed outside the scope of function(data)?
I assumed because I defined it externally it would act as a global variable.
Moving it outside loginStudent() does not solve the problem either.
Any ideas?
$j.get() is going to be an asynchronous call. That means it fires, and the rest of the execution continues. Anything that relies on that call needs to be done in the callback, like so:
$j.get(URL, function(data) {
key = data;
alert(key);
} );
If everything else is good, you'll see the value you expect.
The problem with your code is that $j.get executes asynchronously. That's the reason you pass a callback to it.
If you wish to write asynchronous code synchronously then you should read this answer: https://stackoverflow.com/a/14809354/783743
Edit: It seems that you have created a global variable called key by not declaring it with var. Hence it should be visible in other functions as long as they are called after the callback.
Would you care to provide us these other functions?

javascript: pass function as a parameter to another function, the code gets called in another order then i expect

i want to pass a function to another function as a parameter.
I want to do that because the latter function calls an async Jquery method and AFTER that gives a result back, i want some javascript code executed.
And because this function is called from multiple places, i want the code to execute (after the async Jquery code gets executed) to be passed in the function.
Makes sense? i hope :)
Now what is see is that the order in which the code is executed is noth what i want.
I've simplified the code to this code:
$('#AddThirdParty').click(function() {
var func = new function() {
alert('1');
alert('2');
alert('3');
}
alert('4');
LoadHtml(func);
alert('5');
});
function LoadHtml(funcToExecute) {
//load some async content
funcToExecute;
}
Now what i wanted to achieve (or at least what i thought would happen) was that alert4 would fire, then the loadhtml would fire alert1, alert2 and alert3, and then the code would return to alert5.
But what happens is this: alert1, alert2, alert3, alert4, alert5.
Does anyone know what i'm doing wrong and why this is the order in which the code is executed?
It looks like the alert1..alert3 gets executed when i define the new function(), but why doesn't it ALSO get executed when i call it from the LoadHtml function?
$('#AddThirdParty').click(function() {
var func = function() { // NOTE: no "new"
alert('1');
alert('2');
alert('3');
}
alert('4');
LoadHtml(func);
alert('5');
});
function LoadHtml(funcToExecute) {
//load some async content
funcToExecute(); // NOTE: parentheses
}
Two errors: the syntax for anonymous functions does not include the keyword new; and JavaScript requires parentheses for function calls, even if functions do not take any arguments. When you just say funcToExecute, that is just a variable giving its value in a context where nothing is using that value (kind of like writing 3; as a statement).
You might notice that you already know how to use anonymous functions: you did not write $('#AddThirdParty').click(new function() ...);
$('#AddThirdParty').click(function() {
var func = new function() {
alert('1');
alert('2');
alert('3');
}
alert('4');
LoadHtml(func);
alert('5');
});
function LoadHtml(funcToExecute) {
//load some async content
funcToExecute;
}
The new keyword creates an object from the function. This means the function (which is anonymous) gets called immediatly. This would be the same as
var foo = function() {
alert("1");
alert("2");
alert("3");
}
var func = new foo();
This means your creating a new object (not a function!) and inside the constructor your alert 1,2,3. Then you alert 4. Then you call LoadHtml which does nothing, then you alert 5.
As for
funcToExecute;
The funcToExecute is just a variable containing a function. It actually needs to be executed.

variable scoping in javascript

My code is as follows:
jQuery(document).ready(function() {
var pic = 0;
FB.init({appId: '1355701231239404', status: true, cookie: true, xfbml: true});
FB.getLoginStatus(function(response) {
if (response.session) {
pic = "http://graph.facebook.com/" + response.session.uid + "/picture";
alert(pic);
} else {
window.location = "index.php"
}
});
});
</script>
The issue is that the pic inside my if statement has a different scope with the one I declared above? Why and how do I make them the same?
What I want is to use this var pic (the one that has been assigned by the if statement) inside the body of my html. I will have another script inside the body, a document.write that uses this pic variable.. as of now when I do a document.write it always gives me 0, as if it's not assigned inside the if statement
The issue is that the pic inside my if statement has a different scope
No, it isn't. JavaScript scope is by function. var pic = 0; scopes pic to the anonymous function passed to ready(). The anonymous function passed to getLoginStatus() doesn't use var at all, so the scope of pic there is the same.
(Since you didn't say what outcome you got or what outcome you were expecting, it is hard to say what the solution to your problem actually is)
But there is only one pic in that snippet. So the issue you describe doesn't exist. What problem are you experiencing? How does the code misbehave compared with what you expect?
Update
Okay, your actual problem is that you're expecting pic to be updated so you can use the value of it elsewhere. But consider:
FB.getLoginStatus(function(response) { ... });
The reason that function executes a callback, instead of returning response as a return value, is because it is asynchronous. It make take a while to get the response, and so it doesn't execute the callback immediately. So your other piece of code is probably executing before that happens, i.e. before pic has been properly initialised with a value.

Categories