需求是醬子:

Flash 中點選按鈕→

跑出小視窗,要求登入FB聯外通→

列出朋友照片列表→

點選朋友照片→將被選朋友的個人檔案原吋照片傳回母視窗的 Flash 影片中。

當然,可以用 Facebook 給 Flash 的 API 去做更直接,但我還沒研究過這塊,都在摸 PHP & JS 的 FB 方法,跟 Flash 還不大熟 Orz

回歸正題,我分成幾個部分來說:
1. FB Connect 聯外通 與 取得權限
2. FQL in JavaScript 取得朋友列表 & 取得原吋大圖
3. Flash 與 JavaScript 的溝通,變數傳回

==========================

1. FB Connect 聯外通 與 取得權限

Facebook 的聯外通機制似乎有改,原本的方法取得權限似乎不行。
OK .. 先設定會用到的 script:

<div id="fb-root"></div>
    <script>
      window.fbAsyncInit = function() {
        FB.init({appId: '應用程式 ID', status: true, cookie: true,
                 xfbml: true});

        // fetch the status on load
	    FB.getLoginStatus(function (response)
    	      {
    	  		getFriendlist(); // 這邊自訂一個 getFriendlist 方法,希望登入後就直接去跑朋友列表
    	      }
	    );
      };
      (function() {
        var e = document.createElement('script');
        e.type = 'text/javascript';
        e.src = document.location.protocol +
          '//connect.facebook.net/zh_TW/all.js';
        e.async = true;
        document.getElementById('fb-root').appendChild(e);
      }()); // 把聯外通需要的 js 檔放到 fb-root 這個 div 裡
    </script>

接著來做登入登出的按鈕:

		<span class="btn" id="fblogin" onclick="facebookLogin('user_photos,friends_photos,user_photo_video_tags,friends_photo_video_tags');">
			Connect with Facebook
		</span>
		<span class="btn" id="fblogout" onclick="facebookLogout();" style="display: none;">
			Logout from Facebook
		</span>

之所以自訂呢.. 是因為原生的 FBML 聯外通按鈕,似乎登入後自動重整的屬性在 IE&FX 上會失效,Chrome 倒是可以,尚未細究,先用自己寫的吧。

這邊用到了 facebookLogin 與 facebookLogout 兩個方法,下面緊接著列出:

function facebookLogin(permissions) {
    FB.login(function () {
        window.location.reload();
    }, {
        perms: permissions
    });
}

function facebookLogout() {
    FB.logout(function () {
        window.location.reload();
    });
}

facebookLogin 方法我一併塞入了所需的權限(Permission),這邊就看您應用程式的需求啦 … 另外我希望他登入後可以自動重整頁面,window.location.reload()。

facebookLogout 登出方法很單純 .. 就不多說了。

2. FQL in JavaScript 取得朋友列表 & 取得原吋大圖

取得朋友列表 getFriendlist(),使用 FQL 方法去撈( uid 是 fb 的使用者索引號、pic_small 是使用者的個人檔案小圖),然後把這些圖塞到某個 div 裡面,本例為 id 為 friendlist 的 div。
然後每個圖上都加一個 onclick 屬性,去呼叫抓大圖回傳的 function。

function getFriendlist() {
	var fbLoaded = false;
    FB.getLoginStatus(function (response) {
        var usession = response.session;
        if (usession != null && !fbLoaded) {
            var uid = "" + usession.uid;
            fbLoaded = true;
            $("#fblogin").hide();
            $("#fblogout").show();
            var fql = "SELECT uid,pic_small FROM user WHERE uid IN ( SELECT uid2 FROM friend WHERE uid1='"+ uid +"' )";
            FB.api({
                method: 'fql.query',
                query: fql
            }, function (result, fbex) {
                if (fbex != null) {
                    $("#fblogin").show();
                    $("#fblogout").hide();
                    fbLoaded = false;
                    return;
                }

                var target = $('#friendlist');
                target.html('');

                //取得要顯示API回傳資料的區塊
                for( i = 0, j = result.length; i < j; i++ ){
                    if( result[i].pic_small === null || result[i].pic_small === '' ){
                        result[i].pic_small = 'http://static.ak.fbcdn.net/pics/q_silhouette.gif';
                    }
                    var html = '';
		html = '<img src="'+result[i].pic_small+'" longdesc="'+result[i].pic_small+'" onclick="getPicBigURL('+result[i].uid+')" />';
                    $(html).appendTo(target);
                }

            });
        }

    });
}

接著是取得大圖的方法:
一樣用 FQL 去撈 .. 撈出 src_big (大圖的網址),然後傳回母視窗。
這邊用到了呼叫母視窗 JavaScript function 的方法 opener.callFlash() .. 是為了把變數傳進 Flash。

function getPicBigURL(uid) {
    FB.getLoginStatus(function (response) {

            var fql = "SELECT src_big FROM photo WHERE pid IN (SELECT cover_pid FROM album WHERE owner ='" + uid + "' AND type = 'profile')";
            FB.api({
                method: 'fql.query',
                query: fql
            }, function (result, fbex) {
                if (fbex != null) {
                    return;
                }
				try {
	                //$("#photo").attr("src",result[0]['src_big']);
					opener.callFlash(result[0]['src_big']);
					window.close();
				} catch(exception) {
					alert("無法取得這名使用者的圖片,權限問題?請選擇另一位吧 >_<");
					return;
				}
            });

    });
}

3. Flash 與 JavaScript 的溝通,變數傳回

OK .. 這個就跟 FB 沒啥關係了。
上面兩點都是在 window.open 叫出來的子視窗中做的。

母視窗我擺了個 Flash,裡面的 AS:

btn.addEventListener(MouseEvent.CLICK,function(){
	ExternalInterface.call("openConnect");
});

ExternalInterface.addCallback("flashHello", flashHello);
function flashHello(message:String):void{
    picurl.text = "url is:" + message;

	var imgloader:Loader= new Loader();
	imgloader.load(new URLRequest(message));
	imgloader.name = "xchild";

	if(pic.getChildByName("xchild") != null) {
		pic.removeChild(pic.getChildByName("xchild"));
	}
	pic.addChild(imgloader);
}

ExternalInterface.call() 是用來呼叫 HTML 頁面上的 JavaScript function。
本例是開一個新視窗:

    function openConnect() {
       window.open("getfriend.htm","getfriend","width=600,height=400,status=no,location=no,status=no,menubar=no,toolbar=no,resizable=no,scrollbars=yes");
    }

那怎麼從外部用 JavaScript 去控制 Flash 的內容呢?
就是 ExternalInterface.addCallback 方法囉,第一個變數擺 JavaScript function name,第二個擺 flash 內的 function name。
我希望變數傳進來之後,在文字框內顯示字串、然後將圖片 load 進來擺到 mc 上。

JavaScript 我自訂了一個 callFlash function ..
也就是子視窗呼叫的 function:

	function callFlash(url){

		var obj = swfobject.getObjectById("FlashID");
		if(obj)
			obj.flashHello(url);

	}

上面提到 ExternalInterface.addCallback 方法,要先指定好 Flash 物件名稱,然後 物件名稱.Function名稱(變數) 去使用 ..
若有使用 swfobject 的話,直接照上面那樣就可以抓到元件了。

參考:http://pro.ctlok.com/2010/06/javascript-actionscript.html

大概就是降子。