Advertisement

Create a Facebook Graph API App in Flash: Displaying Facebook Info

by

Welcome back to our facebook app tutorial! This is the last part of the series, and also the part where we get all the Facebook info to display to the user.


Also Available in This Series:

  1. Create a Facebook Graph API App in Flash: Setup and Design
  2. Create a Facebook Graph API App in Flash: Generating Embed Code
  3. Create a Facebook Graph API App in Flash: Loading Events
  4. Create a Facebook Graph API App in Flash: Displaying Facebook Info

Final Result Preview

This application allows you to select a Facebook album or event list from one of your public pages and turn it into a slideshow for your page's tab. When the users enter your page, they will see photos from your chosen album, with your photo title and description, or event name, date and location.

You'll need to be logged in to Facebook in order to see this demo: https://apps.facebook.com/activetuts_tabmaker/


Step 1: Where We Left Off

In the previous part of this series, we created the event slider generator. In this part we'll make the actual slider for the images (and later, for the events).

Create a new 760x500px FLA, in the same folder as usual, with the name AlbumSlider.fla. Set its document class to tabmaker.AlbumSlider, and enter the following in a new AlbumSlider.as file:

 
package tabmaker 
{ 
	import flash.display.*; 
	import flash.events.*; 
	import flash.net.*; 
	import flash.text.*; 
	import flash.external.ExternalInterface; 
	import flash.system.*; 
	import fl.motion.Color; 
 
	import com.greensock.*; 
	import com.greensock.events.*; 
	import com.greensock.easing.*; 
	import com.facebook.graph.Facebook; 
	import flash.utils.Timer; 
 
	public class AlbumSlider extends Sprite 
	{		 
		private var rs; 
		private var show_titles; 
		private var album_id; 
		private var curr; 
		private var t; 
		private var active_slide; 
		private var old_slide; 
		private var title_mc; 
		 
		public function AlbumSlider(){ 
			album_id = loaderInfo.parameters.album_id; 
			show_titles = loaderInfo.parameters.show_titles; 
			 
			init(); 
		} 
		 
		public function init(){ 
			Facebook.api( album_id+'/photos?limit=500', photos_loaded ); 
		} 
    } 
}

The code in this class is potentially simple ( at least, it should be if you've gone through the other parts in the series ). First, we get the album_id and show_titles variables from the passed parameters. Next, we use the Facebook.api() to get the album_id/photos endpoint, which will return us the photos currently in the album.

We have a couple of variables in the class definition:

  • show_titles, which holds the respective param,
  • album_id, which holds the album's ID,
  • curr, which will hold the index of the current slide,
  • t, which is the timer, and
  • active_slide and old_slide, which will hold the active slide and the last displayed slide.

Lastly, we have a title_mc variable which will hold the picture title asset.


Step 2: The photos_loaded() Function

Let's continue by creating the photos_loaded() function:

 
public function photos_loaded( succ, err ){ 
    rs = new Array(); 
    if( succ ){ 
        for( var i=0;i<succ.length;i++){ 
             
            rs.push( succ[i] ); 
        } 
 
        start_slider(); 
    } 
     
}

In this function, I check for the succ object being valid, and if it is, I fill the rs array with the corresponding items.

After we have done this, we can start the slider, for which we'll need this new function:

 
public function start_slider(){ 
    curr = 0; 
    t = new Timer( 5000 ); 
    t.addEventListener( TimerEvent.TIMER, slide_change ); 
    t.start(); 
    slide_change(); 
}

It's a very simple function: basically, it resets curr and then calls slide_change() every five seconds. We'll create the actual slide_change() function next.


Step 3: The slide_change() Function

This function is the most important function in this fla: It changes the slide:

 
function slide_change( e=false ){ 
    if( active_slide ){ 
        if( show_titles ){ 
            hide_title(); 
        } 
        var tw = TweenLite.to( active_slide, 3000, {alpha: 0, onComplete: remove } ); 
    } 
    active_slide = new Picture( rs[ curr ].images[0].source, this ); 
    addChild( active_slide ); 
    TweenLite.to( active_slide, 3000, {alpha: 1} ); 
    if( show_titles ){ 
        show_title( rs[curr] ); 
    } 
     
    curr++; 
    if( curr > (rs.length-1) ){ 
        curr = 0; 
    } 
}

There are quite a few things happening here.

First we check if we have a previous slide that was already added. (The first time we run the slider, active_slide will be null, so this code won't execute.) If so, we check if show_titles is true, in which case we know there's already a title on screen, so we hide it. Then we fade the last picture out.

Next, we set the active_slide to a new instance of Picture (which is a class that we'll code later). We also fade in the picture and add it to the display list.

If the show_titles is true, we also call show_title with the passed item ( from which we'll get the title of the picture ).

Finally, we increment curr; if it's greater than the total number of images we have, we reset it to zero.


Step 4: The Picture Class

Let's code the picture class, which will load the album picture:

 
package tabmaker { 
	 
	import flash.display.*; 
	import flash.events.*; 
	import flash.net.*; 
	import flash.text.*; 
	import flash.external.ExternalInterface; 
	import flash.desktop.*; 
	import fl.motion.Color; 
	 
	import com.greensock.*; 
	import com.greensock.easing.*; 
	 
	public class Picture extends Sprite { 
		 
		private var path; 
		private var main; 
		private var msk; 
		private var thumb; 
		 
		public function Picture( path, main ) { 
			this.path = path; 
			this.main = main; 
			this.addEventListener( Event.ADDED_TO_STAGE, init ); 
		} 
		 
		private function init( e ){ 
			var tl = new Loader(); 
			tl.contentLoaderInfo.addEventListener( Event.COMPLETE, on_loaded_thumb ); 
			tl.load( new URLRequest( path ) ); 
		} 
		 
		public function on_loaded_thumb( e ){ 
			thumb = e.target.loader; 
			var ratio = 0; 
			var th = 500; 
			var tw = 760; 
			if( thumb.width > thumb.height ){ 
				ratio = thumb.width / thumb.height; 
				thumb.width = th*ratio; 
				thumb.height = th; 
			} else { 
				ratio = thumb.height / thumb.width; 
				thumb.width = tw; 
				thumb.height = tw*ratio; 
			} 
			thumb.x = 0; 
			thumb.y = 0; 
			 
			msk = new Shape(); 
			msk.graphics.beginFill(0xffffff,1); 
			msk.graphics.drawRect(0,0,tw,th ); 
			msk.graphics.endFill(); 
			 
			addChild( msk ); 
			addChild( thumb ); 
			thumb.mask = msk; 
			thumb.alpha = 0; 
			TweenLite.to( thumb, 0.3, { alpha: 1 } ); 
		} 
		 
	} 
	 
}

I won't be getting into too much detail, as this class is a close copy of the PhotoItem.as class from Part 1, only without the button interaction.

Basically, we create a Loader object, add the listener for when the picture is loaded, and calculate a size ratio which will fit the picture in the fixed 760x500px rectangle. Also we mask the created image with a mask with the same dimensions ( to make sure the picture is not bigger and doesn't show through ) and fade it in.


Step 5: Showing the Photo Title

Let's make the function which shows the photo title:

 
function show_title( cfg ){ 
    title_mc = new Sprite(); 
    title_mc.graphics.beginFill( 0x000000, 0.4 ); 
    title_mc.graphics.drawRect( 0,0 ,760, 60 ); 
    title_mc.graphics.endFill(); 
    title_mc.x = 0; 
    title_mc.y = 500; 
     
    var t = new TextField(); 
    t.defaultTextFormat = new TextFormat( 'Arial', 18, 0xffffff, true ); 
    t.width = 440; 
    t.selectable = false; 
    t.text = cfg.name; 
    t.x = 30; 
    t.y = 18; 
    title_mc.addChild( t ); 
     
    stage.addChild( title_mc ); 
     
    TweenLite.to( title_mc, 0.5, { y: 440} ); 
     
}

The function is pretty straightforward. We create a 760x60px rectangle sprite with the help of the graphics instructions. I set the background color to 0x000000, which is black, but with 0.4 opacity, which makes it seem like a transparent band.

Next, we created a text field and set up its style. It's important to make the text unselectable, as otherwise it can make the user select the text when he doesn't want to. We also tween the whole clip to it into view ( it starts off out of the screen bounds ).


Step 6: Hiding the Title

So, we have shown the title, but how do we hide it? Let's code the hide_title() function:

 
function hide_title(){ 
    old_slide = active_slide; 
    TweenLite.to( title_mc, 0.5, {y: 500, onComplete: remove}); 
} 
function remove(){ 
    old_slide.parent.removeChild( old_slide ); 
}

We set the active_slide to old_slide, and fade out the title_mc sprite. We have to use the old_slide variable here, as when the remove() function executes, the active_slide variable points to the newly created title of the next slide. This way, the remove() function can do its job, basically using removeChild() to get rid of the clip.

If you compile the clip now and test it on a webserver, you'll see that the pictures are loaded from Facebook and cycled one after the other.


Step 7: The Event Slider

In the case of the event slider, things get a bit more complicated. We cannot get the info direcly without having an access token, so we need to change the embed code in the generator to include the Facebook JavaScript SDK ( in the EventMaker.as file ):

 
private var EMBED_CODE = '<script type="text/javascript" src="https://connect.facebook.net/en_US/all.js"></script><object src="event_tab.swf?page_id=%s&%arg"></object>';

This will ensure the SDK will correctly connect to Facebook via the fbjs bridge.


Step 8: The EventSlider Class

Create a new 760x180px FLA and name it EventSlider.fla. Set its document class to tabmaker.EventSlider and create a new EventSlider.as file in the tabmaker folder.

Let's start coding this class:

 
package tabmaker 
{ 
	import flash.display.*; 
	import flash.events.*; 
	import flash.net.*; 
	import flash.text.*; 
	import flash.external.ExternalInterface; 
	import flash.system.*; 
	import fl.motion.Color; 
 
	import com.greensock.*; 
	import com.greensock.events.*; 
	import com.greensock.easing.*; 
	import com.facebook.graph.Facebook; 
	import flash.utils.Timer; 
 
 
	public class EventSlider extends Sprite 
	{		 
		private var rs; 
		private var page_id; 
		private var curr; 
		private var t; 
		private var active_event; 
		private var old_event; 
		 
		private var APP_ID = '283591785046507'; 
		 
		public function EventSlider(){ 
			page_id = oaderInfo.parameters.event_id; 
			 
			init(); 
		} 
		 
		public function init(){ 
			Facebook.init( APP_ID, on_init, {} ); 
		} 
         
	} 
}

There are some familiar variables in this class. We have an rs array, which will hold the event items; we have a page_id variable, which will hold the page ID from Facebook; again here's the well known curr variable; and we have the active_event and the old_event variables, which will hold the active and old slides.

First, we set the page_id variable from the passed parameters object and call the init() function, in which we use Facebook.init() with the APP_ID variable, which holds the application ID.

I also pass an empty object as the third parameter. I found that without this, we won't receive an access_token. I don't know whether that's a bug or a mistake, but it works!


Step 9: The on_init() Function

We need to get the events and put them in the rs array:

 
public function on_init( succ, fail ){ 
    Facebook.api( page_id+'/events', events_loaded ); 
} 
 
public function events_loaded( succ, err ){ 
    rs = new Array(); 
    if( succ ){ 
        for( var i=0;i<succ.length;i++){ 
            rs.push( succ[i] ); 
        } 
 
        start_slider(); 
    } 
     
}

Let's see what happens here: When we have initialized the Facebook SDK, we have an access token at our disposal, so we call Facebook.api() with the endpoint page_id/events to get a list of the events belonging to the current page.

After we successfully load these in the events_loaded() function, we put them in the rs array and call start_slider(), just as we did in the AlbumSlider.


Step 10: Start Your Slider, Sir

This function does the same thing as the one in AlbumSlider:

 
public function start_slider(){ 
    curr = 0; 
    t = new Timer( 5000 ); 
    t.addEventListener( TimerEvent.TIMER, event_change ); 
    t.start(); 
    event_change(); 
}

Step 11: Switching the Events

Let's write the event_change() function, which is triggered by the code we wrote in the previous step:

 
function event_change( e=false ){ 
    if( active_event ){ 
        old_event = active_event; 
        var tw = TweenLite.to( active_event, 0.6, {y: -200, onComplete: remove } ); 
    } 
    active_event = new EventDisplay( rs[ curr ], this ); 
    addChild( active_event ); 
    active_event.y = 200; 
     
    TweenLite.to( active_event, 0.6, {y: 0} ); 
     
    curr++; 
    if( curr > (rs.length-1) ){ 
        curr = 0; 
    } 
}

Here, we first check for a previous slide. If there is one, we set it to the old_event variable, tween it out of the stage, and call remove(), which will remove the event slide from the display list:

 
function remove(){ 
    old_event.parent.removeChild( old_event ); 
}

Next, we create a new EventDisplay class, which we'll code in a moment. This class will be a slide that contains the information about the event. We create the slide off-stage, then tween it in.

The rest is just as in the AlbumSlider: we increment the curr variable and set it to 0 if it's greater than the number of slides.


Step 12: The EventDisplay Class

Create a new ActionScript class in the tabmaker folder and call it EventDisplay.as:

 
package tabmaker 
{ 
	import flash.display.*; 
	import flash.events.*; 
	import flash.net.*; 
	import flash.text.*; 
	import flash.external.ExternalInterface; 
	import flash.system.*; 
	import fl.motion.Color; 
 
	import com.greensock.*; 
	import com.greensock.events.*; 
	import com.greensock.easing.*; 
	import com.facebook.graph.Facebook; 
	import flash.utils.Timer; 
 
 
	public class EventDisplay extends Sprite 
	{		 
		private var cfg; 
		private var main; 
		 
		public function EventDisplay( cfg, main ){ 
			var t = new TextField(); 
			t.x = 20; 
			t.y = 20; 
			t.width = 680; 
			t.multiline = true; 
			t.autoSize = 'left'; 
			t.selectable = false; 
			t.defaultTextFormat = new TextFormat('Arial', 28, 0xffffff, true ); 
			t.text = cfg.name; 
			addChild( t ); 
 
			var loc = new TextField(); 
			loc.x = 20; 
			loc.y = 30 + t.textHeight; 
			loc.width = 680; 
			loc.defaultTextFormat = new TextFormat('Arial', 22, 0xffffff, true, true ); 
			loc.text = cfg.location; 
			loc.selectable = false; 
			addChild( loc ); 
			 
			var st = new TextField(); 
			st.x = 20; 
			st.y = 110; 
			st.width = 350; 
			st.height = 24; 
			st.selectable = false; 
			//prepare dates 
			var sd = cfg.start_time.split('T'); 
			var ed = cfg.end_time.split('T'); 
			 
			st.defaultTextFormat = new TextFormat('Arial', 18, 0xAAAAFF, true ); 
			st.text = sd[0]+ ' - '+ed[0]; 
			addChild( st ); 
			 
			//thumbnail 
			var th = new Loader(); 
			th.load( new URLRequest( Facebook.getImageUrl( cfg.id, 'square' ) ) ); 
			th.x = 690; 
			th.y = 20; 
			addChild( th ); 
		} 
		 
		 
		 
	} 
}

Wow, this class is really big, but it's got only one function.

The JSON object we pass to it, cfg, contains the title, start date, end date and location of the event ( see the format here ).

First, we create, position, and style text fields for the title, location, and dates. Facebook displays a date as mm-dd-yyyyThh-mm-ss, separating the date from the time with the character T. If we use String.split(), we can obtain the date from the first item of the returned array.

The last part of this rather huge function ( and class ), is the creation of a small thumbnail. We create a Loader object and pass it the URL we get by using Facebook.getImageUrl() function with the ID of the event. The second parameter allows us to specifying the format; Facebook has a special format, "square" which will return a square image, usable as an avatar.


The End of This Series

This is the end of the fourth and final part of the series. I realise the event tab might not look extremely great, but all the code you need is there, at least, so feel free to spruce it up.

If you're up for a challenge, I suggest you make this page display a list of the attendees. ( Here's a hint: it's all about using the event_id/attending graph endpoint and checking the rsvp_status ).

I hope you have learned something new from my series. Thanks for reading!

Advertisement