Skip to content

Instantly share code, notes, and snippets.

@aaronksaunders
Last active December 3, 2017 11:46
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save aaronksaunders/6665528 to your computer and use it in GitHub Desktop.
Save aaronksaunders/6665528 to your computer and use it in GitHub Desktop.
UPDATED PROJECT: http://bit.ly/1p61VRC Tested w/ latest version of parse "parse-1.2.18.js" I took a look at the latest Parse update to the APIs and they have made it even more complex to integrate Appcelerator and Facebook since they have integrated the FB Javascript API into the Parse Module directly.this hack just overrides the FB functions th…

The Parse-Appcelerator JavaScript Hack of Parse JavaScript SDK Version: 1.2.18

The challenge continues to make Parse work with Appcelerator but I have made so adjustment to the original hack I created to get the solution more fully integrated with Appcelerator and include Facebook integration in the solution.

It is the same basic premise as the original solution where we override existing objects in the parse library to leverage the Appcelerator HTTPClient and the Appcelerator Facebook integration. I have tested this solution with the integration IOS support for Facebook single sign on and with old way where you get the web UI for the login prompt.

##Edits to the Parse Javascript API

Add this to line 1348 of Parse JavaScript SDK Version: 1.2.18

  // Import Parse's local copy of underscore.
  if (Titanium !== "undefined") {
    console.log("Using titanium");

    Parse._ = exports._.noConflict();
    exports.Parse = Parse;
  } else

Replace line 8576 of Parse JavaScript SDK Version: 1.2.18

 Parse.User._registerAuthenticationProvider(FB.provider);     

I will create a full example with a git repo soon but for now, here is how you use the library in your application

require("lib/ti.parse_mine")({
  facebookAppId : 'YOUR-FACEBOOK-ID',
  applicationId : 'PARSE-APP-ID',
  javascriptkey : 'PARSE-JAVASCRIPT-KEY'
});
/**
*
* Aaron K. Saunders
* twitter: @aaronksaunders
* last updated may 23, 2014
*
* See more Appcelerator Information on Clearly Innovative Blog
*
* www.clearlyinnovative.com
* blog.clearlyinnovative.com
* http://www.clearlyinnovative.com/blog/post/34758525607/parse-appcelerator-titanium-the-not-so-easy-way
*
* http://www.clearlyinnovative.com
*
* Copyright 2014 Clearly Innovative, Inc.
* The Parse-Appcelerator JavaScript Hack is freely distributable under the MIT license.
*
*/
/**
* Edits to the parse library to work with this helper file
*
* Add this to line 1348
*<pre>
* // Import Parse's local copy of underscore.
* if (Titanium !== "undefined") {
* console.log("Using titanium");
*
* Parse._ = exports._.noConflict();
* exports.Parse = Parse;
* } else
*</pre>
*
* Replace line 8576
* <pre>
* Parse.User._registerAuthenticationProvider(FB.provider);
* </pre>
*/
var TiParse = function(options) {
debugger;
TiFacebook = require('facebook');
TiFacebook.appid = options.facebookAppId;
// UPDATED TO LATEST PARSE LIBRARY version parse-1.2.18
require("lib/parse-1.2.18");
//
// Override the Facebook object on Appcelerator
//
// Create the provider and the other methods the Parse Library is looking for
//
FB = {
provider : {
authenticate : function(options) {
var self = this;
TiFacebook.forceDialogAuth = false;
TiFacebook.authorize();
TiFacebook.addEventListener('login', function(response) {
if (response.success) {
if (options.success) {
options.success(self, {
id : response.data.id,
access_token : TiFacebook.accessToken,
expiration_date : (new Date(TiFacebook.expirationDate)).toJSON()
});
}
} else {
if (options.error) {
options.error(self, response);
}
}
});
},
restoreAuthentication : function(authData) {
debugger;
var authResponse;
if (authData) {
authResponse = {
userID : authData.id,
accessToken : authData.access_token,
expiresIn : (Parse._parseDate(authData.expiration_date).getTime() - (new Date()).getTime()) / 1000
};
} else {
authResponse = {
userID : null,
accessToken : null,
expiresIn : null
};
}
//FB.Auth.setAuthResponse(authResponse);
if (!authData) {
TiFacebook.logout();
}
return true;
},
getAuthType : function() {
return "facebook";
},
deauthenticate : function() {
this.restoreAuthentication(null);
}
},
init : function() {
Ti.API.debug("called FB.init()");
TiFacebook.appid = '175961759252181';
},
login : function() {
Ti.API.debug("called FB.login()");
},
logout : function() {
Ti.API.debug("called FB.logout()");
}
};
/**
* over write the local storage so it works on Appcelerator
*/
Parse.localStorage = {
getItem : function(key) {
return Ti.App.Properties.getObject(Parse.localStorage.fixKey(key));
},
setItem : function(key, value) {
return Ti.App.Properties.setObject(Parse.localStorage.fixKey(key), value);
},
removeItem : function(key, value) {
return Ti.App.Properties.removeProperty(Parse.localStorage.fixKey(key));
},
//Fix Parse Keys. Parse uses a Key containing slashes "/". This is invalid for Titanium Android
//We'll replace those slashes with underscores ""
fixKey : function(key) {
return key.split("/").join("");
}
};
//
// Enter appropriate parameters for initializing Parse
//
// options.applicationId, options.javascriptkey);
//
Parse.initialize(options.applicationId, options.javascriptkey);
/**
* Over write the _ajax function to use titanium httpclient
*
* @TODO Still looking for way to clean this up better
*
* @param {Object} method
* @param {Object} url
* @param {Object} data
* @param {Object} success
* @param {Object} error
*/
Parse._ajax = function(method, url, data, success, error) {
var options = {
success : success,
error : error
};
var promise = new Parse.Promise();
var handled = !1;
var xhr = Ti.Network.createHTTPClient({
timeout : 5e3
});
xhr.onreadystatechange = function() {
if (4 === xhr.readyState) {
if (handled)
return;
handled = !0;
if (xhr.status >= 200 && 300 > xhr.status) {
var response;
try {
response = JSON.parse(xhr.responseText);
} catch (e) {
promise.reject(e);
}
response && promise.resolve(response, xhr.status, xhr);
} else
promise.reject(xhr);
}
};
xhr.open(method, url, !0);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.send(data);
return promise._thenRunCallbacks(options);
};
//
// IF the appid was set for facebook then initialize facebook. if you are going
// to use Facebook, set the appid at the top of this file
//
if (TiFacebook.appid) {
Parse.FacebookUtils.init({
appId : TiFacebook.appid, // Facebook App ID
channelUrl : '//www.clearlyinnovative.com/channel.html', // Channel File - USE YOUR DOMAIN HERE !!
status : false, // check login status
cookie : true, // enable cookies to allow Parse to access the session
xfbml : true // parse XFBML
});
}
};
module.exports = TiParse;
@gstreetmedia
Copy link

Nice solution.

I couldn't get Android local storage to work without removing the forward slashes the Parse SDK adds to the key. My solution

Parse.localStorage = {
getItem : function(key) {
return Ti.App.Properties.getObject(Parse.localStorage.fixKey(key));
},
setItem : function(key, value) {
return Ti.App.Properties.setObject(Parse.localStorage.fixKey(key), value);
},
removeItem : function(key, value) {
return Ti.App.Properties.removeProperty(Parse.localStorage.fixKey(key));
},
//Fix Parse Keys. Parse uses a Key containing slashes "/". This is invalid for Titanium Android
//We'll replace those slashes with underscores ""
fixKey : function(key) {
return key.split("/").join("
");
}
};

@iantearle
Copy link

Sorry guys. But how do you include the module? Ive tried:

require('tiparse').TiParse;
require('tiparse');
var Parse = require('tiparse').TiParse;
var Parse = require('tiparse');

and each time I get Undefined variable Parse or some such error.

EDIT:
Found it. var TiParse = require("tiparse")();

@aaronksaunders
Copy link
Author

@gstreetmedia nice catch, and thanks for sharing

@chmiiller
Copy link

Hey guys, what about a new version of the JS Parse SDK (1.2.12) using TItanium?
This is the new description:
"Improves interaction between Parse.FacebookUtils and the Facebook Javascript SDK."
Looks good =]

@aaronksaunders
Copy link
Author

@chmiiller "Improves interaction between Parse.FacebookUtils and the Facebook Javascript SDK." creates a tighter integration with makes it WORSE for Titanium

@lesleyvanrijn
Copy link

Hey Guys,

I need to catch the error responses provided from Parse Cloud (beforeSafe). Works fine on iOS but does not seem to work on android. Do i need to change something to the hack? The values posted to parse do get stored in the object.

Trough adb i've noticed some errors caused by TiHttpClient but i don't know if this is the source of the problem.

[ERROR]TiHttpClient(26578) [9149,9149] HTTP Error (org.apache.http.client.HttpResponseException): Bad Request
[ERROR][TiHttpClient(26578)] org.apache.http.client.HttpResponseException: Bad Request
[ERROR][TiHttpClient(26578)] at ti.modules.titanium.network.TiHTTPClient$LocalResponseHandler.handleResponse(TiHTTPClient.java:252)
[ERROR][TiHttpClient(26578)] at ti.modules.titanium.network.TiHTTPClient$LocalResponseHandler.handleResponse(TiHTTPClient.java:211)
[ERROR][TiHttpClient(26578)] at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:657)
[ERROR][TiHttpClient(26578)] at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:637)
[ERROR][TiHttpClient(26578)] at ti.modules.titanium.network.TiHTTPClient$ClientRunnable.run(TiHTTPClient.java:1271)
[ERROR][TiHttpClient(26578)] at java.lang.Thread.run(Thread.java:856)

@gregorifaroux
Copy link

@aaronksaunders ; Thanks for TiParse... very helpful. I forked your code to update to parse-1.2.16; feel free to pull and merge to the main branch. Take care.

@adampash
Copy link

Small thing, but on line 64:

Parse.initialize(option.applicationId, option.javascriptkey);

...should be...

Parse.initialize(options.applicationId, options.javascriptkey);

@chmiiller
Copy link

great job! Gonna try it this week =]

@aaronksaunders
Copy link
Author

@chmiiller let me know how it goes

@frodeaux
Copy link

frodeaux commented Sep 9, 2014

Has anyone tried this with the 1.3.0 SDK?

@nitrag
Copy link

nitrag commented Feb 8, 2015

Copy link

ghost commented May 9, 2015

@nitrag - does 1.3.2 support Parse's JS-promises?

@nitrag
Copy link

nitrag commented Aug 26, 2015

@lj222kj not sure, haven't tried. I only use Promises on the CloudCode side.

Does anyone have any tips on how to use this in conjunction with Models/Collections?

@nitrag
Copy link

nitrag commented Dec 3, 2015

Updated to support a pseudo/hybrid "Save Eventaully" function.

https://gist.github.com/nitrag/57514857e78bb71bdf23

//create a "Test" class on Parse.com dashboard, add the column "foo"
var TestObject = Parse.Object.extend("Test");
var testObject = new TestObject();
testObject.set('foo', 'bar1234');

Parse.saveEventually.save("Test", testObject);

//fires via a button click
function saveNow(){
    if(Ti.Network.online){
        if(Parse.saveEventually.sendQueue())
            Parse.saveEventually.clearQueue();
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment