Facebook API Javascript: document.write() doesn't work? - facebook-graph-api

I started having a look into Facebook API today. I couldn' say enough how ugly and totally unintuitive it is, at least its Javascript implementation. Anyway, here's the two things I found:
a. I struggled whole day getting 'undefined' messages after properly loggin and getting an access_toekn, now when I tried to write response.first_name after calling FB.api ('/me') I got 'undefined' messages..... Well, I burnt my brain until I got someone here in stackoverflow that said the access token should HAVE to be passed in the call! But you can't find THIS CLEARLY specified in the FB official documentation, it's not even mentioned, not even parameter is shown. So this works:
FB.api('/me', {access_token: taccesstokenvalue}, function(response) {
alert(response.first_name); });
b. now, if I change alert() by document.write() , well, it just does nothing.
c. console.log() never worked out, I Tried on chrome, firefox, opera. Nothing
Why can't I use document.write? I need to verbosely write a lot of things coming out from the API, how can I do it ?
Thanks!!

Well, I found out a solution I think. Hope it helps other people...
I solved it this way:
a. create a form on top of the body area, with hidden field called hAPIresponse and hAccessToken
b. instead of trying to dump the API response right inside the function() as in the code above, fill the hidden fields with what the API returns, concatenating fields one after another if needed, like this:
FB.api('/me', {access_token: taccesstokenvalue}, function(response) {
document.getElementById("hAPIresponse").value="first name:" + response.first_name;
document.getElementById("hAccessToken").value="access token:" + taccesstokenvalue;
});
*here I didn't concatenate anything, just got the first_name property from the API
c. taccesstokenvalue variable comes from previously retrieving it from the URL or you can retrieve it directly through the API. Here comes the manual approach:
function Mid(str, start, len)
{
// Make sure start and len are within proper bounds
if (start < 0 || len < 0) return "";
var iEnd, iLen = String(str).length;
if (start + len > iLen)
iEnd = iLen;
else
iEnd = start + len;
return String(str).substring(start,iEnd);
}
var taccesstoken=window.location.href;
var tvecaux=taccesstoken.split('access_token=');
var taccesstokenvalue=Mid(tvecaux[1],0, tvecaux[1].indexOf('&',0) );
As far as I saw, when you get into the FB.api() call the code CONTINUES TO EXECUTE below the FB.API() call and not through the function(response). This one is triggered asynchronously by its own will, when it thinks it's better to finish :) It seems it's so complicated for FB developers adding a sync=true/false property in the FB.Init() so people used to sync coding won't pull their hairs out of their heads as I did..
Hope it helps somebody, I spent nearly 36 hours trying to do something so simple and stupid like calling an API and retrieving a value from it...
Again, this API couldn't be less intuitive, I can't say it enough. I can't imagine what I will find when trying to pull coments to FB Post replies or even trying to interact with the FB chat

Related

Fallback on geolocation

I'm having trouble with the most basic aspect of geolocation - no matter what I do, I don't seem to be able to get the fallback to trigger. Here's the code:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position){
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var latNum = parseFloat(latitude);
var longNum = parseFloat(longitude);
This is immediately followed by a nested bunch of if...else if statements that trigger different functions based on the user's location within one of a number of defined areas and an else statement to catch the condition where the user is not in any of the defined locations. This part all works fine, including the 'else' condition at the end. Where it falls over is if the user's device does not have geolocation enabled, or the user denies access to location data when prompted.
The code supposed to capture this is simply:
} else {
function10();
}
I have tried this in FF, Safari and Chrome with the same results: if I disable location services or deny access when prompted, the final 'else' function does not trigger.
I've looked at countless examples of this sort of elegant failure on geolocation and can't see why it doesn't work.
I'd be truly grateful for any clues where I went wrong.
OK - problem solved! I'm not sure if I feel just silly or enlightened, but for the benefit of anyone else with the same problem, here's the solution:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position){
// Do something here if you get position data
},
function() {
// Do something else if you don't get any position data
}
);
}
Where i went wrong, I think, is that I needed to look for a failure of the function(position)rather than the absence of a geolocation enabled agent. The second function within the same if condition provides the action in the event of no position data being returned from the browser, no matter what the reason. The final 'else' statement in the original code (above) would only be triggered on a device with no geolocation capacity.
This all makes sense now, but I have to say the documentation on Google, and many of the tutorial sites was far from clear on this, with frequent references to my initial syntax covering the situation where geolocation capacity was not enabled (as distinct from not present).
Thanks to this answer on SO for pointing me in the right direction.

Instagram authentication scope param using coldfusion

I have an Instagram application written in Coldfusion 8 that basically pulls in media by tags and then allows people to Like / vote on the photos which is all done via the Instagram API. The Liking part is causing me no end of grief though, as I can get the Authentication and Access_Token without a drama, however the Access_Token doesn't appear to have permission to Like by default. There is an optional param for the Authenticate call "scope" which allows you to pass the permissions allowed for the Access_Token but i cannot work out how to pass this via ColdFusion CFHTTP as a POST.
Here is the preparation for the data to be sent over CFHTTP looping over all params as type="FormField". No matter how I try and present the scope options, either JSON format, string with spaces, string with "+" delimiters it seems to have no effect and the Like operation continues to fail due to permission errors.
<cfscript>
var LOCAL = {};
LOCAL['config'] = {};
LOCAL['returnStruct'] = {};
// prep packet required by the main call method
// the following values are required for EVERY call
LOCAL['config']['method'] = 'POST';
LOCAL['config']['format'] = ARGUMENTS['outputType'];
LOCAL['config']['url'] = VARIABLES.authURL;
// variables required by this method
LOCAL['config']['params'] = {};
LOCAL['config']['params']['client_secret'] = ARGUMENTS.client_secret;
LOCAL['config']['params']['grant_type'] = 'authorization_code';
LOCAL['config']['params']['redirect_uri'] = ARGUMENTS.redirect_uri;
LOCAL['config']['params']['code'] = ARGUMENTS.code;
LOCAL['config']['params']['scope'] = 'likes comments relationships';
</cfscript>
If anyone else is running into the same issues with "scope" not being correctly applied to the return Access_Token it turns out the problem was Instagram Documentation being vague about where this argument should be used. I had tried it every way possible as a POST operation as it suggested during the server-side Authentication, however it appears to only work if sent as GET params and after some playing around I decided to tack the "scope" param onto the 2nd stage of the authentication which is where the Code is requested and that worked! See below
https://api.instagram.com/oauth/authorize/?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=likes+basic
This will present the user with an confirmation message from Instagram to allow the application to perform Likes on behalf of the user and everything else works like a charm after this.

google maps geocoding

hi i am having the same probem as here Return address from Google Maps Geocoder v3 , i dont understand how to set my global variable to the return vlaue
i got this at the moment where b returns undefined
var a;
var b;
function outputGeo(result){
b = result;
}
geocoder.geocode({'latLng': event.latLng},function(results, status) {
a = results[1].formatted_address;
outputGeo(a);
});
alert(b);
geocoder.geocode is an asynchronous function because it's performing a JSONP request. In other words, before the results have come back, the alert(b) line is already being called. You need to put that alert line into the callback function after outputGeo(a).
Javascript's a funny language. This async thing bit me until I researched JSONP and the synchrony of Javascript. I suggest you do the same. A great way to learn about this is to write a JSONP-request wrapper of your own. (Just a thought.)

Failing to fetch CategorizedFacebookType

I have an application which I developed about a year ago and I'm
fetching facebook accounts like this:
facebookClient = new DefaultFacebookClient(access_token);
Connection<CategorizedFacebookType> con = facebookClient.fetchConnection("me/accounts", CategorizedFacebookType.class);
fbAccounts = con.getData();
It worked fine until about a month ago, but now it returns the
fbAccounts list empty. Why is that?
I was hoping moving from restfb-1.6.2.jar to restfb-1.6.9.jar would
help but no luck, it comes up empty on both.
What am I missing?
EDIT, to provide the code for another error I have with this API. The following code used to work:
String id = page.getFbPageID(); // (a valid facebook page id)
FBInsightsDaily daily = new FBInsightsDaily(); // an object holding some insights values
try {
Parameter param = Parameter.with("asdf", "asdf"); // seems like the param is required
JsonObject allValues = facebookClient.executeMultiquery(createQueries(date, id), JsonObject.class, param);
daily.setPageActiveUsersDaily((Integer)(((JsonArray)allValues.opt("page_active_users_daily")).getJsonObject(0)).opt("value"));
...
This throws the following exception:
com.restfb.json.JsonException: JsonArray[0] not found.
at com.restfb.json.JsonArray.get(JsonArray.java:252)
at com.restfb.json.JsonArray.getJsonObject(JsonArray.java:341)
Again, this used to work fine but now throws this.
You need the manage_pages permission from the user to access their list of adminned pages - a year ago I'm not sure you did - check that you're obtaining that permission from your users
{edit}
Some of the insights metrics were also deprecated, the specific values you're checking may no longer exist - https://developers.facebook.com/docs/reference/fql/insights/ should have the details of what is available now
Try to check your queries manually in the Graph API Explorer to eliminate any issues in your code and hopefully get more detailed error messages that your SDK may be swallowing

Posting to a wall on Facebook for a fan page

Using the current PHPSDK and API (ie not FBJS or the REST approach) I am trying to work out how to paste to a fanpage wall and struggling to find any hints...
I have successfully (through various attempts)
posted to my wall
posted to a friend's wall
posted to the page's wall (when I like the page before posting)
posted to the page's wall (as the page)
So I am looking to work out what I need to do to access_code/permissions or code to have something like :
$result = $facebook->api(
'/<PAGEID>/feed/',
'post',
array('access_token' => <ACCESSCODE>, 'message' => 'Test message')
);
or
FB.api('/<PAGEID>/feed', 'post', {access_token:<ACCESSCODE>, message:'Test message'},
function(response) {
if (!response || response.error) {
alert(response.error.message);
} else {
}
});
working where a post will appear on the feed of page's wall... However I am currently unable to find a way to post to a page wall for a page that I have not explicitly said I like by using the Graph API in PHP...
I am sure it is possible judging by some of the page walls I have seen.
Searching on google and forums tends to lead to old API implementations (which no longer function) or using methods no longer supported. It seemed that the Templatized function could have been what I was looking for (but again that has been deprecated).
What am I doing wrong?
You have to have one of the page administrators give your app "publish_stream" permission. Something like this:
$session = $facebook->getSession();
$perms = 'publish_stream';
echo '<fb:login-button perms="' . $perms . '"></fb:login-button>';
Once the click the button and approve you, your callback url will get called with their session information.
Once you have that you can post to the wall of any page they administer. Using code like what you show in your question.