Facebook新的api与旧的相比,有了很大的不同,更加倾向于简约实用,摒弃了旧代码的臃肿繁琐.抛弃了Cross-Domain Receiver Page.旧有的Cross Domain经常有卡在xd_receiver.htm页面没反应的情况发生,新api很好的解决了这个问题.
初始化,登录,授权,FQL,UI等各个方面都有了很大的变化,首先看初始化的不同:
Old API:
<script type="text/javascript" src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php"> <script language="javascript"> FB_RequireFeatures(["Api"], function() { FB.Facebook.init('api_key', 'xd_receiver.htm', { "ifUserConnected": function(){ // -- connected }, "ifUserNotConnected": function(){ // -- not connected } }); });
New Api(JS初始化的时候,可以分为两种方式,异步和同步):
异步方式:
<div id="fb-root"></div> <script language="javascript"> window.fbAsyncInit = function() { FB.init({appId: facebook.facebook_app_id, status: true, cookie: true, xfbml: true}); FB.Event.subscribe('auth.sessionChange', facebook.api_sessionChange); FB.getLoginStatus(facebook.api_sessionChange); }; (function() { var e = document.createElement('script'); e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js'; e.async = true; document.getElementById('fb-root').appendChild(e); }());
同步方式:
<div id="fb-root"></div> <script language="JavaScript" src="http://connect.facebook.net/en_US/all.js"> <script language="javascript"> FB.init({appId: facebook.facebook_app_id, status: true, cookie: true, xfbml: true}); FB.Event.subscribe('auth.sessionChange', facebook.api_sessionChange); FB.getLoginStatus(facebook.api_sessionChange); </script>
新api提供了函数FB.Event.subscribe(),用来检测facebook登录状态变化.
新的api需要用户授权时,调用的函数跟Login一样,只是多了需要授权的参数.
FB.login(function(response) {
if (response.session) {
if (response.perms) {
// user is logged in and granted some permissions.
// perms is a comma separated list of granted permissions
} else {
// user is logged in, but did not grant any permissions
}
} else {
// user is not logged in
}
}, {perms:'read_stream,publish_stream,offline_access'});
新的api在简化了之后,也带来了诸多不便,首先,feed发布的时候,有些许bug,facebook规定在feed长度超过1000的字符的时候,用 post的方式传递数据,不过facebook在传递数据的时候,传错了值,应该将attatch对象json_encode后传递,却直接穿了对象过 去,导致feed发布不了,修正方式是,参考source code修改FB.Content.postTarget函数定义.
FB.Content.postTarget = function(opts) { var form = document.createElement('form'); form.action = opts.url; form.target = opts.target; form.method = 'POST'; FB.Content.appendHidden(form); FB.Array.forEach(opts.params, function(val, key) { if (val !== null && val !== undefined) { var input = document.createElement('input'); input.name = key; if (typeof val == "object" || typeof val == "array") { input.value = FB.JSON.stringify(val); } else { input.value = val; } form.appendChild(input); } }); form.submit(); form.parentNode.removeChild(form); };
本来代码是:
postTarget: function(opts) {
var form = document.createElement('form');
form.action = opts.url;
form.target = opts.target;
form.method = 'POST';
FB.Content.appendHidden(form);
FB.Array.forEach(opts.params, function(val, key) {
if (val !== null && val !== undefined) {
var input = document.createElement('input');
input.name = key;
input.value = val;
form.appendChild(input);
}
});
form.submit();
form.parentNode.removeChild(form);
}
facebook的fbml实际上是加载一个iframe,加载之前显示loading,facebook这里采用的是html5 的,facebook这里的实现偶尔会出现问题,一直loading,iframe显示不出来,facebook开发团队还没有给出解决方法,还是通过修 改js source解决
首先增加一个变量:
/********* fix fbjs api start:{set method used for FB.UIServer.iframe} *************/ FB.UIServer._SDialogMethod = ''; /********* fix fbjs api end *************/
修改FB.UIServer.prepareCall方法,增加以下代码,记录当前的ui method:
/********* fix fbjs api start:{set method used for FB.UIServer.iframe} *************/ FB.UIServer._SDialogMethod = params.method.toLowerCase(); /********* fix fbjs api end *************/
修改FB.UIServer.iframe方法,iframe加载的时候,直接显示:
/********* fix fbjs api start:{dialog loading bug,set default iframe and float div size} *************/ if ('stream.publish' == FB.UIServer._SDialogMethod) { var _SLoaderState = false; // -- 是否显示loading,这里改为false,不显示 var _SVisibleState = true; // -- ui dialog是否可见,设为true,可见 // -- set iframe background default size,only set width so it will show at center,if set height, the background can't resize if iframe size changed var _SInitSize = { width: 575, height:'100%'}; call.size.height = 290; } else if ('bookmark.add' == FB.UIServer._SDialogMethod) { var _SLoaderState = false; var _SVisibleState = true; // -- set iframe default size var _SInitSize = { width: 460, height:'100%' }; } else if ('auth.permission' == FB.UIServer._SDialogMethod) { var _SLoaderState = false; var _SVisibleState = true; // -- set iframe default size if ('email' == call.params.ext_perm) { var _SInitSize = { width: 627, height:200}; call.size.height = 200; } else { var _SInitSize = { width: 627, height:350}; call.size.height = 350; } } else { var _SLoaderState = true; var _SVisibleState = false; var _SInitSize = false; } /********* fix fbjs api end *************/
修改FB.Dialog.create方法,修改为以下,如果有初始大小的话,设置长宽值:
if (opts.visible) { /********* fix fbjs api start:{dialog loading bug,set default iframe size} *************/ try { if (opts._SInit) { dialog.style.width = opts._SInit.width + 'px'; dialog.style.height = opts._SInit.height + 'px'; } } catch (e) {} /********* fix fbjs api end *************/ FB.Dialog.show(dialog); }
这样修改之后,feed或者bookmark发布的时候,就不会一直卡在loading那里了,尤其是后台有大量数据加载时候,比较容易卡loading
最后修改授权时的弹出窗口问题,现在授权的时候,调用的是跟登录时候一样的接口,所以授权界面会在新窗口打开,这样就会被大部分浏览器屏蔽掉,在用户至上的现在,显然是不能接受的,所以参考旧api的方法,自定义一个ui method.
/************* fix fbjs api start: {permission dialog} ******************/ FB.provide('UIServer.Methods', { 'auth.permission': { size : { width: 627, height: 350 }, url : 'connect/prompt_permissions.php', transform : function(call) { //FIXME if (!FB._apiKey) { FB.log('FB.login() called before calling FB.init().'); return; } // if we already have a session and permissions are not being requested, // we just fire the callback if (FB._session && !call.params.perms) { FB.log('FB.login() called when user is already connected.'); call.cb && call.cb({ status: FB._userStatus, session: FB._session }); return; } var xdHandler = FB.Auth.xdHandler, cb = call.cb, id = call.id, session = FB._session, cancel = xdHandler( cb, id, 'parent', true, // isDefault FB._userStatus, session), next = xdHandler( cb, id, 'parent', false, // isDefault 'connected', session); FB.copy(call.params, { cancel_url : cancel, channel_url : window.location.toString(), next : next, ext_perm : call.params.perms }); delete call.cb; delete call.params.perms; //TODO fix name to be the same on server return call; } } }); /************* fix fbjs api end ******************/
需要授权时,调用以下函数:
FB.ui( { method: 'auth.permission', perms: p_permissions }, function(response){ if ('' == response) { p_callback('failed'); return false; } if (response.perms && egi.test(response.perms)) { // -- success var p_state = 'success'; } else { var p_state = 'failed'; } if (typeof p_callback == 'function') { p_callback(p_state); } } );