Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: Wizcorp/phonegap-facebook-plugin
...
head fork: felix-digitalkarma/phonegap-plugin-facebook-connect
compare: master
  • 1 commit
  • 98 files changed
  • 0 commit comments
  • 1 contributor
Showing with 23,896 additions and 0 deletions.
  1. +10 −0 example/FacebookandTwitter/.classpath
  2. +33 −0 example/FacebookandTwitter/.project
  3. +52 −0 example/FacebookandTwitter/AndroidManifest.xml
  4. +302 −0 example/FacebookandTwitter/android/src/org/apache/cordova/facebook/ConnectPlugin.java
  5. +57 −0 example/FacebookandTwitter/assets/www/README
  6. +58 −0 example/FacebookandTwitter/assets/www/cdv-plugin-fb-connect.js
  7. +4,987 −0 example/FacebookandTwitter/assets/www/cordova-1.6.1.js
  8. +420 −0 example/FacebookandTwitter/assets/www/css/style.css
  9. +14,638 −0 example/FacebookandTwitter/assets/www/facebook_js_sdk.js
  10. +18 −0 example/FacebookandTwitter/assets/www/hackbook.manifest
  11. BIN  example/FacebookandTwitter/assets/www/img/facebook_icon_large.png
  12. BIN  example/FacebookandTwitter/assets/www/img/facebook_icon_small.png
  13. BIN  example/FacebookandTwitter/assets/www/img/iphone_icon.png
  14. BIN  example/FacebookandTwitter/assets/www/img/iphone_splash.png
  15. BIN  example/FacebookandTwitter/assets/www/img/iphone_splash_retina_display.png
  16. BIN  example/FacebookandTwitter/assets/www/img/loader.gif
  17. +328 −0 example/FacebookandTwitter/assets/www/index.html
  18. +29 −0 example/FacebookandTwitter/assets/www/js/_config.js
  19. +82 −0 example/FacebookandTwitter/assets/www/js/auth.js
  20. +24 −0 example/FacebookandTwitter/assets/www/js/credits.js
  21. +46 −0 example/FacebookandTwitter/assets/www/js/feed.js
  22. +224 −0 example/FacebookandTwitter/assets/www/js/graph_api.js
  23. +55 −0 example/FacebookandTwitter/assets/www/js/requests.js
  24. +78 −0 example/FacebookandTwitter/assets/www/js/ui.js
  25. +58 −0 example/FacebookandTwitter/assets/www/pg-plugin-fb-connect.js
  26. BIN  example/FacebookandTwitter/bin/FacebookandTwitter.apk
  27. BIN  example/FacebookandTwitter/bin/classes.dex
  28. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/AsyncFacebookRunner$1.class
  29. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/AsyncFacebookRunner$2.class
  30. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/AsyncFacebookRunner$RequestListener.class
  31. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/AsyncFacebookRunner.class
  32. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/DialogError.class
  33. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/Facebook$1.class
  34. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/Facebook$DialogListener.class
  35. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/Facebook$ServiceListener.class
  36. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/Facebook$TokenRefreshServiceConnection$1.class
  37. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/Facebook$TokenRefreshServiceConnection.class
  38. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/Facebook.class
  39. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/FacebookError.class
  40. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/FbDialog$1.class
  41. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/FbDialog$FbWebViewClient.class
  42. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/FbDialog.class
  43. BIN  example/FacebookandTwitter/bin/classes/com/facebook/android/Util.class
  44. BIN  example/FacebookandTwitter/bin/classes/me/felixmontanez/fbandtwitter/BuildConfig.class
  45. BIN  example/FacebookandTwitter/bin/classes/me/felixmontanez/fbandtwitter/FacebookandTwitterActivity.class
  46. BIN  example/FacebookandTwitter/bin/classes/me/felixmontanez/fbandtwitter/R$attr.class
  47. BIN  example/FacebookandTwitter/bin/classes/me/felixmontanez/fbandtwitter/R$drawable.class
  48. BIN  example/FacebookandTwitter/bin/classes/me/felixmontanez/fbandtwitter/R$layout.class
  49. BIN  example/FacebookandTwitter/bin/classes/me/felixmontanez/fbandtwitter/R$string.class
  50. BIN  example/FacebookandTwitter/bin/classes/me/felixmontanez/fbandtwitter/R$xml.class
  51. BIN  example/FacebookandTwitter/bin/classes/me/felixmontanez/fbandtwitter/R.class
  52. BIN  example/FacebookandTwitter/bin/classes/org/apache/cordova/facebook/ConnectPlugin$1.class
  53. BIN  example/FacebookandTwitter/bin/classes/org/apache/cordova/facebook/ConnectPlugin$2.class
  54. BIN  example/FacebookandTwitter/bin/classes/org/apache/cordova/facebook/ConnectPlugin$AuthorizeListener.class
  55. BIN  example/FacebookandTwitter/bin/classes/org/apache/cordova/facebook/ConnectPlugin$UIDialogListener.class
  56. BIN  example/FacebookandTwitter/bin/classes/org/apache/cordova/facebook/ConnectPlugin.class
  57. +3 −0  example/FacebookandTwitter/bin/jarlist.cache
  58. BIN  example/FacebookandTwitter/bin/res/drawable-hdpi/close.png
  59. BIN  example/FacebookandTwitter/bin/res/drawable-hdpi/facebook_icon.png
  60. BIN  example/FacebookandTwitter/bin/res/drawable-hdpi/ic_launcher.png
  61. BIN  example/FacebookandTwitter/bin/res/drawable-ldpi/close.png
  62. BIN  example/FacebookandTwitter/bin/res/drawable-ldpi/facebook_icon.png
  63. BIN  example/FacebookandTwitter/bin/res/drawable-ldpi/ic_launcher.png
  64. BIN  example/FacebookandTwitter/bin/res/drawable-mdpi/ic_launcher.png
  65. BIN  example/FacebookandTwitter/bin/res/drawable-xhdpi/close.png
  66. BIN  example/FacebookandTwitter/bin/res/drawable-xhdpi/ic_launcher.png
  67. BIN  example/FacebookandTwitter/bin/res/drawable/close.png
  68. BIN  example/FacebookandTwitter/bin/res/drawable/facebook_icon.png
  69. BIN  example/FacebookandTwitter/bin/resources.ap_
  70. +6 −0 example/FacebookandTwitter/gen/me/felixmontanez/fbandtwitter/BuildConfig.java
  71. +29 −0 example/FacebookandTwitter/gen/me/felixmontanez/fbandtwitter/R.java
  72. BIN  example/FacebookandTwitter/libs/cordova-1.6.1.jar
  73. BIN  example/FacebookandTwitter/libs/facebook-android-sdk.jar
  74. +20 −0 example/FacebookandTwitter/proguard-project.txt
  75. +14 −0 example/FacebookandTwitter/project.properties
  76. BIN  example/FacebookandTwitter/res/drawable-hdpi/close.png
  77. BIN  example/FacebookandTwitter/res/drawable-hdpi/facebook_icon.png
  78. BIN  example/FacebookandTwitter/res/drawable-hdpi/ic_launcher.png
  79. BIN  example/FacebookandTwitter/res/drawable-ldpi/close.png
  80. BIN  example/FacebookandTwitter/res/drawable-ldpi/facebook_icon.png
  81. BIN  example/FacebookandTwitter/res/drawable-ldpi/ic_launcher.png
  82. BIN  example/FacebookandTwitter/res/drawable-mdpi/ic_launcher.png
  83. BIN  example/FacebookandTwitter/res/drawable-xhdpi/close.png
  84. BIN  example/FacebookandTwitter/res/drawable-xhdpi/ic_launcher.png
  85. BIN  example/FacebookandTwitter/res/drawable/close.png
  86. BIN  example/FacebookandTwitter/res/drawable/facebook_icon.png
  87. +12 −0 example/FacebookandTwitter/res/layout/main.xml
  88. +7 −0 example/FacebookandTwitter/res/values/strings.xml
  89. +37 −0 example/FacebookandTwitter/res/xml/cordova.xml
  90. +38 −0 example/FacebookandTwitter/res/xml/plugins.xml
  91. +316 −0 example/FacebookandTwitter/src/com/facebook/android/AsyncFacebookRunner.java
  92. +51 −0 example/FacebookandTwitter/src/com/facebook/android/DialogError.java
  93. +978 −0 example/FacebookandTwitter/src/com/facebook/android/Facebook.java
  94. +50 −0 example/FacebookandTwitter/src/com/facebook/android/FacebookError.java
  95. +195 −0 example/FacebookandTwitter/src/com/facebook/android/FbDialog.java
  96. +329 −0 example/FacebookandTwitter/src/com/facebook/android/Util.java
  97. +13 −0 example/FacebookandTwitter/src/me/felixmontanez/fbandtwitter/FacebookandTwitterActivity.java
  98. +299 −0 example/FacebookandTwitter/src/org/apache/cordova/facebook/ConnectPlugin.java
10 example/FacebookandTwitter/.classpath
View
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="lib" path="libs/facebook-android-sdk.jar"/>
+ <classpathentry kind="lib" path="libs/cordova-1.6.1.jar"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
33 example/FacebookandTwitter/.project
View
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>FacebookandTwitter</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
52 example/FacebookandTwitter/AndroidManifest.xml
View
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="me.felixmontanez.fbandtwitter"
+ android:versionCode="1"
+ android:versionName="1.0" >
+<supports-screens
+android:largeScreens="true"
+android:normalScreens="true"
+android:smallScreens="true"
+android:resizeable="true"
+android:anyDensity="true"
+/>
+<uses-permission android:name="android.permission.CAMERA" />
+<uses-permission android:name="android.permission.VIBRATE" />
+<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
+<uses-permission android:name="android.permission.READ_PHONE_STATE" />
+<uses-permission android:name="android.permission.INTERNET" />
+<uses-permission android:name="android.permission.RECEIVE_SMS" />
+<uses-permission android:name="android.permission.RECORD_AUDIO" />
+<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+<uses-permission android:name="android.permission.READ_CONTACTS" />
+<uses-permission android:name="android.permission.WRITE_CONTACTS" />
+<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+<uses-permission android:name="android.permission.BROADCAST_STICKY" />
+ <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="10"/>
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".FacebookandTwitterActivity"
+ android:label="@string/app_name"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="org.apache.cordova.DroidGap"
+ android:label="@string/app_name"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter> </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
302 example/FacebookandTwitter/android/src/org/apache/cordova/facebook/ConnectPlugin.java
View
@@ -0,0 +1,302 @@
+package org.apache.cordova.facebook;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Iterator;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.*;
+
+import com.facebook.android.DialogError;
+import com.facebook.android.Facebook;
+import com.facebook.android.Facebook.DialogListener;
+import com.facebook.android.FacebookError;
+import org.apache.cordova.api.Plugin;
+import org.apache.cordova.api.PluginResult;
+
+public class ConnectPlugin extends Plugin {
+
+ public static final String SINGLE_SIGN_ON_DISABLED = "service_disabled";
+ private final String TAG = "ConnectPlugin";
+
+ private Facebook facebook;
+ private String userId;
+ //used for dialog auth
+ private String[] permissions = new String[] {};
+ private String callbackId;
+ private Bundle paramBundle;
+ private String method;
+
+ @Override
+ public PluginResult execute(String action, JSONArray args, final String callbackId) {
+ PluginResult pr = new PluginResult(PluginResult.Status.NO_RESULT);
+ pr.setKeepCallback(true);
+
+ if (action.equals("init")) {
+ try {
+ String appId = args.getString(0);
+
+ facebook = new Facebook(appId);
+
+ Log.d(TAG, "init: Initializing plugin.");
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this.ctx.getContext());
+ String access_token = prefs.getString("access_token", null);
+ Long expires = prefs.getLong("access_expires", -1);
+
+ if (access_token != null && expires != -1) {
+ this.facebook.setAccessToken(access_token);
+ this.facebook.setAccessExpires(expires);
+ try {
+ JSONObject o = new JSONObject(this.facebook.request("/me"));
+ this.userId = o.getString("id");
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ if(facebook.isSessionValid() && this.userId != null) {
+ return new PluginResult(PluginResult.Status.OK, this.getResponse());
+ }
+ else {
+ return new PluginResult(PluginResult.Status.NO_RESULT);
+ }
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return new PluginResult(PluginResult.Status.ERROR, "Invalid JSON args used. expected a string as the first arg.");
+ }
+ }
+
+ else if (action.equals("login")) {
+ if (facebook != null) {
+ final ConnectPlugin me = this;
+ String[] permissions = new String[args.length()];
+ try {
+ for (int i=0; i<args.length(); i++) {
+ permissions[i] = args.getString(i);
+ }
+ } catch (JSONException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ return new PluginResult(PluginResult.Status.ERROR, "Invalid JSON args used. Expected a string array of permissions.");
+ }
+
+ this.ctx.setActivityResultCallback(this);
+ this.permissions = permissions;
+ this.callbackId = callbackId;
+ Runnable runnable = new Runnable() {
+ public void run() {
+ me.facebook.authorize((Activity)me.ctx, me.permissions, new AuthorizeListener(me));
+ };
+ };
+ this.ctx.runOnUiThread(runnable);
+ } else {
+ pr = new PluginResult(PluginResult.Status.ERROR, "Must call init before login.");
+ }
+ }
+
+ else if (action.equals("logout")) {
+ if (facebook != null) {
+ try {
+ facebook.logout(this.ctx.getContext());
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this.ctx.getContext());
+ prefs.edit().putLong("access_expires", -1).commit();
+ prefs.edit().putString("access_token", null).commit();
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ pr = new PluginResult(PluginResult.Status.MALFORMED_URL_EXCEPTION, "Error logging out.");
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ pr = new PluginResult(PluginResult.Status.IO_EXCEPTION, "Error logging out.");
+ }
+ pr = new PluginResult(PluginResult.Status.OK, getResponse());
+ } else {
+ pr = new PluginResult(PluginResult.Status.ERROR, "Must call init before logout.");
+ }
+ }
+
+ else if (action.equals("getLoginStatus")) {
+ if (facebook != null) {
+ pr = new PluginResult(PluginResult.Status.OK, getResponse());
+ } else {
+ pr = new PluginResult(PluginResult.Status.ERROR, "Must call init before getLoginStatus.");
+ }
+ }
+
+ else if (action.equals("showDialog")) {
+ if (facebook != null) {
+ Bundle collect = new Bundle();
+ JSONObject params = null;
+ try {
+ params = args.getJSONObject(0);
+ } catch (JSONException e) {
+ params = new JSONObject();
+ }
+
+ final ConnectPlugin me = this;
+ Iterator<?> iter = params.keys();
+ while (iter.hasNext()) {
+ String key = (String) iter.next();
+ if (key.equals("method")) {
+ try {
+ this.method = params.getString(key);
+ } catch (JSONException e) {
+ Log.w(TAG, "Nonstring method parameter provided to dialog");
+ }
+ } else {
+ try {
+ collect.putString(key, params.getString(key));
+ } catch (JSONException e) {
+ // Need to handle JSON parameters
+ Log.w(TAG, "Nonstring parameter provided to dialog discarded");
+ }
+ }
+ }
+ this.paramBundle = new Bundle(collect);
+ Runnable runnable = new Runnable() {
+ public void run() {
+ me.facebook.dialog (me.ctx.getContext(), me.method , me.paramBundle , new UIDialogListener(me));
+ };
+ };
+ this.ctx.runOnUiThread(runnable);
+ } else {
+ pr = new PluginResult(PluginResult.Status.ERROR, "Must call init before showDialog.");
+ }
+
+ }
+
+ return pr;
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ facebook.authorizeCallback(requestCode, resultCode, data);
+ }
+
+ public JSONObject getResponse() {
+ String response = "{"+
+ "\"status\": \""+(facebook.isSessionValid() ? "connected" : "unknown")+"\","+
+ "\"authResponse\": {"+
+ "\"accessToken\": \""+facebook.getAccessToken()+"\","+
+ "\"expiresIn\": \""+facebook.getAccessExpires()+"\","+
+ "\"session_key\": true,"+
+ "\"sig\": \"...\","+
+ "\"userId\": \""+this.userId+"\""+
+ "}"+
+ "}";
+
+ try {
+ return new JSONObject(response);
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return new JSONObject();
+ }
+
+ class UIDialogListener implements DialogListener {
+ final ConnectPlugin fba;
+
+ public UIDialogListener(ConnectPlugin fba){
+ super();
+ this.fba = fba;
+ }
+
+ public void onComplete(Bundle values) {
+ // Handle a successful dialog
+ Log.d(TAG,values.toString());
+ this.fba.success(new PluginResult(PluginResult.Status.OK), this.fba.callbackId);
+ }
+
+ public void onFacebookError(FacebookError e) {
+ Log.d(TAG, "facebook error");
+ this.fba.error("Facebook error: " + e.getMessage(), callbackId);
+ }
+
+ public void onError(DialogError e) {
+ Log.d(TAG, "other error");
+ this.fba.error("Dialog error: " + e.getMessage(), this.fba.callbackId);
+ }
+
+ public void onCancel() {
+ Log.d(TAG, "cancel");
+ this.fba.error("Cancelled", this.fba.callbackId);
+ }
+ }
+
+ class AuthorizeListener implements DialogListener {
+ final ConnectPlugin fba;
+
+ public AuthorizeListener(ConnectPlugin fba){
+ super();
+ this.fba = fba;
+ }
+
+ public void onComplete(Bundle values) {
+ // Handle a successful login
+
+ String token = this.fba.facebook.getAccessToken();
+ long token_expires = this.fba.facebook.getAccessExpires();
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this.fba.ctx.getContext());
+ prefs.edit().putLong("access_expires", token_expires).commit();
+ prefs.edit().putString("access_token", token).commit();
+
+ Log.d(TAG, "authorized");
+ Log.d(TAG, values.toString());
+
+ try {
+ JSONObject o = new JSONObject(this.fba.facebook.request("/me"));
+ this.fba.userId = o.getString("id");
+ this.fba.success(getResponse(), this.fba.callbackId);
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public void onFacebookError(FacebookError e) {
+ Log.d(TAG, "facebook error");
+ this.fba.error("Facebook error: " + e.getMessage(), callbackId);
+ }
+
+ public void onError(DialogError e) {
+ Log.d(TAG, "other error");
+ this.fba.error("Dialog error: " + e.getMessage(), this.fba.callbackId);
+ }
+
+ public void onCancel() {
+ Log.d(TAG, "cancel");
+ this.fba.error("Cancelled", this.fba.callbackId);
+ }
+ }
+}
+
57 example/FacebookandTwitter/assets/www/README
View
@@ -0,0 +1,57 @@
+--------
+LICENSE
+--------
+Copyright 2010 Facebook, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may
+not use this file except in compliance with the License. You may obtain
+a copy of the License at
+
+ http:www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations
+under the License.
+
+
+--------
+LIVE DEMO
+--------
+http://www.fb.me/fbhackbook
+
+
+--------
+INSTALLING
+--------
+- Create Facebook application at http://developers.facebook.com/apps and set Application Settings
+- Change gAppID in js/_config.js
+- In all files, replace "http://apps.facebook.com/mobile-start/" with the Canvas URL you entered in Application Settings
+- In all files, replace "http://www.facebookmobileweb.com/hackbook/" with the Canvas URL you entered in Application Settings
+- Upload files to your server
+- Visit the URL where you uploaded the files
+
+Note: Credits will not work out of the box since it requires server-side integration. See the docs at https://developers.facebook.com/docs/creditsapi/ for a tutorial that describes setting up Credits.
+
+
+--------
+DOCUMENTATION
+--------
+All documentation is at https://developers.facebook.com/docs/mobile/web/build/
+
+
+--------
+RESOURCES
+--------
+- There are a large amount of comments in the HTML and Javascript files. It's highly recommended that you poke around those files.
+- console.log() (http://getfirebug.com/logging) statements are scattered throughought all of the example. You can view these in Firebug, iPhone Safari, Android, Chrome, etc. See below for more info.
+- Debugging in iPhone Safari: http://developer.apple.com/library/safari/#documentation/appleapplications/Conceptual/Safari_Developer_Guide/DebuggingYourWebsite/DebuggingYourWebsite.html
+- Debugging in Android Web Browser: http://developer.android.com/guide/webapps/debugging.html
+- Debugging in Chrome: http://www.google.com/chrome/intl/en/webmasters-faq.html#testrender
+- Debugging in Safari (desktop): http://mactips.info/2010/07/use-safari-5s-web-inspector
+- Debugging in Firefox: http://getfirebug.com/
+- Debuging in Internet Exploer: http://msdn.microsoft.com/en-us/library/dd565628(v=vs.85).aspx
+- Debugging devices remotely : http://pmuellr.github.com/weinre/
+- File bugs at http://bugs.developers.facebook.net/
+- See the health of Facebook Platform at https://developers.facebook.com/live_status
58 example/FacebookandTwitter/assets/www/cdv-plugin-fb-connect.js
View
@@ -0,0 +1,58 @@
+CDV = ( typeof CDV == 'undefined' ? {} : CDV );
+var cordova = window.cordova || window.Cordova;
+CDV.FB = {
+ init: function(apiKey, fail) {
+ // create the fb-root element if it doesn't exist
+ if (!document.getElementById('fb-root')) {
+ var elem = document.createElement('div');
+ elem.id = 'fb-root';
+ document.body.appendChild(elem);
+ }
+ cordova.exec(function() {
+ var authResponse = JSON.parse(localStorage.getItem('cdv_fb_session') || '{"expiresIn":0}');
+ if (authResponse && authResponse.expirationTime) {
+ var nowTime = (new Date()).getTime();
+ if (authResponse.expirationTime > nowTime) {
+ // Update expires in information
+ updatedExpiresIn = Math.floor((authResponse.expirationTime - nowTime) / 1000);
+ authResponse.expiresIn = updatedExpiresIn;
+
+ localStorage.setItem('cdv_fb_session', JSON.stringify(authResponse));
+ FB.Auth.setAuthResponse(authResponse, 'connected');
+ }
+ }
+ console.log('Cordova Facebook Connect plugin initialized successfully.');
+ }, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'init', [apiKey]);
+ },
+ login: function(params, cb, fail) {
+ params = params || { scope: '' };
+ cordova.exec(function(e) { // login
+ if (e.authResponse && e.authResponse.expiresIn) {
+ var expirationTime = e.authResponse.expiresIn === 0
+ ? 0
+ : (new Date()).getTime() + e.authResponse.expiresIn * 1000;
+ e.authResponse.expirationTime = expirationTime;
+ }
+ localStorage.setItem('cdv_fb_session', JSON.stringify(e.authResponse));
+ FB.Auth.setAuthResponse(e.authResponse, 'connected');
+ if (cb) cb(e);
+ }, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'login', params.scope.split(',') );
+ },
+ logout: function(cb, fail) {
+ cordova.exec(function(e) {
+ localStorage.removeItem('cdv_fb_session');
+ FB.Auth.setAuthResponse(null, 'notConnected');
+ if (cb) cb(e);
+ }, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'logout', []);
+ },
+ getLoginStatus: function(cb, fail) {
+ cordova.exec(function(e) {
+ if (cb) cb(e);
+ }, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'getLoginStatus', []);
+ },
+ dialog: function(params, cb, fail) {
+ cordova.exec(function(e) { // login
+ if (cb) cb(e);
+ }, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'showDialog', [params] );
+ }
+};
4,987 example/FacebookandTwitter/assets/www/cordova-1.6.1.js
View
4,987 additions, 0 deletions not shown
420 example/FacebookandTwitter/assets/www/css/style.css
View
@@ -0,0 +1,420 @@
+html, body, form, fieldset, p, div, h1, h2, h3, h4, h5, h6 {
+ -webkit-text-size-adjust:none;
+}
+
+body {
+ background-color: #fff;
+ font: 12px Arial;
+ margin: 0px;
+ padding: 0px;
+ color: #323232;
+}
+
+body.connected .show_when_not_connected {
+ display: none;
+}
+
+body.connected .show_when_connected {
+ display: block;
+}
+
+body.not_connected .show_when_not_connected {
+ display: block;
+}
+
+body.not_connected .show_when_connected {
+ display: none;
+}
+
+body.permissioned .show_when_not_connected {
+ display: none;
+}
+
+body.not_permissioned .show_when_not_connected {
+ display: none;
+}
+
+body.permissioned #extended_permission_button {
+ display: none;
+}
+
+body.not_permissioned #extended_permission_button {
+ display: block;
+}
+
+#action {
+ display: none;
+ position: fixed;
+ background-color: #fff;
+ opacity: 0.9;
+ filter: alpha(opacity=90);
+ font-size: 1.5em;
+ font-weight: bold;
+ width: 100%;
+ height: 1250px;
+ text-align: center;
+ color: #323232;
+ padding-top: 100px;
+ z-index: 99;
+}
+
+#action #msg {
+ position: relative;
+ margin: 0px auto;
+}
+
+#action #loading-icon {
+ background: url('../img/loader.gif');
+ position: relative;
+ margin: 0px auto;
+ width: 16px;
+ height: 11px;
+ margin-bottom: 15px;
+}
+
+#header {
+ position: fixed;
+ font-size: 1.2em;
+ width: 100%;
+ height: 44px;
+ text-align: center;
+ color: #fff;
+ background-color: #3b5998;
+ border-bottom: 2px solid #1d4088;
+ z-index: 99;
+}
+
+#header a {
+ color: #fff;
+ font-weight:bold;
+ text-decoration: none;
+}
+
+#header #back {
+ width: 80px;
+ height: 29px;
+ clear: none;
+ border-right: 1px solid #1d4088;
+ padding-top: 15px;
+ font-weight: bold;
+ background-color: #627aad;
+ }
+
+ #header #back-link {
+ position: absolute;
+ left: 0;
+ width: 81px;
+ height: 44px;
+ }
+
+ #header #title {
+ margin: auto;
+ height: 25px;
+ text-align: center;
+ line-height: 2.7em;
+ font-weight: bold;
+ color: #fff;
+ display: inline;
+ font-size: 1.2em;
+ }
+
+ #header #right-block {
+ position: absolute;
+ right: 0px;
+ top: 0;
+ margin: 11px;
+ }
+
+#main-desc {
+ background-color: #f2f2f2;
+ padding: 10px;
+ border-bottom: 2px solid #e9e9e9;
+ position: relative;
+ margin: 0px auto;
+ width: 90%;
+ margin-bottom: 10px;
+}
+
+.section {
+ float: left;
+ clear: both;
+ margin: 10px 0px 10px 0px;
+ border-bottom: 2px solid #e9e9e9;
+ padding-bottom: 10px;
+ width: 100%;
+}
+
+.section h1 {
+ margin-left: 10px;
+}
+
+.section p {
+ margin-left: 10px;
+}
+
+.button {
+ width: 100%;
+ font-size: 1.2em;
+ background-color: #f6f6f6;
+ margin-bottom: 10px;
+ border-bottom: 1px solid #9f9f9f;
+ border-right: 1px solid #9f9f9f;
+ text-align: center;
+ padding: 10px 0 10px;
+ color: #323232;
+ -moz-border-radius: 6px;
+ -webkit-border-radius: 6px;
+ font-weight:bold;
+ text-decoration: none;
+ width: 100%;
+ -moz-box-shadow: 0 1px 7px #9f9f9f;
+ -webkit-box-shadow: 0 1px 7px #9f9f9f;
+ cursor: pointer;
+ position: relative;
+ margin: 0px auto;
+ width: 95%;
+ margin-bottom: 10px;
+}
+
+#content {
+ float: left;
+ width: 100%;
+}
+
+h1 {
+ font-size: 1.3em;
+ }
+
+ #footer {
+ float: right;
+ clear: right;
+ font-size: 1.1em;
+ width: 100%;
+ height: 35px;
+ background-color: #f2f2f2;
+ margin-top: 10px;
+ border-top: 1px solid #e9e9e9;
+ text-align: center;
+ padding:10px 0px 10px 0px;
+}
+
+#footer a {
+ color: #535353;
+ text-decoration: none;
+ font-weight: bold;
+}
+
+.menu-item {
+ float: left;
+ clear: both;
+ font-size: 1.2em;
+ width: 100%;
+ height: 30px;
+ background-color: #f6f6f6;
+ margin-bottom: 10px;
+ border-bottom: 1px solid #9f9f9f;
+ border-right: 1px solid #9f9f9f;
+ text-align: center;
+ padding-top: 15px;
+ color: #323232;
+ -moz-border-radius: 6px;
+ -webkit-border-radius: 6px;
+ font-weight:bold;
+ text-decoration: none;
+ width: 100%;
+ height: 30px;
+ -moz-box-shadow: 0 1px 7px #9f9f9f;
+ -webkit-box-shadow: 0 1px 7px #9f9f9f;
+ cursor: pointer;
+}
+
+#welcome {
+ float: left;
+ clear: both;
+ font-size: 1.9em;
+ text-align: center;
+ width: 100%;
+ height: 70px;
+}
+#welcome span {
+ font-size: .7em;
+ text-align: right;
+ width: 100%;
+}
+
+#user-picture {
+ width: 45px;
+ height: 45px;
+}
+
+#navigation-header {
+ float: left;
+ clear: both;
+ height: 40px;
+ width: 100%;
+ text-align: center;
+}
+
+
+body.permissioned .show_when_not_permissioned {
+ display: none;
+}
+
+body .show_when_not_permissioned {
+ display: none;
+}
+
+body .show_when_permissioned {
+ display: block;
+}
+
+body.permissioned .show_when_permissioned {
+ display: block;
+}
+
+body.not_permissioned .show_when_not_permissioned {
+ display: block;
+}
+
+body.not_permissioned .show_when_permissioned {
+ display: none;
+}
+
+body.not_connected .show_when_not_permissioned {
+ display: block;
+}
+
+body.not_connected .show_when_permissioned {
+ display: none;
+}
+
+#fb-content {
+ margin-top: 10px;
+}
+
+ul {
+ list-style-type: none;
+ padding: 0;
+ width: 95%;
+ margin: auto;
+ margin-top: 15px;
+}
+
+.page {
+ float: left;
+ clear: both;
+ width: 100%;
+ margin-top: 55px;
+}
+
+.login-button {
+ background:url(https://s-static.ak.fbcdn.net/images/connect_sprite.png) no-repeat scroll left -188px #29447e;
+ display:inline-block;
+ line-height:14px;
+ outline:medium none;
+ padding:0 0 0 1px
+}
+
+.login-button span {
+ background:url(https://s-static.ak.fbcdn.net/images/connect_sprite.png) repeat scroll 0 0 #5f78ab;
+ border-bottom:1px solid #1a356e;
+ border-top:1px solid #879ac0;
+ color:#fff;
+ cursor:pointer;
+ display:block;
+ font-size:11px;
+ font-weight:bold;
+ margin:1px 1px 0 21px;
+ padding:2px 6px 3px;
+ font-family: 'Lucida Grande', Verdana, Arial, sans-serif;
+}
+
+#user-friends {
+ margin: 0px 0px 20px 30px;
+}
+
+#user-friends img {
+ width: 32px;
+ height: 32px;
+ margin-right: 5px;
+}
+
+#checkins {
+ margin: 0px 0px 20px 30px;
+}
+
+#locations-nearby {
+ margin: 0px 0px 20px 30px;
+}
+
+#user-info {
+ margin: 0px 0px 20px 30px;
+}
+
+.place {
+ float: left;
+ clear: both;
+}
+
+.place .picture {
+ float: left;
+ clear: none;
+ margin: 2px;
+}
+
+.place .info {
+ float: left;
+ clear: none;
+}
+
+.place .name {
+ float: left;
+ clear: both;
+ margin: 5px;
+}
+
+.place .check-in-button {
+ float: left;
+ clear: both;
+}
+
+body.not_connected .button-requires-connect {
+ display: none;
+}
+
+.info-requires-connect {
+ font-weight: bold;
+ margin: 10px 0px 15px 10px;
+}
+
+body.connected .info-requires-connect {
+ display: none;
+}
+
+body.not_permissioned .info-requires-connect {
+ display: none;
+}
+
+body.permissioned .info-requires-connect {
+ display: none;
+}
+
+.place .check-in-msg {
+ float: left;
+ clear: both;
+ margin: 3px 0px 0px 5px;
+ font-style: italic;
+}
+
+.data-header {
+ margin-bottom: 10px;
+ font-weight: bold;
+}
+
+#like-button {
+ float: left;
+ clear: both;
+ width: 90%;
+ margin: 10px 0px 35px 15px;
+ overflow: hidden;
+}
14,638 example/FacebookandTwitter/assets/www/facebook_js_sdk.js
View
14,638 additions, 0 deletions not shown
18 example/FacebookandTwitter/assets/www/hackbook.manifest
View
@@ -0,0 +1,18 @@
+CACHE MANIFEST
+# 2011-10-10:v6
+
+# Explicitly cached entries
+index.html
+css/style.css
+img/facebook_icon_large.png
+img/facebook_icon_small.png
+img/iphone_icon.png
+img/iphone_splash.png
+js/_config.js
+js/auth.js
+js/feed.js
+js/graph_api.js
+js/requests.js
+
+NETWORK:
+*
BIN  example/FacebookandTwitter/assets/www/img/facebook_icon_large.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  example/FacebookandTwitter/assets/www/img/facebook_icon_small.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  example/FacebookandTwitter/assets/www/img/iphone_icon.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  example/FacebookandTwitter/assets/www/img/iphone_splash.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  example/FacebookandTwitter/assets/www/img/iphone_splash_retina_display.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  example/FacebookandTwitter/assets/www/img/loader.gif
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
328 example/FacebookandTwitter/assets/www/index.html
View
@@ -0,0 +1,328 @@
+<html xmlns:og="http://ogp.me/ns" xmlns:fb="http://www.facebook.com/2008/fbml" lang="en" manifest="hackbook.manifest">
+<head>
+ <title>Hackbook</title>
+ <!-- See https://developers.facebook.com/docs/opengraph/ -->
+ <meta property="og:title" content="Hackbook for Mobile Web" />
+ <meta property="og:type" content="website" />
+ <meta property="og:url" content="http://apps.facebook.com/mobile-start/" />
+ <meta property="og:site_name" content="Hackbook for Mobile Web" />
+ <meta property="og:image" content="http://www.facebookmobileweb.com/hackbook/img/facebook_icon_large.png"/>
+ <meta property="fb:admins" content="20901205" />
+
+ <!-- See http://developer.apple.com/library/safari/#documentation/appleapplications/reference/SafariHTMLRef/Articles/MetaTags.html -->
+ <meta name="apple-mobile-web-app-capable" content="yes" />
+ <meta name="apple-mobile-web-app-status-bar-style" content="default" />
+
+ <!-- See https://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html -->
+ <link rel="apple-touch-icon" href="http://www.facebookmobileweb.com/hackbook/img/iphone_icon.png" />
+ <link rel="apple-touch-startup-image" href="http://www.facebookmobileweb.com/hackbook/img/iphone_splash.png" />
+ <link rel="apple-touch-icon-precomposed" href="http://www.facebookmobileweb.com/hackbook/img/iphone_icon.png" />
+
+ <!-- See http://davidbcalhoun.com/2010/viewport-metatag for information on the viewport tag. -->
+ <meta name="viewport" content="initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+
+ <link rel="stylesheet" type="text/css" href="css/style.css">
+</head>
+
+<body>
+ <!-- This initializes the Facebook JS SDK. -->
+ <div id="fb-root"></div>
+ <!--<script src=" http://connect.facebook.net/en_US/all.js"></script>-->
+ <script src="cordova-1.6.1.js"></script>
+ <!-- cordova facebook plugin -->
+ <script src="cdv-plugin-fb-connect.js"></script>
+ <!-- facebook js sdk -->
+ <script src="facebook_js_sdk.js"></script>
+
+ <div id="header">
+ <div id="back-link" onclick="openPage('root')"><div id="back">&lt; Back</div></div>
+ <div id="title">Title</div>
+
+ <div id="right-block">
+ <div class="show_when_not_connected">
+ <a onclick="promptLogin()" class="login-button">
+ <span>Login</span>
+ </a>
+ </div>
+ </div>
+ </div>
+
+ <div id="action">
+ <div id="loading-icon"></div>
+
+ <div id="msg"></div>
+ </div>
+
+ <!-- Page: Homepage -->
+ <div id="page-root" class="page">
+ <div class="show_when_connected">
+ <div id="welcome"><img id="user-picture" /><br /><span id="user-name"></span></div>
+ </div>
+
+ <ul>
+ <li class="menu-item" onclick="openPage('Login');">Login and Permissions</li>
+ <li class="menu-item" onclick="openPage('Requests');">Requests</li>
+ <li class="menu-item" onclick="openPage('News-Feed');">News Feed</li>
+ <li class="menu-item" onclick="openPage('Graph-API');">Graph API</li>
+ <!-- <li class="menu-item" onclick="openPage('Credits');" id="credits-button">Credits</li>
+ <li class="menu-item" onclick="openPage('Social-Plugins');">Social Plugins</li> -->
+ </ul>
+ <div id="like-button"><fb:like url="http://www.cnn.com/" width="275"></fb:like></div>
+ </div>
+
+ <!-- Page: Login and Permissions -->
+ <div id="page-Login" class="page">
+ <p id="main-desc">
+ Facebook Platform uses the OAuth 2.0 protocol for logging a user into your app.
+ The Login button in the top right of this app, shown when you're logged out, is a good example.<br /><br />
+ <strong>Check out the mobile web app tutorial at <a href="http://developers.facebook.com/docs/mobile/web/build//">developers.facebook.com/docs/mobile/web/build/</a></strong>
+ </p>
+
+ <div class="section">
+ <div class="show_when_not_connected">
+ <h1>Logging the user in</h1>
+ <p>
+ If a user visit your site directly, you will need to ask them to login with Facebook.
+ </p>
+ </div>
+ <div class="show_when_connected">
+ <h1>Logging the user out</h1>
+ <p>
+ You should include a button to enable the user to log out. Also, you can include a button so that the user can uninstall your app.
+ </p>
+ </div>
+
+ <div class="show_when_not_connected">
+ <div id="login_button" class="button" onclick="promptLogin()" />Login using Facebook</div>
+ </div>
+ <div class="show_when_connected">
+ <div id="login_button" class="button" onclick="logout()" />Logout</div>
+ <div id="login_button" class="button" onclick="uninstallApp()" />Uninstall app</div>
+ </div>
+ </div>
+
+ <div class="section">
+ <h1>Asking for extended permissions</h1>
+ <p>
+ If your app needs more than this basic information to function, you must request specific permissions from the user.
+ For example, you might prompt the user to grant access to their Likes in order to recommend related content for them.
+ </p>
+
+ <div id="extended_permission_button" class="button button-requires-connect" onclick="promptExtendedPermissions()" />Grant the 'user_likes' permission</div>
+
+ <div class="info-requires-connect">You need to login before you can use this functionality.</div>
+ </div>
+ </div>
+
+ <!-- Page: Requests -->
+ <div id="page-Requests" class="page">
+ <p id="main-desc">
+ Requests allows the user to invite their friends to the app, or to re-engage their friends so they come back to your app.
+ Friends receive requests in Notifications on Facebook.
+ <br /><br />
+ <strong>Check out the mobile web app tutorial at <a href="http://developers.facebook.com/docs/mobile/web/build//">developers.facebook.com/docs/mobile/web/build/</a></strong>
+ </p>
+
+ <div class="section">
+ <h1>Request</h1>
+ <p>
+ If you show the request dialog with no friend suggestions, it will automatically show friends that are using your app, as well as friends that have already used your app.
+ </p>
+ <div id="request_button" class="button" onclick="sendRequestBoth()" />Send request</div>
+ </div>
+
+ <div class="section">
+ <h1>Invite friends not using app</h1>
+ <p>
+ The user can invite their friends that have not started using your application yet. This will help grow your mobile website virally.
+ </p>
+
+ <div id="request_button" class="button button-requires-connect" onclick="sendRequestInvite()" />Send invite</div>
+
+ <div class="info-requires-connect">You need to login before you can use this functionality.</div>
+ </div>
+
+ <div class="section">
+ <h1>Request to app friends</h1>
+ <p>
+ If a friend of the active user needs to take an action in your mobile web app, you can prompt them to send a request.
+ This can be used for re-engagement, like telling a friend it's their turn in a board game.
+ </p>
+ <div id="request_button" class="button button-requires-connect" onclick="sendRequest()" />Send request</div>
+
+ <div class="info-requires-connect">You need to login before you can use this functionality.</div>
+ </div>
+
+ <div class="section">
+ <h1>Request to targeted friend</h1>
+ <p>
+ If the user's friends need to take an action in your mobile website, you can prompt them to send a request.
+ This can be used for things like telling a friend it is their turn in a board game.
+ </p>
+ <div id="request_button" class="button button-requires-connect" onclick="sendRequestSingle()" />Send request</div>
+
+ <div class="info-requires-connect">You need to login before you can use this functionality.</div>
+ </div>
+ </div>
+
+ <!-- Page: News Feed -->
+ <div id="page-News-Feed" class="page">
+ <p id="main-desc">
+ Your app can prompt users to share on their own wall or their friend's wall.
+ <br /><br />
+ <strong>Check out the mobile web app tutorial at <a href="http://developers.facebook.com/docs/mobile/web/build//">developers.facebook.com/docs/mobile/web/build/</a></strong>
+ </p>
+
+ <div class="section">
+ <h1>Publishing to the user's wall</h1>
+ <p>
+ This allows a user to post something to their own Wall, which means it will also appear in all of their friends' News Feeds on Facebook.
+ </p>
+
+ <div id="publish_button" class="button" onclick="publishStory()" />Publish to your wall</div>
+ </div>
+
+ <div class="section">
+ <h1>Publish to a friend's wall</h1>
+ <p>
+ This allows a user to post something to their friend's Wall, which means it will also appear in all of their mutual friends' News Feeds on Facebook.
+ </p>
+
+ <div id="publish_button" class="button button-requires-connect" onclick="publishStoryFriend()" />Publish to friend's wall</div>
+
+ <div class="info-requires-connect">You need to login before you can use this functionality.</div>
+ </div>
+ </div>
+
+ <!-- Page: Graph API -->
+ <div id="page-Graph-API" class="page">
+ <p id="main-desc">
+ The Graph API enables you to read and write data to Facebook.
+ You can utilize what the user has liked, friends, photos, events, as well as most of the data that's available on Facebook.<br /><br />
+ <strong>Check out the mobile web app tutorial at <a href="http://developers.facebook.com/docs/mobile/web/build//">developers.facebook.com/docs/mobile/web/build/</a></strong>
+ </p>
+
+ <div class="section">
+ <h1>Get user's basic information</h1>
+ <p>
+ You can fetch the user's profile picture and name in order to personalize the experience for them.
+ </p>
+
+ <div id="user-info"></div>
+
+ <div class="button button-requires-connect" onclick="getUserBasicInfo();hideButton(this);" />Get your information</div>
+
+ <div class="info-requires-connect">You need to login before you can use this functionality.</div>
+ </div>
+
+ <div class="section">
+ <h1>Get user's friends</h1>
+ <p>
+ To make your mobile web app social, you can fetch their friends' information like profile pictures and names.
+ </p>
+
+ <div id="user-friends"></div>
+
+ <div class="button button-requires-connect" onclick="getUserFriends();hideButton(this);" />Get your friends</div>
+
+ <div class="info-requires-connect">You need to login before you can use this functionality.</div>
+
+ </div>
+
+ <div class="section">
+ <h1>Get user's recent check-ins</h1>
+ <p>
+ You can fetch fetch their previous Facebook Places check-ins.
+ </p>
+
+ <div id="checkins"></div>
+
+ <div class="show_when_not_permissioned">
+ <div class="button button-requires-connect" onclick="promptCheckInPermission()" />Grant check-in permission</div>
+
+ <div class="info-requires-connect">You need to login before you can use this functionality.</div>
+ </div>
+
+ <div class="show_when_permissioned">
+ <div class="button" onclick="getCheckIns();hideButton(this);"/>Get past check-ins</div>
+ </div>
+ </div>
+
+ <div class="section">
+ <h1>Check the user into a place</h1>
+ <p>
+ You can fetch Places near the user's current location and check the user in.
+ </p>
+
+ <div id="locations-nearby"></div>
+
+ <div class="show_when_not_permissioned">
+ <div class="button button-requires-connect" onclick="promptCheckInPermission()" />Grant check-in permission</div>
+
+ <div class="info-requires-connect">You need to login before you can use this functionality.</div>
+ </div>
+
+ <div class="show_when_permissioned">
+ <div class="button" onclick="getNearby();hideButton(this);" />Find nearby locations</div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Page: Credits
+ <div id="page-Credits" class="page">
+ <p id="main-desc">
+ Your app or game can prompt the user to pay for a virtual good by using Credits.
+ <br /><br />
+ <strong>Check out the mobile web app tutorial at <a href="http://developers.facebook.com/docs/mobile/web/build//">developers.facebook.com/docs/mobile/web/build/</a></strong>
+ </p>
+
+ <div class="section">
+ <h1>Prompting the user to pay</h1>
+ <p>
+ This allows the user to pay for a virtual good in your app or game.
+ </p>
+
+ <div id="publish_button" class="button" onclick="sendPay()" />Prompt to Pay</div>
+ </div>
+ </div>-->
+
+ <!-- Page: Social Plugins -->
+ <!--<div id="page-Social-Plugins" class="page">
+ <p id="main-desc">
+ Social plugins lets a user see what their friends have liked, commented on or shared on sites across the web.
+ Currently, the only social plugin that's available is the Like button. More coming soon.<br /><br />
+ <strong>Check out the mobile web app tutorial at <a href="http://developers.facebook.com/docs/mobile/web/build//">developers.facebook.com/docs/mobile/web/build/</a></strong>
+ </p>
+
+ <div class="section">
+ <h1>Like button</h1>
+ <p>
+ <fb:like></fb:like>
+ </p>
+ </div>
+ </div>-->
+
+ <!--<script src="js/_config.js"></script>-->
+ <script src="js/ui.js"></script>
+ <script src="js/auth.js"></script>
+ <script src="js/feed.js"></script>
+ <script src="js/graph_api.js"></script>
+ <script src="js/requests.js"></script>
+ <!--<script src="js/credits.js"></script>-->
+
+ <script>
+ if ((typeof Cordova == 'undefined') && (typeof cordova == 'undefined')) alert('Cordova variable does not exist. Check that you have included cordova.js correctly');
+ if (typeof CDV == 'undefined') alert('CDV variable does not exist. Check that you have included pg-plugin-fb-connect.js correctly');
+ if (typeof FB == 'undefined') alert('FB variable does not exist. Check that you have included the Facebook JS SDK file.');
+
+ document.addEventListener('deviceready', function() {
+ try {
+ //alert('Device is ready! Make sure you set your app_id below this alert.');
+ FB.init({ appId: "313825608690788", nativeInterface: CDV.FB, useCachedDialogs: false });
+ } catch (e) {
+ alert(e);
+ }
+ }, false);
+ </script>
+</body>
+</html>
29 example/FacebookandTwitter/assets/www/js/_config.js
View
@@ -0,0 +1,29 @@
+//////////////////////////
+//
+// Config
+// Set your app id here.
+//
+//////////////////////////
+
+if (window.location.host == 'facebookmobileweb.com' || window.location.host == 'www.facebookmobileweb.com') {
+ var gAppID = '147366981996453';
+}
+//Add your Application ID here
+else {
+ var gAppID = 'enter_your_appid_here';
+}
+
+if (gAppID == 'enter_your_appid_here') {
+ alert('You need to enter your App ID in js/_config.js on line 13.');
+}
+
+//Initialize the Facebook SDK
+FB.init({
+ appId: gAppID,
+ status: true,
+ cookie: true,
+ xfbml: true,
+ frictionlessRequests: true,
+ useCachedDialogs: true,
+ oauth: true
+});
82 example/FacebookandTwitter/assets/www/js/auth.js
View
@@ -0,0 +1,82 @@
+//////////////////////////
+//
+// Authentication
+// See "Logging the user in" on https://developers.facebook.com/mobile
+//
+//////////////////////////
+
+var user = [];
+
+//Detect when Facebook tells us that the user's session has been returned
+FB.Event.monitor('auth.statusChange', function(session) {
+ console.log('Got the user\'s session: ', session);
+
+ if (session && session.status != 'not_authorized' && session.status != 'notConnected') {
+ if (session.authResponse['accessToken']) {
+ document.body.className = 'connected';
+
+ //Fetch user's id, name, and picture
+ FB.api('/me', {
+ fields: 'name, picture'
+ },
+ function(response) {
+ if (!response.error) {
+ user = response;
+
+ console.log('Got the user\'s name and picture: ', response);
+
+ //Update display of user name and picture
+ if (FB.$('user-name')) {
+ FB.$('user-name').innerHTML = user.name;
+ }
+ if (FB.$('user-picture')) {
+ FB.$('user-picture').src = user.picture;
+ }
+ }
+
+ clearAction();
+ });
+ }
+ }
+ else if (session === undefined) {
+ document.body.className = 'not_connected';
+
+ clearAction();
+ }
+ else if (session && (session.status == 'not_authorized' || session.status == 'notConnected')) {
+ document.body.className = 'not_connected';
+
+ clearAction();
+ }
+});
+
+//Prompt the user to login and ask for the 'email' permission
+function promptLogin() {
+ FB.login(null, {scope: 'email'});
+}
+
+//This will prompt the user to grant you acess to their Facebook Likes
+function promptExtendedPermissions() {
+ FB.login(function() {
+ setAction("The 'user_likes' permission has been granted.", false);
+
+ setTimeout('clearAction();', 2000);
+
+ document.body.className = 'permissioned';
+ }, {scope: 'user_likes'});
+}
+
+//See https://developers.facebook.com/docs/reference/rest/auth.revokeAuthorization/
+function uninstallApp() {
+ FB.api({method: 'auth.revokeAuthorization'},
+ function(response) {
+ window.location.reload();
+ });
+}
+
+//See https://developers.facebook.com/docs/reference/javascript/FB.logout/
+function logout() {
+ FB.logout(function(response) {
+ window.location.reload();
+ });
+}
24 example/FacebookandTwitter/assets/www/js/credits.js
View
@@ -0,0 +1,24 @@
+//////////////////////////
+//
+// Credits
+// See https://developers.facebook.com/docs/creditsapi/
+//
+//////////////////////////
+
+//Prompt the user to pay for a virtual good
+function sendPay() {
+ FB.ui({
+ method: 'pay',
+ credits_purchase: false,
+ // This is the item ID defined in your game or app
+ order_info: 'locket'
+ },
+ function(response) {
+ console.log('sendPay response: ', response);
+ });
+}
+
+//If Hackbook is running from within the Facebook iOS native app, disable Credits
+if (FB.UA.nativeApp()) {
+ document.getElementById('credits-button').style.display = 'none';
+}
46 example/FacebookandTwitter/assets/www/js/feed.js
View
@@ -0,0 +1,46 @@
+//////////////////////////
+//
+// News Feed
+// See the "News Feed" section on https://developers.facebook.com/mobile
+//
+//////////////////////////
+
+//Publish a story to the user's own wall
+function publishStory() {
+ FB.ui({
+ method: 'feed',
+ name: 'I\'m using the Hackbook web app',
+ caption: 'Hackbook for Mobile Web.',
+ description: 'Check out Hackbook for Mobile Web to learn how you can make your web apps social using Facebook Platform.',
+ link: 'http://apps.facebook.com/mobile-start/',
+ picture: 'http://www.facebookmobileweb.com/hackbook/img/facebook_icon_large.png',
+ actions: [{ name: 'Get Started', link: 'http://apps.facebook.com/mobile-start/' }],
+ },
+ function(response) {
+ console.log('publishStory UI response: ', response);
+ });
+}
+
+//Publish a story to the user's friend's wall
+function publishStoryFriend() {
+ randNum = Math.floor ( Math.random() * friendIDs.length );
+
+ var friendID = friendIDs[randNum];
+
+ console.log('Opening a dialog for friendID: ', friendID);
+
+ FB.ui({
+ method: 'feed',
+ to: friendID,
+ name: 'I\'m using the Hackbook web app',
+ caption: 'Hackbook for Mobile Web.',
+ description: 'Check out Hackbook for Mobile Web to learn how you can make your web apps social using Facebook Platform.',
+ link: 'http://apps.facebook.com/mobile-start/',
+ picture: 'http://www.facebookmobileweb.com/hackbook/img/facebook_icon_large.png',
+ actions: [{ name: 'Get Started', link: 'http://apps.facebook.com/mobile-start/' }],
+ user_message_prompt: 'Tell your friends about building social web apps.'
+ },
+ function(response) {
+ console.log('publishStoryFriend UI response: ', response);
+ });
+}
224 example/FacebookandTwitter/assets/www/js/graph_api.js
View
@@ -0,0 +1,224 @@
+//////////////////////////
+//
+// Graph API
+// See https://developers.facebook.com/docs/reference/api/
+//
+//////////////////////////
+
+//Detect when Facebook tells us that the user's session has been returned
+FB.Event.monitor('auth.statusChange', function(session) {
+ //If the user isn't logged in, set the body class so that we show/hide the correct elements
+ if (session == undefined || session.status == 'not_authorized') {
+ if (document.body.className != 'not_connected') {
+ document.body.className = 'not_permissioned';
+ }
+ }
+ //The user is logged in, so let's see if they've granted the check-in permission and pre-fetch some data
+ //Depending on if they have or haven't, we'll set the body to reflect that so we show/hide the correct elements on the page
+ else {
+ preFetchData();
+
+ FB.api({method: 'fql.query', query: 'SELECT user_checkins, publish_checkins FROM permissions WHERE uid = me()'}, function(response) {
+ if (document.body.className != 'not_connected') {
+ //We couldn't get a check-in for the user, so they haven't granted the permission
+ if (response[0] && response[0].user_checkins == 1) {
+ document.body.className = 'permissioned';
+ }
+ //We were able to get a check-in for the user, so they have granted the permission already
+ else {
+ document.body.className = 'not_permissioned';
+ }
+ }
+ });
+ }
+});
+
+//Get the user's basic information
+function getUserBasicInfo() {
+ setAction('Getting your information', false);
+
+ var markup = '<div class="data-header">Your information:</div>';
+
+ //Update display of user name and picture
+ if (FB.$('user-info')) {
+ markup = markup + '<strong>User ID:</strong> ' + user.id + '<br />' + '<strong>Name:</strong> ' + user.name + '<br />' + '<strong>Profile picture URL:</strong> <a href="' + user.picture + '" target="_blank">' + user.picture + '</a><br />';
+ FB.$('user-info').innerHTML = markup;
+
+ clearAction();
+ }
+}
+
+//Get the user's friends
+function getUserFriends() {
+ var markup = '<div class="data-header">Friends (capped at 25):</div>';
+
+ for (var i=0; i < friendsInfo.length && i < 25; i++) {
+ markup = markup + '<img src="' + friendsInfo[i].picture + '">' + friendsInfo[i].name + '<br />';
+ }
+
+ FB.$('user-friends').innerHTML = markup;
+}
+
+//Get the user's check-ins
+function getCheckIns() {
+ setAction('Getting check-ins', false);
+
+ FB.api('/me/checkins', function(response) {
+ console.log('Got your check-ins: ', response);
+
+ clearAction();
+
+ if (!response.error) {
+ displayCheckIns(response.data, FB.$('checkins'));
+ }
+ });
+}
+
+//Display the user's check-ins
+function displayCheckIns(checkins, dom) {
+ var markup = '<div class="data-header">Your last five check-ins:</div>';
+
+ for (var i=0; i < checkins.length && i < 5; i++) {
+ var checkin = checkins[i];
+
+ markup += '<div class="place">'
+ + '<div class="picture"><img src="https://graph.facebook.com/' + checkin.place.id + '/picture"></div>'
+ + '<div class="info">'
+ + ' <div class="name">' + checkin.place.name + '</div>'
+ + ' <div class="check-in-msg">' + (checkin.message || '') + '</div>'
+ + '</div>'
+ + '</div>';
+ }
+
+ dom.innerHTML = markup;
+}
+
+//Display the local places that the user can check into
+function displayPlaces(places, dom) {
+ var markup = '<div class="data-header">Nearby locations:</div>';
+
+ for (var i=0; i < places.length && i < 5; i++) {
+ var place = places[i];
+
+ markup += '<div class="place">'
+ + '<div class="picture"><img src="https://graph.facebook.com/' + place.id + '/picture"></div>'
+ + '<div class="info">'
+ + ' <div class="name">' + place.name + '</div>'
+ + ' <div class="check-in-button"><input type="button" value="Check in" onclick="checkin(' + place.id + ')" /></div>'
+ + '</div>'
+ + '</div>';
+ }
+
+ dom.innerHTML = markup;
+}
+
+//Check the user into the place
+function checkin(id) {
+ setAction("Checking you in", false);
+
+ var params = {
+ method: 'POST',
+ place: id,
+ coordinates: {
+ latitude: curLocation.coords.latitude,
+ longitude: curLocation.coords.longitude
+ },
+ message: ''
+ };
+
+ FB.api('/me/checkins', params,
+ function(response) {
+ clearAction();
+
+ var debugOutput = '';
+ for (var property in response) {
+ debugOutput += property + ': ' + response[property]+'; ';
+ }
+ console.log('Checked you into the place, here\'s the response::'+debugOutput);
+ //console.log('Checked you into the place, here\'s the response: ', response);
+
+ setAction("You've successfully checked in!", false);
+
+ setTimeout('clearAction();', 2000);
+ }
+ );
+}
+
+//Get locations near the user
+function getNearby() {
+ setAction("Getting nearby locations", false);
+
+ // First use browser's geolocation API to obtain location
+ navigator.geolocation.getCurrentPosition(function(location) {
+ curLocation = location;
+ console.log(location);
+
+ // Use graph API to search nearby places
+ var path = '/search?type=place&center=' + location.coords.latitude + ',' + location.coords.longitude + '&distance=1000';
+
+ FB.api(path, function(response) {
+ clearAction();
+ console.log('Got some places near you: ', response);
+ if (!response.error) {
+ displayPlaces(response.data, FB.$('locations-nearby'));
+ }
+ });
+ });
+}
+
+//Prompt the user to grant the check-in permission
+function promptCheckInPermission() {
+ FB.login(function(response) {
+ if (response.authResponse) {
+ //User granted permissions
+ document.body.className = 'permissioned';
+ }
+ else {
+ //User didn't grant permissions
+ alert('You need to grant the check-in permission before using this functionality.');
+ }
+ }, {scope:'user_checkins,publish_checkins'});
+}
+
+//Pre-fetch data, mainly used for requests and feed publish dialog
+var nonAppFriendIDs = [];
+var appFriendIDs = [];
+var friendIDs = [];
+var friendsInfo = [];
+
+function preFetchData() {
+ //First, get friends that are using the app
+ FB.api({method: 'friends.getAppUsers'}, function(appFriendResponse) {
+ appFriendIDs = appFriendResponse;
+
+ //Now fetch all of the user's friends so that we can determine who hasn't used the app yet
+ FB.api('/me/friends', { fields: 'id, name, picture' }, function(friendResponse) {
+ friends = friendResponse.data;
+
+ //limit to a 200 friends so it's fast
+ for (var k = 0; k < friends.length && k < 200; k++) {
+ var friend = friends[k];
+ var index = 1;
+
+ friendIDs[k] = friend.id;
+ friendsInfo[k] = friend;
+
+ for (var i = 0; i < appFriendIDs.length; i++) {
+ if (appFriendIDs[i] == friend.id) {
+ index = -1;
+ }
+ }
+
+ if (index == 1) {
+ nonAppFriendIDs.push(friend.id);
+ }
+ }
+
+ console.log('Got your friend\'s that use the app: ', appFriendIDs);
+
+ console.log('Got all of your friends: ', friendIDs);
+
+ console.log('Got friends that are not using the app yet: ', nonAppFriendIDs);
+ });
+ });
+}
55 example/FacebookandTwitter/assets/www/js/requests.js
View
@@ -0,0 +1,55 @@
+//////////////////////////
+//
+// Requests
+// See the "Requests" section on https://developers.facebook.com/mobile
+//
+//////////////////////////
+
+//Send a request to friends have have logged into the app in the past, as well as friends that haven't
+function sendRequestBoth() {
+ FB.ui({
+ method: 'apprequests',
+ message: 'Learn how to make your mobile web app social',
+ },
+ function(response) {
+ console.log('sendRequestBoth response: ', response);
+ });
+}
+
+//Send an invite to friends that haven't logged into the app yet
+function sendRequestInvite() {
+ FB.ui({
+ method: 'apprequests',
+ suggestions: nonAppFriendIDs,
+ message: 'Learn how to make your mobile web app social',
+ }, function(response) {
+ console.log('sendRequestInvite UI response: ', response);
+ });
+}
+
+//Send a request to friends that are already using the app
+function sendRequest() {
+ FB.ui({
+ method: 'apprequests',
+ suggestions: appFriendIDs,
+ message: 'Learn how to make your mobile web app social',
+ }, function(response) {
+ console.log('sendRequest UI response: ', response);
+ });
+}
+
+//Send a request to a single friend that is using the app
+function sendRequestSingle() {
+ randNum = Math.floor ( Math.random() * friendIDs.length );
+
+ var friendID = friendIDs[randNum];
+
+ FB.ui({
+ method: 'apprequests',
+ //Use the first friend returned
+ to: friendID,
+ message: 'Learn how to make your mobile web app social',
+ }, function(response) {
+ console.log('sendRequestSingle UI response: ', response);
+ });
+}
78 example/FacebookandTwitter/assets/www/js/ui.js
View
@@ -0,0 +1,78 @@
+//////////////////////////
+//
+// UI assist functions
+//
+//////////////////////////
+
+//show a loading screen when launched, until we get the user's session back
+setAction("Loading Hackbook", true);
+
+//Swaps the pages out when the user taps on a choice
+function openPage(pageName, ignoreHistoryPush) {
+ window.scrollTo(0,1);
+
+ var els = document.getElementsByClassName('page');
+
+ for (var i = 0 ; i < els.length ; ++i) {
+ els[i].style.display = 'none';
+ }
+
+ var page = document.getElementById('page-' + pageName);
+
+ page.style.display = "block";
+
+ title = (pageName == 'root') ? 'Hackbook' : pageName.replace(/-/g, ' ');
+ document.getElementById('title').innerHTML = title;
+
+ if (ignoreHistoryPush != true) {
+ window.history.pushState({page: pageName}, '', document.location.origin + document.location.pathname + "#" + pageName);
+ }
+
+ document.getElementById('back').style.display = (pageName == 'root') ? 'none' : 'block';
+}
+
+window.onpopstate = function(e) {
+ if (e.state != null) {
+ console.log(e.state);
+ openPage(e.state.page);
+ }
+ else {
+ openPage('root', true);
+ }
+}
+
+openPage('root', true);
+
+//Shows a modal dialog when fetcing data from Facebook
+function setAction(msg, hideBackground) {
+ document.getElementById('action').style.display = 'block';
+
+ if (hideBackground) {
+ document.getElementById('action').style.opacity = '100';
+ }