I'm trying to dynamically load the phonegap javascript file (so that I can choose not to load it in debug mode when I'm using Ripple) but I'm running in to some issues.
I load the jquery and jquerymobile javascript libraries using a normal script tag. In another script block, I do:
function onDeviceReady() {
alert("Device Ready!");
}
$(document).ready(function() {
alert("doc ready!");
$.getScript("js/phonegap.0.9.5.1.js", function() {alert("Got Phonegap!");});
document.addEventListener("deviceready", onDeviceReady, false);
});
This code alerts that it "Got Phonegap!" but never alerts "Device Ready". Using jsconsole.com, I can see that the PhoneGap javascript object exists. However, trying to call device.uuid (or other simple phonegap API calls) fails. It's almost like PhoneGap didn't fully initialize. Doesn't seem like that should be the case though. Am I missing something? Thanks!
Finally I got it working without using any external library.
THE PROBLEM
For a multiplatform Phonegap project, two are the parts that differ from one platform to another:
Those encapsulating projects typically do not change much over the course of the project. It would be desirable to have a single HTML5 codebase that one could directly paste (or using build scripts) onto the platform-dependent projects. Since the javascript phonegap library is inside the set of web files, it's really painfull to replace the correct file each time.
MY SOLUTION
In my project I have several cordova files, one for each target platform:
(Notice how every one of these files is included in the app even if it is not used. For me it's not a problem, since the scripts are bundled in the app and only the one for the correct platform is loaded to memory).
In my pages, instead of a script tag for phonegap, I placed the loader module:
<script src="phonegap-loader.js"></script>
And this would be the phonegap-loader.js script. I make use of user-agent detection to dynamically and synchronously load the script:
(function(){
var useragent = navigator.userAgent;
if(/Android/i.test(useragent)){
loadScript('cordova.android.js');
} else if((/iPhone/i.test(useragent)) || (/iPad/i.test(useragent))){
loadScript('cordova.ios.js');
}
...
// Else desktop browser is assumed and no phonegap js is loaded
function loadScript(url){
// synchronous load by @Sean Kinsey
// https://stackoverflow.com/a/2880147/813951
var xhrObj = new XMLHttpRequest();
xhrObj.open('GET', url, false);
xhrObj.send('');
var se = document.createElement('script');
se.text = xhrObj.responseText;
document.getElementsByTagName('head')[0].appendChild(se);
}
})();
Its really important to load the script SYNCHRONOUSLY. This gave me innumerable headaches. Before realising this I tried adding scripts tags at the bottom of the head, and using $.getScript, but none worked, since ondeviceReady
was not fired. Looks like the only valid approach to ensure the Phonegap script is executed when loaded dynamically is the one shown in this amazing answer by @Sean Kinsey (all kudos to him).
The only drawback is that the script is inlined, but for me is a cheap price to pay for having the core HTML5 app finally isolated from the containers.
I was facing the similar issue where in which I need to load the PhoneGap and dependent plugin files based on the platform type. I went through the PhoneGap source and found that it uses the windows/browser events to load and prepare the objects. If I call the browser events manually then it initializes the PhoneGap objects (API and Plugins) I needed to run my application.
The following code which is using Yabble has worked for me now:
<html>
<head>
<script
src="https://raw.github.com/jbrantly/yabble/master/lib/yabble.js"></script>
<script>
require.setModuleRoot("js");
require.useScriptTags();
require.ensure([ "jquery", "phonegap" ], function(require) {
// Trigger PhoneGap Initialization
PhoneGap.onPhoneGapInit.fire();
// Load PhoneGap Plugins
require.ensure([ "plugin1" ], function() {
$("#console").append("Plugin1 loaded<br>");
});
// Both following functions will work only if PhoneGap is loaded/initialized and Plugin is successfully registered
// Check PhoneGap device object
$("#checkDevice").click(function() {
console.log(JSON.stringify(device));
});
// Call Native Plugin
$("#callPlugin").click(function() {
window.plugins.plugin1.call();
});
});
</script>
</head>
<body>
<div id="console"></div>
<input type="button" id="checkDevice" value="Check Device">
<input type="button" id="callPlugin" value="Call Plugin">
</body>
</html>
Both Device info and Plugin calls is working fine on Android. Although I have not checked all the PhoneGap API but as of now I need only these two to work and they are working.
Edit
In Phonegap 1.5/Cordova, PhoneGap.onPhoneGapInit.fire();
is not available due to API change. In my current test most of the required objects are available without any change after loading the JS dynamically. Updated test is available at this gist - Cordova Lazy Load Test
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With