Max
Max

Reputation: 1218

How to fire deviceready event in Chrome browser (trying to debug phonegap project)

I'm developing a PhoneGap application and I'd like to be able to debug it in Chrome rather than on the phone. However, I do the initialization of my code in an onDeviceReady() function that is triggered when PhoneGap fires the "deviceready" event. Since Chrome doesn't fire this event, my code isn't ever initialized.

Here's a stripped down version of my code:

var dashboard = {};

$(document).ready(function() {
    document.addEventListener("deviceready", dashboard.onDeviceReady, false);
}); 

dashboard.onDeviceReady = function() {
    alert("hello!"); //this is never fired in Chrome
};

I've tried using the StopGap code, which basically just does the following:

var e = document.createEvent('Events'); 
e.initEvent("deviceready");
document.dispatchEvent(e);

But when I run that code in the Chrome javascript console, the "hello" alert still doesn't trigger. What am I doing wrong? Or does chrome just not support firing "custom" events like deviceready?

Upvotes: 58

Views: 37411

Answers (9)

Pasquale Mangialavori
Pasquale Mangialavori

Reputation: 81

You simulate events like this:

const simulateEvent = (eventName, attrs = {customData:"data"}, time = 1000, target = document) => {
    let event = new CustomEvent(eventName, { detail:  attrs });    
    setTimeout(() => {
        target.dispatchEvent(event);
    }, time);
};

var divReady = document.querySelector('div#ready');

document.addEventListener('deviceready', (e) => {
 console.log("triggered with:", e.detail);
 divReady.innerHTML = `Ready! ${JSON.stringify(e.detail)}`;
});

simulateEvent('deviceready', {customData:"My custom data goes in event.detail"});
<div id="ready"> Wait for ready... </div>

Upvotes: 1

Max
Max

Reputation: 1218

Ended up pulling out the StopGap code and having to introduce a tiny delay (have this code running in a separate script than page-specific code):

window.setTimeout(function() {
    var e = document.createEvent('Events'); 
    e.initEvent("deviceready", true, false); 
    document.dispatchEvent(e);
}, 50);

Upvotes: 14

bladnman
bladnman

Reputation: 2651

user318696 had the magic I was looking for. "device" is defined in cordova and does not get defined when in a browser (non-phoneGap app wrapper).

EDITED:

I ran into a scenario where Cordova took quite a while to initialize on a device and the "original" answer here was no longer valid. I have moved on to requiring a parameter on the URL when running tests in the browser. (in the example I'm looking for "testing=" in the url of the original page)

$(document).ready(function () {

    // ALWAYS LISTEN
    document.addEventListener("deviceready", main, false);

    // WEB BROWSER
    var url = window.location.href;
    if ( url.indexOf("testing=") > -1 ) {
        setTimeout(main, 500);
    }

});

ORIGINAL:

I haven't dug deeply enough to know how long to trust this [could they start defining "device" in the browser in a future release?] But at least up to 2.6.0 this is safe:

$(document).ready(function () {
    // call main from Cordova
    if ( window.device ) {
        document.addEventListener("deviceready", main, false);
    }

    // from browser
    else {
        main();
    }
});

Upvotes: 6

TaeKwonJoe
TaeKwonJoe

Reputation: 1177

user318696's window.device detection works well. If using Kendo UI Mobile and PhoneGap, the following script will enable functionality in both PhoneGap builds and web browsers. This is based on Burke Holland's PhoneGap Build Bootstrap Project for Kendo UI Mobile and is intended to be placed at the bottom of the page before the closing body tag.

    <script type="text/javascript">
    var tkj = tkj || {};

    tkj.run = (function () {
        // create the Kendo UI Mobile application
        tkj.app = new kendo.mobile.Application(document.body);
    });

    // this is called when the intial view shows. it prevents the flash of unstyled content (FOUC)
    tkj.show = (function () {
        $(document.body).show();
    });

    (function () {
        if (!window.device) {
            //initialize immediately for web browsers
            tkj.run();
        }
        else if (navigator.userAgent.indexOf('Browzr') > -1) {
            // blackberry
            setTimeout(tkj.run, 250)
        } else {
            // attach to deviceready event, which is fired when phonegap is all good to go.
            document.addEventListener('deviceready', tkj.run, false);
        }
    })();
    </script>

Upvotes: 3

jerone
jerone

Reputation: 16881

For my mobile site and mobile App I'm using the following code with jQuery:

function init() { ... };
if ("cordova" in window) {
    $(document).on("deviceready", init);
} else {
    $(init);
}

Upvotes: 9

Page2PagePro
Page2PagePro

Reputation: 168

Enhancing Chemik suggestion. The following code uses navigator.userAgent string to generically determine if the client browser is on a mobile platform.

The purpose of the separation from desktop browsers is to allow code verifying prior to compiling/installing android apk, etc. It is much faster to make a quick code change, refresh desktop browser vs. compiling in eclipse and loading on android. Another added bonus is the ability to use weinre in one tab & the index.html from android assets in another tab (and use firebug).

PS: weinre code is excluded since it has my private VPS info & UUID.

thx!

<!-- Framework:jQuery -->
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.2, minimum-scale=1.0, maximum-scale=3.0, user-scalable=yes" >
<link  href="./framework/jquery/mobile/1.2.0/jquery.mobile-1.2.0.min.css" type="text/css" media="screen" rel="stylesheet" title="JQuery Mobile">
<script src="./framework/jquery/jquery-1.8.2.min.js"></script>
<script src="./framework/jquery/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>

<!-- Framework:Weinre -->

<!-- Framework:PhoneGap -->
<script src="./framework/phonegap/cordova-2.0.0.js" type="text/javascript" charset="utf-8"></script>

<script type="text/javascript" charset="utf-8">
    var mobile = false;
    if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
        document.addEventListener("deviceready", function(){mobile = true; onDeviceReady();}, false);
    } else {
        $(document).ready(onDeviceReady);   
    }
    function onDeviceReady() {
        setEvents();
        test();
        if (mobile) {
            navigator.notification.alert("Debugging-ready for\n" + navigator.userAgent);
        } else {
            alert("Debugging-ready for\n" + navigator.userAgent);
        }
    };
</script>

Upvotes: 1

Chemik
Chemik

Reputation: 1479

Add this code to your onLoad handler function:

    if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
        document.addEventListener("deviceready", onDeviceReady, false);
    } else {
        onDeviceReady();
    }

Event "deviceready" is fired in cordova.js so I don't know a way to detect existence of this event in application code.

Upvotes: 73

Katrina
Katrina

Reputation: 79

I use Safari for debugging and do this:

//my standard PG device ready
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
//debug("onDeviceReady")
getDefaultPageSetup();

}

//then add this (for safari
window.onload = function () {
if(! window.device)
    onDeviceReady()
}

Upvotes: 7

kirb
kirb

Reputation: 2049

Use the Ripple Mobile Emulator. It is free on the Chrome Web Store. When it is installed, navigate to the page you want to test it on, right click the page and choose Ripple Mobile Emulator > Enable. When prompted, choose PhoneGap.

The emulator is good, but it is still in beta so not everything has been implemented yet.

Ad@m

Upvotes: 8

Related Questions