├── test ├── features │ └── ngFacebook.feature ├── scripts │ └── web-server.js ├── index.html ├── index.js └── specs │ └── def.js ├── bower.json ├── protractor.conf.js ├── .travis.yml ├── package.json ├── LICENSE ├── .gitignore ├── README.md └── ngFacebook.js /test/features/ngFacebook.feature: -------------------------------------------------------------------------------- 1 | Feature: ngFacebook 2 | Scenario: Facebook load 3 | Given angular webpage with ngFacebook 4 | Then facebook sdk should be loaded 5 | Scenario: Login 6 | Given an anonymous state 7 | When I login with facebook user "charlie_hportxj_chaplin@tfbnw.net" with password "1234" 8 | Then I should be logged in 9 | Then my name is "Charlie Chaplin" 10 | Scenario: cachedApi- friends list 11 | When I getting the list of my friends 12 | Then I should see "Marilyn Monroe" as a friend of mine -------------------------------------------------------------------------------- /test/scripts/web-server.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Authored by AlmogBaku 3 | * almog.baku@gmail.com 4 | * http://www.almogbaku.com/ 5 | * 6 | * 27/12/14 21:20 7 | */ 8 | 9 | var express = require('express'); 10 | var app = express(); 11 | 12 | app.use(express.static(__dirname+'/../..')); 13 | 14 | var port = process.env.HTTP_PORT || 8081; 15 | app.listen(port, function () { 16 | var host = (process.env.HTTP_HOST || this.address().address); 17 | 18 | console.log('Example app listening at http://%s:%s/test/', host, port); 19 | }); -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-facebook", 3 | "main": "ngFacebook.js", 4 | "version": "0.1.6", 5 | "homepage": "https://github.com/GoDisco/ngFacebook", 6 | "authors": [ 7 | "AlmogBaku " 8 | ], 9 | "description": "Angular service to handle facebook api", 10 | "keywords": [ 11 | "facebook", 12 | "facebook-api", 13 | "service", 14 | "angularjs", 15 | "angular", 16 | "ngFacebook", 17 | "api", 18 | "facebook-sdk", 19 | "sdk" 20 | ], 21 | "license": "MIT", 22 | "dependencies": { 23 | "angular": ">=1.0.0 <2.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | exports.config = { 2 | seleniumAddress: 'http://localhost:4444/wd/hub', 3 | baseUrl: 'http://localhost:'+(process.env.HTTP_PORT || 8081)+'/test/', 4 | framework: 'cucumber', 5 | specs: [ 6 | 'test/features/*.feature' 7 | ], 8 | cucumberOpts: { 9 | require: 'test/specs/*.js', 10 | format: 'pretty' 11 | }, 12 | sauceUser: process.env.SAUCE_USERNAME, 13 | sauceKey: process.env.SAUCE_ACCESS_KEY, 14 | capabilities: { 15 | 'browserName': (process.env.TEST_BROWSER_NAME || 'chrome'), 16 | 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, 17 | 'build': process.env.TRAVIS_BUILD_NUMBER, 18 | 'name': 'ngFacebook Tests' 19 | } 20 | }; 21 | 22 | if(process.env.TRAVIS_BUILD_NUMBER) { 23 | delete exports.config.seleniumAddress; 24 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | 5 | env: 6 | global: 7 | - secure: "CFH6k4N0JIjJ17qKdKDqjX45yOTcB6DY8wAHL/lDHneaIHeg0A6waHA1Ri6jjChiwsw7h8tSSYmqu+x2fdLNI4SxpVapcRhr8iunoWOIypHDJ0J8cpn4py3zs70g+RkRLXE++Prys/zj2AEvXftBQDlb0dRWf751y+TNFudC0vA=" 8 | - secure: "RNrtdx+CQecGkBWsaWGEr3IEsQsjXpVL/+lJfRnZYs5jQP7uE9sjWLZsBQsEGC9lFinmY+HoU0ucfxA9Kqe1Ts6itEP2lTPg2le/xRZRV6g0jCcvqc57l7WwIxhxQR74u2J3n+NhVT4FE7tvLx4jhkoCP0nIokOfsZF7+EY9W4k=" 9 | 10 | addons: 11 | sauce_connect: true 12 | 13 | install: 14 | - npm install 15 | - npm install protractor cucumber bower -g 16 | - npm install lodash 17 | - bower install 18 | 19 | script: 20 | - node test/scripts/web-server.js & 21 | - sleep 1 # give the server some time to get his things... drink coffee.. and such 22 | - protractor 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-facebook", 3 | "version": "0.1.6", 4 | "description": "Angular service to handle facebook api", 5 | "main": "ngFacebook.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/GoDisco/ngFacebook.git" 9 | }, 10 | "keywords": [ 11 | "facebook", 12 | "angularjs", 13 | "service", 14 | "ng-facebook", 15 | "ngFacebook" 16 | ], 17 | "author": "@AlmogBaku (by GoDisco)", 18 | "license": "MIT License", 19 | "bugs": { 20 | "url": "https://github.com/GoDisco/ngFacebook/issues" 21 | }, 22 | "homepage": "https://github.com/GoDisco/ngFacebook", 23 | "devDependencies": { 24 | "express": "~4.10.6", 25 | "chai": "~1.10.0", 26 | "chai-as-promised": "~4.1.1" 27 | }, 28 | "scripts": { 29 | "test": "protractor" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014, GoDisco 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 4 | 5 | *.iml 6 | 7 | ## Directory-based project format: 8 | .idea/ 9 | # if you remove the above rule, at least ignore the following: 10 | 11 | # User-specific stuff: 12 | # .idea/workspace.xml 13 | # .idea/tasks.xml 14 | # .idea/dictionaries 15 | 16 | # Sensitive or high-churn files: 17 | # .idea/dataSources.ids 18 | # .idea/dataSources.xml 19 | # .idea/sqlDataSources.xml 20 | # .idea/dynamic.xml 21 | # .idea/uiDesigner.xml 22 | 23 | # Gradle: 24 | # .idea/gradle.xml 25 | # .idea/libraries 26 | 27 | # Mongo Explorer plugin: 28 | # .idea/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.ipr 32 | *.iws 33 | 34 | ## Plugin-specific files: 35 | 36 | # IntelliJ 37 | out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Crashlytics plugin (for Android Studio and IntelliJ) 46 | com_crashlytics_export_strings.xml 47 | crashlytics.properties 48 | crashlytics-build.properties 49 | 50 | 51 | ### Yeoman template 52 | node_modules/ 53 | bower_components/ 54 | *.log 55 | 56 | build/ 57 | dist/ 58 | 59 | 60 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 15 |

ngFacebook tests

16 |
17 |

Login

18 | 22 | 23 | You are Logged in as {{user.first_name}} {{user.last_name}} 24 | 25 | 26 | You are not logged in. 27 | 28 |
29 |
30 |

Friends via cachedApi:

31 | 32 |
33 |

List of friends:

34 |
    35 |
  • {{friend.name}}
  • 36 |
37 |
38 |
39 | 40 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Authored by AlmogBaku 3 | * almog.baku@gmail.com 4 | * http://www.almogbaku.com/ 5 | * 6 | * 27/12/14 21:01 7 | */ 8 | 9 | angular.module('myApp', ['ngFacebook']) 10 | .config(['$facebookProvider', function($facebookProvider) { 11 | $facebookProvider.setAppId('764262530321266').setPermissions(['email','user_friends']); 12 | }]) 13 | .run(['$rootScope', '$window', function($rootScope, $window) { 14 | (function(d, s, id) { 15 | var js, fjs = d.getElementsByTagName(s)[0]; 16 | if (d.getElementById(id)) return; 17 | js = d.createElement(s); js.id = id; 18 | js.src = "//connect.facebook.net/en_US/sdk.js"; 19 | fjs.parentNode.insertBefore(js, fjs); 20 | }(document, 'script', 'facebook-jssdk')); 21 | $rootScope.$on('fb.load', function() { 22 | $window.dispatchEvent(new Event('fb.load')); 23 | }); 24 | }]) 25 | .controller('myCtrl', ['$scope', '$facebook', function($scope, $facebook) { 26 | $scope.$on('fb.auth.authResponseChange', function() { 27 | $scope.status = $facebook.isConnected(); 28 | if($scope.status) { 29 | $facebook.api('/me').then(function(user) { 30 | $scope.user = user; 31 | }); 32 | } 33 | }); 34 | 35 | $scope.loginToggle = function() { 36 | if($scope.status) { 37 | $facebook.logout(); 38 | } else { 39 | $facebook.login(); 40 | } 41 | }; 42 | 43 | $scope.getFriends = function() { 44 | if(!$scope.status) return; 45 | $facebook.cachedApi('/me/friends').then(function(friends) { 46 | $scope.friends = friends.data; 47 | }); 48 | } 49 | }]) 50 | ; -------------------------------------------------------------------------------- /test/specs/def.js: -------------------------------------------------------------------------------- 1 | // Use the external Chai As Promised to deal with resolving promises in expectations. 2 | var chai = require('chai'); 3 | var chaiAsPromised = require('chai-as-promised'); 4 | chai.use(chaiAsPromised); 5 | 6 | var expect = chai.expect; 7 | 8 | // Chai expect().to.exist syntax makes default jshint unhappy. 9 | // jshint expr:true 10 | 11 | module.exports = function() { 12 | this.Given('angular webpage with ngFacebook', function(next) { 13 | browser.get('index.html'); 14 | next(); 15 | }); 16 | this.Then('facebook sdk should be loaded', function(next) { 17 | var fbRoot = by.id('fb-root'); 18 | browser.wait(function() { 19 | return browser.driver.isElementPresent(fbRoot); 20 | }, 10000); 21 | browser.driver.isElementPresent(fbRoot).then(function(exists) { 22 | expect(exists).to.equal(true); 23 | }); 24 | next(); 25 | }); 26 | 27 | this.Given('an anonymous state', function(next) { 28 | browser.driver.executeScript(function() { 29 | window.addEventListener('fb.load', function () { 30 | window.FB.logout(); 31 | }); 32 | }).then(function() { 33 | setTimeout(function() { 34 | next(); 35 | }, 1000); 36 | }); 37 | }); 38 | this.When('I login with facebook user "$user" with password "$pass"', function(user, pass, next) { 39 | var parentWindow; 40 | element(by.id('login-btn')).click() 41 | .then(browser.getAllWindowHandles) 42 | .then(function(handles) { 43 | parentWindow = handles[0]; 44 | return browser.switchTo().window(handles[1]); 45 | }) 46 | .then(function() { 47 | browser.driver.findElement(by.id('email')).sendKeys(user); 48 | browser.driver.findElement(by.id('pass')).sendKeys(pass); 49 | return browser.driver.findElement(by.id('loginbutton')).click(); 50 | }) 51 | .then(browser.getAllWindowHandles) 52 | .then(function(handles){ 53 | var deferred = protractor.promise.defer(); 54 | 55 | if(handles.length===1) { 56 | deferred.fulfill(); 57 | } 58 | 59 | //wait for window to be ready 60 | setTimeout(function() { 61 | browser.driver.isElementPresent(by.id('platformDialogForm')).then(function (exists) { 62 | if (exists) { 63 | deferred.fulfill(browser.driver.findElement(by.css('button[name=__CONFIRM__]')).click()); 64 | } else { 65 | deferred.fulfill(); 66 | } 67 | }).thenCatch(deferred.fulfill); 68 | }, 500); 69 | 70 | return deferred.promise; 71 | }) 72 | .then(function() { 73 | return browser.switchTo().window(parentWindow); 74 | }) 75 | .then(function() { 76 | setTimeout(next, 1000); 77 | }); 78 | }); 79 | this.Then('I should be logged in', function(next) { 80 | element(by.id('login-btn')).getText().then(function(text) { 81 | expect(text).to.equal('Logout'); 82 | }); 83 | next(); 84 | }); 85 | this.Then('my name is "$fullname"', function(fullname, next) { 86 | element(by.css('.message')).getText().then(function(text) { 87 | expect(text).to.equal('You are Logged in as '+fullname); 88 | }); 89 | next(); 90 | }); 91 | 92 | this.When('I getting the list of my friends', function(next) { 93 | element(by.id('friends-btn')).click() 94 | .then(function() { 95 | setTimeout(next, 1000) 96 | }); 97 | }); 98 | this.Then('I should see "$friend" as a friend of mine', function(friend, next) { 99 | element(by.id('friend-list')).getText().then(function(text) { 100 | var friendlist = text.split('\n') 101 | expect(friendlist).to.contain(friend); 102 | }); 103 | next(); 104 | }); 105 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | This is no longer supported, please consider following [the official HOWTO tutorial](https://developers.facebook.com/docs/javascript/howto/angularjs/). 3 | 4 | Angular Facebook [![Build Status](https://travis-ci.org/GoDisco/ngFacebook.svg?branch=master)](https://travis-ci.org/GoDisco/ngFacebook) 5 | ================== 6 | Angular service to handle facebook 7 | 8 | Installation 9 | ------------ 10 | 1. Download the package: 11 | 1. download using npm: `npm install ng-facebook` 12 | 1. download using the [zip file](https://github.com/GoDisco/ngFacebook/archive/master.zip) 13 | 1. download using bower: `bower install ng-facebook` 14 | 1. Modify your application to include `ngFacebook` in your application dependencies 15 | 1. Configure the ngFacebook module using the configuration steps outlined in the section titled "Configuration" below. 16 | 1. Load the [*Facebook SDK for javascript*](https://developers.facebook.com/docs/reference/javascript/), **BUT DO NOT** call `FB.init` or set `window.fbAsyncInit`. These steps are automatically done by the ngFacebook module. 17 | 18 | Example: 19 | 20 | ```javascript 21 | angular.module('', ['ngFacebook']) 22 | 23 | .config( function( $facebookProvider ) { 24 | $facebookProvider.setAppId(''); 25 | }) 26 | 27 | .run( function( $rootScope ) { 28 | // Cut and paste the "Load the SDK" code from the facebook javascript sdk page. 29 | 30 | // Load the facebook SDK asynchronously 31 | (function(){ 32 | ... 33 | }()); 34 | }) 35 | 36 | ; 37 | 38 | var DemoCtrl = function ($scope, $facebook) { 39 | ... 40 | function refresh() { 41 | $facebook.api("/me").then( 42 | function(response) { 43 | $scope.welcomeMsg = "Welcome " + response.name; 44 | }, 45 | function(err) { 46 | $scope.welcomeMsg = "Please log in"; 47 | }); 48 | } 49 | }; 50 | 51 | ``` 52 | 53 | For more details check out this [plunker which uses ngFacebook](http://plnkr.co/edit/HcYBFKbqFcgQGhyCGQMw?p=preview). 54 | 55 | Configuration 56 | ----- 57 | You *must* configure your `facebook application ID` in your app, for example: 58 | 59 | app.config(function(FacebookProvider) { 60 | $facebookProvider.setAppId(11111111111); 61 | }); 62 | 63 | ### Additional configurations 64 | You can also configure the following properties. Both `set` and `get` methods are available for each property. 65 | 66 | 67 | 1. `permissions()` - permissions required by your app. 68 | 69 | Example: 70 | 71 | $facebookProvider.setPermissions("email,user_likes"); 72 | 73 | 1. `customInit()` - the parameters to pass to `FB.init()`. The 'appId' parameter is automatically specified using the value passed to '$facebookProvider.setAppId()', however the remaining parameters are configurable. 74 | 75 | Example to set: 76 | 77 | $facebookProvider.setCustomInit({ 78 | channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html', 79 | xfbml : true 80 | }); 81 | 82 | 1. `version()` - specify the version of the api (_2.0 by default_). 83 | 84 | Example to set: 85 | 86 | $facebookProvider.setVersion("v2.2"); 87 | 88 | 89 | Using 90 | ----- 91 | ### Methods 92 | 1. `$facebook.config(property)` - Return the config property. 93 | 1. `$facebook.getAuthResponse()` - Return the `AuthResponse`(assuming you already connected) 94 | 1. `$facebook.getLoginStatus()` - Return *promise* of the result. 95 | 1. `$facebook.login()` - Logged in to your app by facebook. Return *promise* of the result. 96 | 1. `$facebook.logout()` - Logged out from facebook. Return *promise* of the result. 97 | 1. `$facebook.ui(params)` - Do UI action(see facebook sdk docs). Return *promise* of the result. 98 | 1. `$facebook.api(args...)` - Do API action(see facebook sdk docs). Return *promise* of the result. 99 | 1. `$facebook.cachedApi(args...)` - Do API action(see above), but the result will cached. Return *promise* of the result. 100 | 1. `$facebook.setVersion(version)` - Set another SDK version 101 | 1. `$facebook.getVersion()` - Get current SDK version 102 | Example: 103 | 104 | app.controller('indexCtrl', function($scope, $facebook) { 105 | $scope.user=$facebook.cachedApi('/me'); 106 | }); 107 | 108 | ### Events 109 | The service will broadcast the facebook sdk events with the prefix `fb.`. 110 | 111 | In return you will get the next arguments to your `$on` handler: `event,response,FB` (`FB` is the facebook native js sdk). 112 | 113 | 1. `fb.auth.login` 114 | 1. `fb.auth.logout` 115 | 1. `fb.auth.prompt` 116 | 1. `fb.auth.sessionChange` 117 | 1. `fb.auth.statusChange` 118 | 1. `fb.auth.authResponseChange` 119 | 1. `fb.xfbml.render` 120 | 1. `fb.edge.create` 121 | 1. `fb.edge.remove` 122 | 1. `fb.comment.create` 123 | 1. `fb.comment.remove` 124 | 1. `fb.message.send` 125 | 126 | *For additional information about the events see the sdk docs.* 127 | 128 | License 129 | -------- 130 | This project is released over [MIT license](http://opensource.org/licenses/MIT "MIT License") 131 | 132 | 133 | Sponsors 134 | ------ 135 | Thanks to our sponsors for this project: 136 | 137 | 1. [GoDisco](http://www.godisco.net) 138 | 1. [JetBrains](http://www.jetbrains.com/) - for providing the great IDE [PhpStorm](http://www.jetbrains.com/phpstorm/) 139 | 140 | 141 | Authors 142 | ------- 143 | 144 | 1. [Almog Baku](http://www.AlmogBaku.com "AlmogBaku") - by [GoDisco](http://www.godisco.net) 145 | 1. [Amir Valiani](https://github.com/avaliani "Avaliani") 146 | 1. [Tal Gleichger](http://gleichger.com/ "talgleichger") - by [GoDisco](http://www.godisco.net) 147 | -------------------------------------------------------------------------------- /ngFacebook.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Angular Facebook service 3 | * --------------------------- 4 | * 5 | * Authored by AlmogBaku (GoDisco) 6 | * almog@GoDisco.net 7 | * http://www.GoDisco.net/ 8 | * 9 | * 9/8/13 10:25 PM 10 | */ 11 | 12 | angular.module('ngFacebook', []) 13 | .provider('$facebook', function() { 14 | var config = { 15 | permissions: 'email', 16 | appId: null, 17 | version: 'v2.0', 18 | customInit: {} 19 | }; 20 | 21 | this.setAppId = function(appId) { 22 | config.appId=appId; 23 | return this; 24 | }; 25 | this.getAppId = function() { 26 | return config.appId; 27 | }; 28 | this.setVersion = function(version) { 29 | config.version=version; 30 | return this; 31 | }; 32 | this.getVersion = function() { 33 | return config.version; 34 | }; 35 | this.setPermissions = function(permissions) { 36 | if(permissions instanceof Array) { 37 | permissions.join(','); 38 | } 39 | config.permissions=permissions; 40 | return this; 41 | }; 42 | this.getPermissions = function() { 43 | return config.permissions; 44 | }; 45 | this.setCustomInit = function(customInit) { 46 | if(angular.isDefined(customInit.appId)) { 47 | this.setAppId(customInit.appId); 48 | } 49 | config.customInit=customInit; 50 | return this; 51 | }; 52 | this.getCustomInit = function() { 53 | return config.customInit; 54 | }; 55 | 56 | this.$get = ['$q', '$rootScope', '$window', function($q, $rootScope, $window) { 57 | var $facebook=$q.defer(); 58 | $facebook.config = function(property) { 59 | return config[property]; 60 | }; 61 | 62 | //Initialization 63 | $facebook.init = function() { 64 | if($facebook.config('appId')==null) 65 | throw "$facebookProvider: `appId` cannot be null"; 66 | 67 | $window.FB.init( 68 | angular.extend({ appId: $facebook.config('appId'), version: $facebook.config('version') }, $facebook.config("customInit")) 69 | ); 70 | $rootScope.$broadcast("fb.load", $window.FB); 71 | }; 72 | 73 | $rootScope.$on("fb.load", function(e, FB) { 74 | $facebook.resolve(FB); 75 | 76 | //Define action events 77 | angular.forEach([ 78 | 'auth.login', 'auth.logout', 'auth.prompt', 79 | 'auth.sessionChange', 'auth.statusChange', 'auth.authResponseChange', 80 | 'xfbml.render', 'edge.create', 'edge.remove', 'comment.create', 81 | 'comment.remove', 'message.send' 82 | ],function(event) { 83 | FB.Event.subscribe(event, function(response) { 84 | $rootScope.$broadcast("fb."+event, response, FB); 85 | if(!$rootScope.$$phase) $rootScope.$apply(); 86 | }); 87 | }); 88 | 89 | // Make sure 'fb.auth.authResponseChange' fires even if the user is not logged in. 90 | $facebook.getLoginStatus(); 91 | $facebook.canvasSetAutoResize(); 92 | }); 93 | 94 | /** 95 | * Internal cache 96 | */ 97 | $facebook._cache={}; 98 | $facebook.setCache = function(attr,val) { 99 | $facebook._cache[attr]=val; 100 | }; 101 | $facebook.getCache = function(attr) { 102 | if(angular.isUndefined($facebook._cache[attr])) return false; 103 | return $facebook._cache[attr]; 104 | }; 105 | $facebook.clearCache = function() { 106 | $facebook._cache = {}; 107 | }; 108 | 109 | /** 110 | * Authentication 111 | */ 112 | 113 | var firstAuthResp=$q.defer(); 114 | var firstAuthRespReceived=false; 115 | function resolveFirstAuthResp(FB) { 116 | if (!firstAuthRespReceived) { 117 | firstAuthRespReceived=true; 118 | firstAuthResp.resolve(FB); 119 | } 120 | } 121 | 122 | $facebook.setCache("connected", null); 123 | $facebook.isConnected = function() { 124 | return $facebook.getCache("connected"); 125 | }; 126 | $rootScope.$on("fb.auth.authResponseChange", function(event, response, FB) { 127 | $facebook.clearCache(); 128 | 129 | if(response.status=="connected") { 130 | $facebook.setCache("connected", true); 131 | } else { 132 | $facebook.setCache("connected", false); 133 | } 134 | resolveFirstAuthResp(FB); 135 | }); 136 | 137 | $facebook.getAuthResponse = function () { 138 | return FB.getAuthResponse(); 139 | }; 140 | $facebook.getLoginStatus = function (force) { 141 | var deferred=$q.defer(); 142 | 143 | return $facebook.promise.then(function(FB) { 144 | FB.getLoginStatus(function(response) { 145 | if(response.error) deferred.reject(response.error); 146 | else { 147 | deferred.resolve(response); 148 | if($facebook.isConnected()==null) 149 | $rootScope.$broadcast("fb.auth.authResponseChange", response, FB); 150 | } 151 | if(!$rootScope.$$phase) $rootScope.$apply(); 152 | }, force); 153 | return deferred.promise; 154 | }); 155 | }; 156 | $facebook.login = function (permissions, rerequest) { 157 | if(permissions==undefined) permissions=$facebook.config("permissions"); 158 | var deferred=$q.defer(); 159 | 160 | var loginOptions = { scope: permissions }; 161 | if (rerequest) { 162 | loginOptions.auth_type = 'rerequest'; 163 | } 164 | 165 | return $facebook.promise.then(function(FB) { 166 | FB.login(function(response) { 167 | if(response.error) deferred.reject(response.error); 168 | else deferred.resolve(response); 169 | if(!$rootScope.$$phase) $rootScope.$apply(); 170 | }, loginOptions); 171 | return deferred.promise; 172 | }); 173 | }; 174 | $facebook.logout = function () { 175 | var deferred=$q.defer(); 176 | 177 | return $facebook.promise.then(function(FB) { 178 | FB.logout(function(response) { 179 | if(response.error) deferred.reject(response.error); 180 | else deferred.resolve(response); 181 | if(!$rootScope.$$phase) $rootScope.$apply(); 182 | }); 183 | return deferred.promise; 184 | }); 185 | }; 186 | $facebook.ui = function (params) { 187 | var deferred=$q.defer(); 188 | 189 | return $facebook.promise.then(function(FB) { 190 | FB.ui(params, function(response) { 191 | if(response && response.error_code) { 192 | deferred.reject(response.error_message); 193 | } else { 194 | deferred.resolve(response); 195 | } 196 | if(!$rootScope.$$phase) $rootScope.$apply(); 197 | }); 198 | return deferred.promise; 199 | }); 200 | }; 201 | $facebook.api = function () { 202 | var deferred=$q.defer(); 203 | var args=arguments; 204 | args[args.length++] = function(response) { 205 | if(response.error) deferred.reject(response.error); 206 | if(response.error_msg) deferred.reject(response); 207 | else deferred.resolve(response); 208 | if(!$rootScope.$$phase) $rootScope.$apply(); 209 | }; 210 | 211 | return firstAuthResp.promise.then(function(FB) { 212 | FB.api.apply(FB, args); 213 | return deferred.promise; 214 | }); 215 | }; 216 | 217 | /** 218 | * API cached request - cached request api with promise 219 | * 220 | * @param path 221 | * @returns $q.defer.promise 222 | */ 223 | $facebook.cachedApi = function() { 224 | if(typeof arguments[0] !== 'string') 225 | throw "$facebook.cacheApi can works only with graph requests!"; 226 | 227 | var promise = $facebook.getCache(arguments[0]); 228 | if(promise) return promise; 229 | 230 | var result = $facebook.api.apply($facebook, arguments); 231 | $facebook.setCache(arguments[0], result); 232 | 233 | return result; 234 | }; 235 | 236 | $facebook.canvasSetAutoGrow = function () { 237 | return FB.Canvas.setAutoGrow(); 238 | }; 239 | 240 | $facebook.canvasScrollTop = function (x,y) { 241 | return FB.Canvas.scrollTo(x,y); 242 | }; 243 | 244 | $facebook.canvasSetAutoResize = function () { 245 | setInterval(function() { 246 | if (!FB) 247 | return; 248 | var height = angular.element(document.querySelector('body'))[0].offsetHeight; 249 | return FB.Canvas.setSize({ height: height }); 250 | }, 500); 251 | }; 252 | 253 | return $facebook; 254 | }]; 255 | }) 256 | .run(['$rootScope', '$window', '$facebook', function($rootScope, $window, $facebook) { 257 | $window.fbAsyncInit = function() { 258 | $facebook.init(); 259 | if(!$rootScope.$$phase) $rootScope.$apply(); 260 | }; 261 | }]) 262 | ; 263 | --------------------------------------------------------------------------------