Sunday, November 30, 2008

Facebook error: "Errors while loading page from application Runtime errors: URLExceptionEmpty URLs not allowed here"

I got this error while coding a canvas page:

"Errors while loading page from application Runtime errors: URLExceptionEmpty URLs not allowed here"

It turns out that I had an image tag that I wanted to start empty and then set the src at a later time using javascript:

<img id="myimg" src="" />

But the error above gets thrown when you try to leave the img src blank. So as a workaround I've placed a transparent spacer image instead and now it works fine...

Saturday, November 29, 2008

Form.submit does not work in Facebook FBJS

Just a note: Facebook apparently does not support the ability to submit a form using javascript -- or fbjs -- (form.submit). Thus a user must click something in order for it to submit a form.

This came up because I'm working on a Facebook app in Flex that needs to post items to the user's feed. The Facebook AS3 API (http://code.google.com/p/facebook-actionscript-api/) appears to no longer work completely -- or at least the google code page indicates that development has stopped on it -- and I'm getting very gun shy about developing too tightly against a Facebook API that changes too quickly. As a result, I've decided to use javascript to pass values out of Flash and into hidden form fields on the facebook canvas page. The problem is that I can't call a function from flash that can also submit the form. So it seems that the best work around will be to create a button that shows above or below the Flex app that a user can click when they want to share an video or audio clip on their feed. The form will be updated with the proper values from Flex whenever a user changes their audio or video selection. It's not the cleanest implementation but the tests so far prove that it can work...

Making sense out of Facebook feeds - Part one: Template Bundles

I'm trying to make posting content to a Facebook feed work and have run into quite a few problems finding a good tutorial that actually works. So I'm posting these notes for myself and anyone else who might find them useful:

In order to publish a item from a Facebook application to a users feed you need to follow a couple of steps:

1. Create a "Template Bundle": This is a template that contains up to three types of feed templates, a title only (one line), a title and short content (short story) or a longer amount of content (full story). The template contain "tokens" which are essentially placemarks where dynamic content will be inserted once a user actually publishes content to their feed using this template. Tokens have this format {*name-of-token*}. {*actor*} and {*target*} are two reserved tokens and if used will be replaced with the name of the facebook user {*actor*} and/or the target of the action {*target*} such as : "Joe tagged Joanie". There are additional reserved words that can't be used for token names such as "flash", "images", "mp3" and "video".

Here is an example of a php page that creates and registers a template bundle. In this example we will use the {*actor*} token and also create a another token called {*author*}:


<?php

// create the different feed templates

// one line feed template

$one_line_story = array('{*actor*} saw a great video from {*author*}!');

//short story template

$short_story = array(

'template_title' => '{*actor*} saw a great short video from {*author*}!',

'template_body' => 'Check this video out >'

);



//full story template

$full_story = array(

'template_title' => '{*actor*} saw a great full video from {*author*}!',

'template_body' => 'Check it out! I found on <a href="http://www.youtube.com">YouTube</a>: <br/>'

);



// now register the bundle

$res = $facebook->api_client->feed_registerTemplateBundle($one_line_story, $short_story, $full_story);

// this is the template bundle id

echo $res

?>



2. Once you've registered this bundle you can save the id you got in the last line:
 echo $res 
or go to the Facebook Developer "Registered Templates Console" (http://developers.facebook.com/tools.php?templates) and get the ID for the particular template you want to use later.

3. Now you are ready to set the feed.

4. Lets say that you have a canvas page where you post a number of videos from YouTube and CNN. On the page you want to allow the user to let people know which one they looked at--such as: "Bill watched a video from CNN". To do this you need to create a form on your page with a required tag fbtype="feedStory" and the action param that points to a php page that will process the feed content and post it for you:

<form fbtype="feedStory" action="http://apps.facebook.com/myapp/set-feed-item.php"> 

<select size=2 name="author">

<option value="" selected="true">Select an author</option>

<option value="CNN" > CNN </option>

<option value="YouTube"> YouTube</option>

</select>

<input type="submit" label="Submit" /> </form>


5. Now here is the php processing page:


<?php

$feedReturn = array(

'content'=> array(

'feed'=> array(

'template_id'=>100566785645,

'template_data'=> array (

'author'=>$_POST['author']

// add additional tokens here

)

)

),

'method'=>'feedStory'

);
echo json_encode($feedReturn);

 
?>


Once the user has submitted the form from the canvas page, this page will process the information and post the feed. However, this sample will only post text. While I have successfully implemented adding an image to a short story feed post, I have been unable to add flash, videos and mp3s - despite following the Facebook documentation closely. Hopefully I will be able to figure this out shortly and add to this post later...

Friday, November 28, 2008

Finally figured out how to have Flash call Javascript in Facebook!

This took some doing. My goal was to have a Flash as3 movie (built in Flex) to communicate with Javascript on a Facebook canvas page. Here are the steps (quickly):

1. On the Facebook Canvas page insert a <fb:fbjs-bridge/> tag ABOVE your embedded flash movie (very important that it is ABOVE).
2. Insert the <fb:swf /> as indicated in the Facebook docs. Facebook will automatically pass a localConnection name via flashvars into the swf (the var is called "fb_local_connection").
3. In your flash movie get the localConnection name that Facebook passed in:
private var connectionName:String = Application.application.parameters.fb_local_connection;

4. Facebook exposes the Javascript that has been placed on a Canvas page by providing the function "callFBJS" in the bridge flash movie. This function requires two arguments:

callFBJS(myFunctionName:String,myArgs:Array)


5. With this info you can make the connection and call the javascript function:

connection.send(connectionName,"callFBJS",myFunctionName,myArgs);



Here is the sample code of a AS3 Flex app that call a js function on the canvas page called: showInvite();



<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="components.*" creationComplete="init();">

<mx:Script>

<![CDATA[

import flash.net.LocalConnection;

private var connection:LocalConnection = new LocalConnection();

private var connectionName:String = "";



private function init():void{

connectionName = Application.application.parameters.fb_local_connection;

}



private function callFBJS(methodName:String,args:Array):void {

if (connectionName!=""){

connection.allowDomain("apps.facebook.com", "apps.*.facebook.com");

connection.send(connectionName,"callFBJS",methodName,args);

}

}



private function showInvite():void{

var args:Array = new Array("arg1","arg2");

callFBJS("showInvite",args);

}

]]>

</mx:Script>

<mx:Button x="40" y="10" label="click" click="showInvite()"/>

</mx:Application>




For more info on this evolving drama (Facebook changes stuff all the time it appears): http://wiki.developers.facebook.com/index.php/Fb:fbjs-bridge

Facebook and Flash -- problem with fbjs-bridge

I'm learning the hard way how much of a pain it is to develop apps for Facebook. Documentation is quite bad, there are very few good tutorials-- and they change things without saying anything.

Here is a GREAT example. I'm trying to use their fb:fwjs-bridge to allow an swf file to communicate with js on the facebnook page -- using a localConnection. But it turns out that it completely fails if you don't place the fb:fbjs-bridge tag ABOVE your own swf file tag (fb:swf). If you put it below, nothing works.

Makes NO sense but there it is.....

Sunday, November 23, 2008

Save the hassle -- code FBML in blocks

After struggling with using a series of inline fbml blocks in order to create a narrow and wide version of a profile box, I've decided to just do two different versions each surrounding each with either<fb:wide><fb:/wide> or <fb:narrow><fb:/narrow> tags. This saves having the complicated inline tags every line or so. It also allows me to use the style block since that is also inside the FBML tag.

Cannot use FBML in css style block

I'm learning a lot about facebook right now -- especially that there are not a lot of good resources whe you want to do more complex coding with it. The tutorials mostly skim the surface of the easiest integration -- or provide you wiht code that you have to deconstruct. Even the OReilly "Essential" book is a joke--it give a few pages of intro and then just provides the API in book form.

In any event, here is a css tip: you cannot use FBML is a style block. For instance, if you have a div like this:

<div class="content"></div>

and you define the style in a block:

<style>
.content{
width:400px;
}
</style>

you can't use FBML to change the property based on something like the width of the profile box it appears in:

<style>
.content{
<fb:wide> width:400px;</fb:wide>
<fb:narrow> width:100px;</fb:narrow>
}
</style>

Instead, you'll need to use inline styles --or enclose the tag itself in the fbml code:

<fb:wide> <div id="content" style="width:400px"></fb:wide>
<fb:narrow> <div id="content" style="width:100px"></fb:narrow>

Thursday, November 20, 2008

Facebook and Flash -- getting an embedded Flash app to work with getURL() or navigateToURL()

Long story short, you can't use getURL() or navigateToURL() with Flash when you embed the piece with fb:swf. The Flash security sandbox prohibits this in a flash movie loaded from a different domain. You can use an iframe but that causes other issues with Facebook. The folks at Facebook decided to resolve this by using a localConnection instead.

To use it add this FBML tag to the page where your FB:swf tag is:

fb:fbjs_bridge

I then created a util function called getURL() to remind me of the good old days. This function first checks to see if it can make the navigateToURL() directly and if not uses the lc instead. This way the same movie will work as a standalone and on Facebook too:

public static function getURL(thisURL:String):void{
var request:URLRequest = new URLRequest(thisURL);
try{
navigateToURL(request);
}catch(er:Error){
// for Facebook
var conn: LocalConnection = new LocalConnection(); ;
conn.send("callFBJS", "document.setLocation",[thisURL]);
}

}

Here is more info onthe genesis of the problem:

http://bugs.developers.facebook.com/show_bug.cgi?id=994#c28

Facebook errors: fb:redirect: redirect forbidden

I'm working on putting a flash app onto facebook and had this error when I tried to use a page in a tab:

fb:redirect: redirect forbidden by flavor TabFBMLFlavor on the profile tab.

A bit of searching revealed that you can't require ogin: $userid = $facebook->require_login();

Unless you check to see if the userid is null:

$userid = $facebook->get_profile_user();
if(is_null($userid)){
$userid = $facebook->require_login();
}

Monday, November 3, 2008

Outline around a Flash movie in Firefox -- with SWFObject

Suprisingly this one took a while to find the answer to. I embedded a flash movie using SWFObject and found that once a user clicked on the movie, a dotted line appeared around the edge of the swf (in Firefox). I tried adding "outline:none" to the css for the div but it didn't help. The only thing that worked was to add this to the javascript right after creating the swfObject:

swfobject.createCSS("#growth","outline:none");
(where growth was the name of the target div)

So here was the full code for the swfObject:

swfobject.embedSWF("web-v2.swf", "growth", "1024", "768", "9.0.124","expressInstall.swf", flashvars, params, attributes);

swfobject.createCSS("#growth","outline:none");