From 62adb566c01c622e7b8fe5327b33d496337fdea7 Mon Sep 17 00:00:00 2001 From: Steven Gill Date: Mon, 12 Mar 2012 16:29:02 +0200 Subject: [PATCH] added hackbook example --- README.md | 2 +- example/HackBook/README | 57 + example/HackBook/css/style.css | 420 + example/HackBook/facebook_js_sdk.js | 14638 ++++++++++++++++ example/HackBook/hackbook.manifest | 18 + example/HackBook/img/facebook_icon_large.png | Bin 0 -> 6824 bytes example/HackBook/img/facebook_icon_small.png | Bin 0 -> 3270 bytes example/HackBook/img/iphone_icon.png | Bin 0 -> 7755 bytes example/HackBook/img/iphone_splash.png | Bin 0 -> 29064 bytes .../img/iphone_splash_retina_display.png | Bin 0 -> 46866 bytes example/HackBook/img/loader.gif | Bin 0 -> 723 bytes example/HackBook/index.html | 329 + example/HackBook/js/_config.js | 29 + example/HackBook/js/auth.js | 82 + example/HackBook/js/credits.js | 24 + example/HackBook/js/feed.js | 46 + example/HackBook/js/graph_api.js | 221 + example/HackBook/js/requests.js | 55 + example/HackBook/js/ui.js | 78 + example/HackBook/pg-plugin-fb-connect.js | 52 + example/HackBook/phonegap-1.4.1.js | 4123 +++++ example/Simple/www/index.html | 8 +- 22 files changed, 20177 insertions(+), 5 deletions(-) create mode 100644 example/HackBook/README create mode 100644 example/HackBook/css/style.css create mode 100644 example/HackBook/facebook_js_sdk.js create mode 100644 example/HackBook/hackbook.manifest create mode 100644 example/HackBook/img/facebook_icon_large.png create mode 100644 example/HackBook/img/facebook_icon_small.png create mode 100644 example/HackBook/img/iphone_icon.png create mode 100644 example/HackBook/img/iphone_splash.png create mode 100644 example/HackBook/img/iphone_splash_retina_display.png create mode 100644 example/HackBook/img/loader.gif create mode 100644 example/HackBook/index.html create mode 100644 example/HackBook/js/_config.js create mode 100644 example/HackBook/js/auth.js create mode 100644 example/HackBook/js/credits.js create mode 100644 example/HackBook/js/feed.js create mode 100644 example/HackBook/js/graph_api.js create mode 100644 example/HackBook/js/requests.js create mode 100644 example/HackBook/js/ui.js create mode 100755 example/HackBook/pg-plugin-fb-connect.js create mode 100644 example/HackBook/phonegap-1.4.1.js diff --git a/README.md b/README.md index dccee8f3d..7290cbdca 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ NOTE: If you are having problems with SBJSON conflicts, download the latest vers 1. Create a basic PhoneGap iOS application. See http://www.phonegap.com/start/#ios-x4 2. From the **PhoneGap Facebook Connect Plugin** folder copy the contents of the **native/ios** folder into your app in Xcode (usually in the **Plugins** folder group). Make sure it is added as a "group" (yellow folder) -3. Modify the **APP\_SECRET** value in **FacebookConnectPlugin.m** with your Facebook app's **APP\_SECRET** +SKIP -> 3. Modify the **APP\_SECRET** value in **FacebookConnectPlugin.m** with your Facebook app's **APP\_SECRET** 4. Find the PhoneGap.plist file in the project navigator, expand the "Plugins" sub-tree, and add a new entry. For the key, add **com.phonegap.facebook.Connect**, and its value will be **FacebookConnectPlugin** 5. From the **PhoneGap Facebook Connect Plugin** folder copy the contents of the **www** folder into the **www** directory in Xcode (don't forget to add script tags in your index.html to reference any .js files copied over) 6. for Xcode 4, you will need to build it once, and heed the warning - this is an Xcode 4 template limitation. The warning instructions will tell you to drag copy the **www** folder into the project in Xcode (add as a **folder reference** which is a blue folder). diff --git a/example/HackBook/README b/example/HackBook/README new file mode 100644 index 000000000..6e281366c --- /dev/null +++ b/example/HackBook/README @@ -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 \ No newline at end of file diff --git a/example/HackBook/css/style.css b/example/HackBook/css/style.css new file mode 100644 index 000000000..504d1de03 --- /dev/null +++ b/example/HackBook/css/style.css @@ -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; +} \ No newline at end of file diff --git a/example/HackBook/facebook_js_sdk.js b/example/HackBook/facebook_js_sdk.js new file mode 100644 index 000000000..2ad8e32c4 --- /dev/null +++ b/example/HackBook/facebook_js_sdk.js @@ -0,0 +1,14638 @@ +/*1329323125,171364642,JIT Construction: v510186,en_US*/ + +/** + * Copyright 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. + * + * + * + * @provides fb.prelude + */ + +/** + * Prelude. + * + * Namespaces are one honking great idea -- let's do more of those! + * -- Tim Peters + * + * The Prelude is what keeps us from being messy. In order to co-exist with + * arbitary environments, we need to control our footprint. The one and only + * rule to follow here is that we need to limit the globals we introduce. The + * only global we should every have is ``FB``. This is exactly what the prelude + * enables us to do. + * + * The main method to take away from this file is `FB.copy()`_. As the name + * suggests it copies things. Its powerful -- but to get started you only need + * to know that this is what you use when you are augmenting the FB object. For + * example, this is skeleton for how ``FB.Event`` is defined:: + * + * FB.provide('Event', { + * subscribe: function() { ... }, + * unsubscribe: function() { ... }, + * fire: function() { ... } + * }); + * + * This is similar to saying:: + * + * FB.Event = { + * subscribe: function() { ... }, + * unsubscribe: function() { ... }, + * fire: function() { ... } + * }; + * + * Except it does some housekeeping, prevents redefinition by default and other + * goodness. + * + * .. _FB.copy(): #method_FB.copy + * + * @class FB + * @static + * @access private + */ +if (!window.FB) { + window.FB = { + // use the init method to set these values correctly + _apiKey : null, + _authResponse : null, + _userStatus : 'unknown', // or 'notConnected' or 'connected' + + // logging is enabled by default. this is the logging shown to the + // developer and not at all noisy. + _logging: true, + _inCanvas: ( + (window.name.indexOf('iframe_canvas') > -1) || + (window.name.indexOf('app_runner') > -1)), + + // Determines if we should use HTTPS when attempting cross-domain + // communication with facebook.com. This is assumed to be the case when + // window.name contains "_fb_https". This value may also be set by the + // response from FB.login() or FB.getLoginStatus() + _https: (window.name.indexOf('_fb_https') > -1), + + // + // DYNAMIC DATA + // + // the various domains needed for using Connect + _domain: { + api : 'https://api.facebook.com/', + api_read : 'https://api-read.facebook.com/', + cdn : 'http://static.ak.fbcdn.net/', + https_cdn : 'https://s-static.ak.fbcdn.net/', + graph : 'https://graph.facebook.com/', + staticfb : 'http://static.ak.facebook.com/', + https_staticfb : 'https://s-static.ak.facebook.com/', + www : 'http://www.facebook.com/', + https_www : 'https://www.facebook.com/', + m : 'http://m.facebook.com/', + https_m : 'https://m.facebook.com/' + }, + _locale: null, + _localeIsRtl: false, + + + // PHONEGAP PATCH + _nativeInterface : null, + + /** + * Retrieve one of the various domains needed for Connect. + * + * @access private + * @param domain (String) The domain to retrieve + * @param noForcedHTTPS (bool) Do not force https domain + */ + getDomain: function(domain, noForcedHTTPS) { + var forceHTTPS = !noForcedHTTPS && + (window.location.protocol == 'https:' || FB._https); + switch (domain) { + case 'api': + return FB._domain.api; + case 'api_read': + return FB._domain.api_read; + case 'cdn': + return forceHTTPS ? FB._domain.https_cdn : FB._domain.cdn; + case 'cdn_foreign': + return FB._domain.cdn_foreign; + case 'https_cdn': + return FB._domain.https_cdn; + case 'graph': + return FB._domain.graph; + case 'staticfb': + return forceHTTPS ? FB._domain.https_staticfb : FB._domain.staticfb; + case 'https_staticfb': + return FB._domain.https_staticfb; + case 'www': + return forceHTTPS ? FB._domain.https_www : FB._domain.www; + case 'https_www': + return FB._domain.https_www; + case 'm': + return forceHTTPS ? FB._domain.https_m : FB._domain.m; + case 'https_m': + return FB._domain.https_m; + } + }, + + /** + * Copies things from source into target. + * + * @access private + * @param target {Object} the target object where things will be copied + * into + * @param source {Object} the source object where things will be copied + * from + * @param overwrite {Boolean} indicate if existing items should be + * overwritten + * @param transform {function} [Optional], transformation function for + * each item + */ + copy: function(target, source, overwrite, transform) { + for (var key in source) { + if (overwrite || typeof target[key] === 'undefined') { + target[key] = transform ? transform(source[key]) : source[key]; + } + } + return target; + }, + + /** + * Create a namespaced object. + * + * @access private + * @param name {String} full qualified name ('Util.foo', etc.) + * @param value {Object} value to set. Default value is {}. [Optional] + * @return {Object} The created object + */ + create: function(name, value) { + var node = window.FB, // We will use 'FB' as root namespace + nameParts = name ? name.split('.') : [], + c = nameParts.length; + for (var i = 0; i < c; i++) { + var part = nameParts[i]; + var nso = node[part]; + if (!nso) { + nso = (value && i + 1 == c) ? value : {}; + node[part] = nso; + } + node = nso; + } + return node; + }, + + /** + * Copy stuff from one object to the specified namespace that + * is FB.. + * If the namespace target doesn't exist, it will be created automatically. + * + * @access private + * @param target {Object|String} the target object to copy into + * @param source {Object} the source object to copy from + * @param overwrite {Boolean} indicate if we should overwrite + * @return {Object} the *same* target object back + */ + provide: function(target, source, overwrite) { + // a string means a dot separated object that gets appended to, or created + return FB.copy( + typeof target == 'string' ? FB.create(target) : target, + source, + overwrite + ); + }, + + /** + * Generates a weak random ID. + * + * @access private + * @return {String} a random ID + */ + guid: function() { + return 'f' + (Math.random() * (1<<30)).toString(16).replace('.', ''); + }, + + /** + * Logs a message for the developer if logging is on. + * + * @access private + * @param args {Object} the thing to log + */ + log: function(args) { + if (FB._logging) { + //TODO what is window.Debug, and should it instead be relying on the + // event fired below? +//#JSCOVERAGE_IF 0 + if (window.Debug && window.Debug.writeln) { + window.Debug.writeln(args); + } else if (window.console) { + window.console.log(args); + } +//#JSCOVERAGE_ENDIF + } + + // fire an event if the event system is available + if (FB.Event) { + FB.Event.fire('fb.log', args); + } + }, + + /** + * Shortcut for document.getElementById + * @method $ + * @param {string} DOM id + * @return DOMElement + * @access private + */ + $: function(id) { + return document.getElementById(id); + } + }; +} + +/** + * Copyright 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. + * + * @provides fb.array + * @layer basic + * @requires fb.prelude + */ + +/** + * Array related helper methods. + * + * @class FB.Array + * @private + * @static + */ +FB.provide('Array', { + /** + * Get index of item inside an array. Return's -1 if element is not found. + * + * @param arr {Array} Array to look through. + * @param item {Object} Item to locate. + * @return {Number} Index of item. + */ + indexOf: function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + var length = arr.length; + if (length) { + for (var index = 0; index < length; index++) { + if (arr[index] === item) { + return index; + } + } + } + return -1; + }, + + /** + * Merge items from source into target, but only if they dont exist. Returns + * the target array back. + * + * @param target {Array} Target array. + * @param source {Array} Source array. + * @return {Array} Merged array. + */ + merge: function(target, source) { + for (var i=0; i < source.length; i++) { + if (FB.Array.indexOf(target, source[i]) < 0) { + target.push(source[i]); + } + } + return target; + }, + + /** + * Create an new array from the given array and a filter function. + * + * @param arr {Array} Source array. + * @param fn {Function} Filter callback function. + * @return {Array} Filtered array. + */ + filter: function(arr, fn) { + var b = []; + for (var i=0; i < arr.length; i++) { + if (fn(arr[i])) { + b.push(arr[i]); + } + } + return b; + }, + + /** + * Create an array from the keys in an object. + * + * Example: keys({'x': 2, 'y': 3'}) returns ['x', 'y'] + * + * @param obj {Object} Source object. + * @param proto {Boolean} Specify true to include inherited properties. + * @return {Array} The array of keys. + */ + keys: function(obj, proto) { + var arr = []; + for (var key in obj) { + if (proto || obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + }, + + /** + * Create an array by performing transformation on the items in a source + * array. + * + * @param arr {Array} Source array. + * @param transform {Function} Transformation function. + * @return {Array} The transformed array. + */ + map: function(arr, transform) { + var ret = []; + for (var i=0; i < arr.length; i++) { + ret.push(transform(arr[i])); + } + return ret; + }, + + /** + * For looping through Arrays and Objects. + * + * @param {Object} item an Array or an Object + * @param {Function} fn the callback function for iteration. + * The function will be pass (value, [index/key], item) parameters + * @param {Bool} proto indicate if properties from the prototype should + * be included + * + */ + forEach: function(item, fn, proto) { + if (!item) { + return; + } + + if (Object.prototype.toString.apply(item) === '[object Array]' || + (!(item instanceof Function) && typeof item.length == 'number')) { + if (item.forEach) { + item.forEach(fn); + } else { + for (var i=0, l=item.length; i