PhoneGap Cloud Build: Correct facebookConnectPlugin installation - javascript

I'm sure this is going to be so trivial, but have had a number of tries and being the last thing I need to configure before I can deploy the private test is driving me mad.
This question extends off this question, my config.xml is established in the same way, this part is a no brainer. I have also got in my <head>:
<script type='text/javascript' src="./js/facebookConnectPlugin.js"></script>
I have tried both ./facebookConnectPlugin.js as well as ./js/facebookConnectPlugin.js, so part (a) of my question is, how can I determine what is the correct relative path without seeing the directory? I can't find its install location to verify.
Next part of the question follows the advice I received from somewhere, that instead of using the usual device ready event, to use the window.onload:
window.onload = onDeviceReady;
...
function onDeviceReady() {
onDeviceReadyFacebook();
...
}
...
function onDeviceReadyFacebook() {
// ?
}
window.fbAsyncInit = function () {
if (!window.cordova) {
// Initialize - only executed when testing in the browser.
facebookConnectPlugin.browserInit(<APP_ID>);
}
}
I have tried the window.fbAsyncInit both inside and out of the call I make for onDeviceReadyFacebook, trying to follow the advice from different forums...
So finally the error occurs within the call I have made to login:
function fb_login(){
var login_data = {};
client.cmd = "login";
login_data.userid = user_id;
login_data.cmd = "login";
facebookConnectPlugin.login([
'user_about_me',
'email',
'user_status',
'user_posts',
'user_photos',
'user_videos',
'user_friends'
],function(response) {
// success
...
Saying that the facebookConnectPlugin is undefined. After sligthly modifying different areas and everything else about the app is working, I would generally say that I'm not specifying the right source url for the primary JS file...
One last question on this topic: if I have correctly put in my Content Security Policy, is there any reason I need to use a plugin when I can just use the Facebook all.js they provide as is used in the browser version? I have got my key hash and other properties defined to add the android platform, I would have thought I can specify those attributes to match the platform...
EDIT: The plugin branch in question is located here.
UPDATE 2:
#JesseMonroy650:
Yes; a few things are definitely becoming clearer, but I did switch to cordova-plugin-facebookconnect-orlando, but adding that made the build crash, the log file result saying the message "...-FacebookLib/ant-build does not exist". I found the exact problem happening here, so I've now tried the same npm plugin and preference settings that was used there. It now builds, but I have the same problem (facebookConnectPlugin is undefined).
However, I checked the repo again this morning, specifically the path:
/platforms/android/assets/www/index.html
To see what I am crucially missing :
<div id="fb-root"></div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/facebookConnectPlugin.js">/script>
So hopefully if I copy off this example, I should be alright now. Will be trying again tonight.
Any help is always very appreciated!

The code added to index.html has finally resolved the issue. I tidied up the actual call to the login as demonstrated, but ultimately the variable wasn't found because I hadn't done the script include. Confusion over the scripts to include and what path they would be.
BIG relief!!! Props to you #JesseMonroy650 for steering me in the right direction of a deprecated plugin.

Related

Parse.View.extend - "cannot read property 'extend' of undefined"

Currently using the Parse JavaScript SDK for a web app, but I'm also new to Backbone, and since this particular problem is in functionality that Parse copied over from Backbone, I'm not sure exactly where I'm making my mistake.
I have index.html, with this basic structure & script template tag (to be used by _underscore):
<div id="my-app">
</div>
<script type="text/template" id="album-header-template">
<div id="some-id">
Some Content
</div>
</script>
At the end of <body>, the following script tags, to take care of Parse dependencies, load Parse, & use my own JS file:
<script src="libraries/node_modules/jquery/dist/jquery.min.js"></script>
<script src="libraries/node_modules/underscore/underscore-min.js"></script>
<script src="libraries/node_modules/parse/dist/parse-latest.min.js"></script>
<script src="app/ParseApp.js"></script>
Then in ParseApp.js, where I am trying to get off the ground by creating simple objects and views, I have the following:
$(function () {
var Album = Parse.Object.extend("Album",{
// Default attributes for the album
defaults: {
name: "Album Title"
},
// Ensure that each album created has a title
initialize: function() {
if (!this.get("name")) {
this.set({"name": this.defaults.content});
}
},
});
var HomeView = Parse.View.extend({
el: $("#my-app"),
initialize: function() {
console.log("new instance of HomeView");
this.render();
},
render: function() {
this.$el.html(_.template($("#album-header-template").html()));
}
});
new HomeView;
});
When I run index.html in the browser, I get the following error in console: Uncaught TypeError: Cannot read property 'extend' of undefined (occurring at the var Home View = Parse.View.extend line).
Originally, I had thought this might be because Parse wasn't initiated in time for ParseApp.js to use it, based on my scripts loading. However, I ran the recommended "Test the SDK" script from Parse, and it's indeed initialized (in addition, adding an object with var Album works fine). So I'm really stuck on what's causing either HomeView or Parse.View to be "undefined".
Likely a straightforward answer that I'm overlooking, but any help would be greatly appreciated, and I could provide full files if need be.
Not a very satisfying answer, but thanks to the help from #Yura & #Daniel Blank, discovered that the error was resulting because the most recent versions of the Parse SDK (everything after 1.6.0) no longer include full Backbone functionality. This includes the version I had been using locally from npm.
The best explanation of the Parse SDK direction is in the link given above, and there seem to be three options, for those hoping to continue using Parse and/or Backbone:
Use an old version (1.5.0 being the most recent that includes Backbone functionality) in order to maintain your Backbone functions, such as Parse.Collection or Parse.Router.
Try going Parse SDK-agnostic, while continuing to use Backbone. Can use the basic Parse REST API, or try one of the GitHub projects attempting to do that linking for you.
Give up on Backbone going forward, and use Parse with VanillaJS, or perhaps switch over to React (which is obviously the direction Facebook would want Parse to head)
I'm too inexperienced to recommend one of the three, although #1 seems the easiest, while #3 seems far and away the most maintainable. Still trying to make my own decision, but that's outside the scope of my original question. Thanks for the help, everyone.
2 things jump out at me:
I don't see where you initialize Parse... typically that
produces a different error, but still might be an issue
You are referencing your own local library for Parse... maybe try targeting the officially deployed version.
script src="http://www.parsecdn.com/js/parse-1.2.13.min.js"

NodeJS, SocketIO and Express logic context build

I read a lot about Express / SocketIO and that's crazy how rarely you get some other example than a "Hello" transmitted directly from the app.js. The problem is it doesn't work like that in the real world ... I'm actually desperate on a logic problem which seems far away from what the web give me, that's why I wanted to point this out, I'm sure asking will be the solution ! :)
I'm refactoring my app (because there were many mistakes like using the global scope to put libs, etc.) ; Let's say I've got a huge system based on SocketIO and NodeJS. There's a loader in the app.js which starts the socket system.
When someone join the app it require() another module : it initializes many socket.on() which are loaded dynamically and go to some /*_socket.js files in a folder. Each function in those modules represent a socket listener, then it's way easier to call it from the front-end, might look like this :
// Will call `user_socket.js` and method `try_to_signin(some params)`
Queries.emit_socket('user.try_to_signin', {some params});
The system itself works really well. But there's a catch : the module that will load all those files which understand what the front-end has sent also transmit libraries linked with req/res (sessions, cookies, others...) and must do it, because the called methods are the core of the app and very often need those libraries.
In the previous example we obviously need to check if the user isn't already logged-in.
// The *_socket.js file looks like this :
var $h = require(__ROOT__ + '/api/helpers');
module.exports = function($s, $w) {
var user_process = require(__ROOT__ + '/api/processes/user_process')($s, $w);
return {
my_method_called: function(reference, params, callback) {
// Stuff using $s, $w, etc.
}
}
// And it's called this way :
// $s = services (a big object)
// $w = workers (a big object depending on $s)
// They are linked with the req/res from the page when they are instantiated
controller_instance = require('../sockets/'+ controller_name +'_socket')($s, $w);
// After some processes ...
socket_io.on(socket_listener, function (datas, callback) {
// Will call the correct function, etc.
$w.queries.handle_socket($w, controller_name, method_name, datas);
});
The good news : basically, it works.
The bad news : every time I refresh the page, the listeners double themselves because they are in a loop called on page load.
Below, this should have been one line :
So I should put all the socket.on('connection'...) stuff outside the page loading, which means when the server starts ... Yes, but I also need the req/res datas to be able to load the libraries, which I get only when the page is loaded !
It's a programing logic problem, I know I did something wrong but I don't know where to go now, I got this big system which "basically" works but there's like a paradox on the way I did it and I can't figure out how to resolve this ... It's been a couple of hours I'm stuck.
How can I refacto to let the possibility to get the current libraries depending on req/res within a socket.on() call ? Is there a trick ? Should I think about changing completely the way I did it ?
Also, is there another way to do what I want to do ?
Thank you everyone !
NOTE : If I didn't explain well or if you want more code, just tell me :)
EDIT - SOLUTION : As seen above we can use sockets.once(); instead of sockets.on(), or there's also the sockets.removeAllListeners() solution which is less clean.
Try As Below.
io.sockets.once('connection', function(socket) {
io.sockets.emit('new-data', {
channel: 'stdout',
value: data
});
});
Use once instead of on.
This problem is similar as given in the following link.
https://stackoverflow.com/questions/25601064/multiple-socket-io-connections-on-page-refresh/25601075#25601075

PhantomJS Change JS src before he starts loading

I'trying to change Javascript src in order to get a "dev environment" for testing some Javascripts.
( Obviously i can't build a real dev environment , i can't mirror this website on a dev env ).
So i was thinking about manipulating Dom with PhantomJS and testing javascript with CasperJS. I wanna convert ( for example ) this script
<script type="..." language="..." src="production_path/source.js"></script>
into this one
<script type="..." language="..." src="dev_path/source.js"></script>
before the script starts loading.
I'm trying with
casper.start("http://www.example.com/",function(status){
var scripts = document.getElementsByTagName('script');
casper.each(scripts,function(self,my_script){
//here i would rewrite script url
});
});
casper.run();
but it doesn't work. I'm afraid i have to wait for something , but i'm not understanding what.
Taking a step back, is it okay to re-phrase your question as: how do I get PhantomJS to load "dev_path/source.js" when it tries to load "production_path/source.js"?
If so, write a onResourceRequested handler, and use the changeUrl function of the resourceRequest object.
It will be something like this:
casper.page.onResourceRequested = function(requestData, networkRequest) {
if(requestData.url == 'production_path/source.js'){
console.log("Changing request from production to dev for source.js");
networkRequest.changeUrl('dev_path/source.js');
}
};
Of course in a real situation I'd use a regex replace (as I expect there are multiple URLs to replace).
(Untested, so let me know if it does not work, and I'll look into it more carefully.)

Autoloading Javascript

I have a interesting concept I was working on and looking over, through various stack questions on auto loading JavaScript. I dint want to use a third party tool, aside form jquery, so I thought I would role my own. The concept I have is:
var scripts = {
'name' : 'path/to/script_dir/' // Load all scripts in this file.
}
requireScripts(scripts); // Requires all scripts
// Call your classes, methods, objects and so on ....
The requireScript() function would work something like:
function requireScript(hash){
$.each(hash, function(key, value)){
$.ajax({
url: value,
dataType: "script",
async: false,
error: function () {
throw new Error("Could not load script " + script);
}
});
});
}
Note: The above is just a concept, I don't think it will work.
The above would let you load SPECIFIC scripts. so in essence your hash key value would be 'name' : 'path/to/specific/script'. The issue this posses is that your hash would get rather large ....
The other issue I ran into is what if I simplified this to "php pear naming standard" so, as the trend seems to be - we would create a class, and it would be named after its location:
var some_folder_name_class = function(){}
Would be translated by the autoloader as: some/folder/name/class.js and then loaded that way.
To wrap up and get to my point there are two ways of loading javascript file I am looking at, via rolling my own "require" method. One is loading a directory of javascript files via the hash idea implemented above. (the provided code sample of how this hash would be walked through would have to be changed and fixed....I dont think it works to even load a single file)
OR
to have you just do:
new some_class_name() and have a global function listen for the new word, go find the file your trying to call based on the name of the class and load it, this you never have to worry - as long as you follow "pear naming standards" in both class and folder structure your js file will be loaded.
Can either approach be done? or am I dreaming to big?
I see a lot of frameworks do a bunch of require('/path/to/script') and if I could role my own autoloader to just allow me to either load a directory of js files or even have it where it listens for new before a class instantiation then I could make my life SO MUCH easier.
Have you consider using requirejs and probably Lazy loading.
http://www.joezimjs.com/javascript/lazy-loading-javascript-with-requirejs/
Here is sample version:
You can download here.
The sample is based on this folder structure :
public
index.html
scripts
app.js
lib
** jquery-1.10.2.js
** require.js
3 . From Code:
html
`<!DOCTYPE html><html>
<head><title>Sample Test</title>`
<script src="scripts/lib/require.js"></script> <!-- downloaded from link provide above-->
<script src="scripts/app.js"></script></head>
`<body><h1>My Sample Project</h1><div id="someDiv"></div></body></html>`
application configuration app.js
requirejs.config({
baseUrl: 'scripts',
paths: {
app: 'app',
jquery: 'lib/jquery-1.10.2' //your libraries/modules definitions
}
});
// Start the main app logic. loading jquery module
require(['jquery'], function ($) {
$(document).on('ready',function(){
$('#someDiv').html('Hello World');
});
});
jQuery-only option
If you are looking for a jQuery-only solution, have a look at jQuery.getScript(). It would be a great candidate for handling the script loading portion of your problem. You could then write a very small wrapper around it to load all the scripts—something like you wrote above:
var loadScripts = function(scripts) {
$.each(scripts, function(name, path) {
jQuery.getScript("/root/path/" + path + ".js");
})
}
If you are interested in more information on this approach, read this article by David Walsh.
Other great libraries
I strongly recommend taking a look at the current batch of script-loading libraries. I think that you will pleasantly surprised by what is out there. Plus, they come with the benefit of great community support and documentation. RequireJS seems to be the front runner but David Walsh has great articles on curl.js and LABjs.

Using SnapEngage with Emberjs cause a JS error

As soon as I add:
<script src="/bower_components/ember/ember.min.js"></script>
on the same page where there's our snagengage chat code:
<!-- begin SnapEngage code -->
<script type="text/javascript">
(function() {
var se = document.createElement('script'); se.type = 'text/javascript'; se.async = true;
se.src = '//commondatastorage.googleapis.com/code.snapengage.com/js/4f645e9b-afb9-4226-9ebc-f8fc52d28cef.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(se, s);
})();
</script>
<!-- end SnapEngage code -->
it provokes an error:
Uncaught TypeError: Cannot call method 'push' of undefined 4f645e9b-afb9-4226-9ebc-f8fc52d28cef.js:223
YAHOO.register 4f645e9b-afb9-4226-9ebc-f8fc52d28cef.js:223
(anonymous function) 4f645e9b-afb9-4226-9ebc-f8fc52d28cef.js:242
Anyone ever experienced this? Any suggestion about how to fix this?
PS: I tried removing that JS line and it works, that's definitively a conflict between Ember and some YAHOO library I guess.
Thanks!
I opened a ticket on this with SnapEngage and they recently pushed out a fix. If you had a SnapEngage account prior to Mar 6, 2014, then you need to click "Save" within the "Style" section of your account in order for the JS to be updated to the latest version. After this, the error should go away - worked for me!
NOTE: I am using Ember 1.4.0
I had this same issue and I think it was caused by a _super() on the YAHOO.register function cycling through line 233 twice. The first time it does it the variables k.versions and k.builds are defined, but the second time they are not (perhaps because the super reruns the YAHOO.register function without passing in any arguments. Regardless of exactly what caused it, I was able to remedy the issue (albeit in a VERY hacky way) by making the following edits to the snapengage.js source:
1) On line 233 change:
k.versions.push(p);k.builds.push(q);
to:
k.versions ? k.versions.push(p):false;k.builds ? k.builds.push(q):false;
All this does is check to see if the variables are defined and if they are, push to them. If not, do nothing.
I placed the edited snapengage.js source file in app/assets/javascripts/vendor/ and then added the following line to my application.js file:
//= stub ./vendor/snapengage.js
This will stop your ember application from loading the SnapEngage source when the app loads.
Finally, I wrote a chat mixin and loaded the snapengage.js script as follows:
App.Chat = Em.Mixin.create({
agentOnline: false,
didInsertElement: function() {
this._getChatApi();
},
_getChatApi: function() {
var url = 'assets/home/vendor/snapengage.js',
_this = this;
$.getScript(url).done(function() {
// Your custom SnapEngage Javascript API code here. For example...
SnapEngage.getAgentStatusAsync(function(online) {
_this.set('agentOnline', online);
});
});
},
});
App.IndexView = Em.View.extend(Home.Chat, {
// The rest of your view code here
});
The snapengage.js script won't load itself twice but if you're using the mixin on multiple pages you might want to make sure you're not loading the chat assets (images, loading spinner, etc) twice because the plugin seems to make a call to snapengage.com everytime you click on the 'help' button rendered on the webpage.
As I mentioned, it's a very hacky solution and I don't recommend editing the source code for plugins, but this will give you a fix to easily use Snapengage in an Ember.js app.

Categories