需求是醬子:
跑出小視窗,要求登入FB聯外通→
列出朋友照片列表→
點選朋友照片→將被選朋友的個人檔案原吋照片傳回母視窗的 Flash 影片中。
當然,可以用 Facebook 給 Flash 的 API 去做更直接,但我還沒研究過這塊,都在摸 PHP & JS 的 FB 方法,跟 Flash 還不大熟 Orz
回歸正題,我分成幾個部分來說:
1. FB Connect 聯外通 與 取得權限
2. FQL in JavaScript 取得朋友列表 & 取得原吋大圖
3. Flash 與 JavaScript 的溝通,變數傳回
- 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 & Firefox 上會失效,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
登出方法很單純,就不多說了。
- FQL in JavaScript 取得朋友列表 & 取得原吋大圖
取得朋友列表 getFriendlist()
,使用 FQL 方法去撈(uid
是 Facebook 的使用者索引號、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;
}
});
});
}
- Flash 與 JavaScript 的溝通,變數傳回
OK,這個就跟 FB 沒啥關係了。
上面兩點都是在 window.open
叫出來的子視窗中做的。
母視窗我擺了個 Flash,裡面的 ActionScript:
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 進來擺到 MovieClip 上。
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
大概就是降子。