Phonegap 3.4.0, jQuery 1.9.1, jQuery Mobile 1.4.2.
I've posted other questions about issues with my app, but the underlying problem seems to be that my event listeners are not working correctly. This could either be that I've done it wrong, or there is a conflict.
I have this code in my javascript file:
function onPause() {
initialize();
navigator.app.exitApp();
}
function onResume() {
initialize();
}
function onBack(e) {
alert("running");
if($.mobile.pageContainer.pagecontainer( 'getActivePage' ).attr( 'id' ) == "login") {
e.preventDefault();
alert("halted");
navigator.app.exitApp();
}
}
function onDeviceReady(){
document.addEventListener("pause", onPause, false);
document.addEventListener("resume", onResume, false);
document.addEventListener("backbutton", onBack, false);
}
$( "body" ).load(function() {
document.addEventListener("deviceready", onDeviceReady, false);
});
However, none of the functions, onPause, onResume, or onBack are ever called. Which leads me to believe my event listeners are not correct or something is wrong. Am I missing something? Is there something I can check that might be causing this problem?
.load() is deprecated since version 1.8 of jQuery. So your event listeners are probably never added. .ready() would be the replacement for .load().
But you should think about using it anyway. At least in the way you are doing it now. Because there is no need to wait for the body to load to add an event listener and it might be possible that the "deviceready" event fires before the body is ready. So you would miss the event. I actually don't know if this could ever happen in a cordova app, but I wouldn't take the risk.
Related
I am writing a chrome extension, that has this content_script. I have written 3 functions to be triggered by 2 respective events - The double Click and Load function.
The Double Click event executes the function written for it, but, the load function or onload function are not executing their respective functions.
$("*").dblclick(function(){
alert("Double Click");
})
document.addEventListener ("onload", myMain, false);
function myMain (evt) {
alert("On Load");
}
document.addEventListener ("load", myMain, false);
function myMain (evt) {
alert("Load");
}
Using jQuery, here is my understanding of desired events :
$(window).on('load', function() {
alert('Loaded');
});
$(document).ready(function() {
alert('Ready');
});
$(window).on('dblclick', function() {
alert('Double click');
});
The difference between event 'load' and 'ready' is :
'Load' is triggered when your page is completely loaded (images,
charts ...).
'Ready' is triggered when your page script's is safe to manipulate.
Just check jQuery documentation for event on document loading : https://api.jquery.com/category/events/document-loading/
There is no event to trigger a document 'onload'.
You can use the DOMContentLoaded event in JS to achieve this. Like this:
window.addEventListener('DOMContentLoaded', myMain);
function myMain (evt) {
alert("Load");
}
Hope that's how you wanted it to work.
You can check here for more info - DOMContentLoaded Event
I have two event listeners pagecontainerbeforeshow and pagecontainershow, but both only fire when code is deployed to my Android devices (Nexus 6P, and the oldie Nexus S). When I launch the code in the Android Emulator (Nougat), the code doesn't fire, and there are no error messages.
MWE code snippet:
$(':mobile-pagecontainer').on('pagecontainerbeforeshow', function(event, ui) {
console.log('I AM HERE');
});
$(':mobile-pagecontainer').on('pagecontainershow', function(event, ui) {
console.log('I AM HERE 2');
});
What's weird is that I have other identical code (for other modularity needs) elsewhere in the project (but still loaded from the same DOM) which fires fine. Internally the other code uses a switch to differentiate specific pages (switch (ui.toPage.attr('id')) {), again its identical except for content of the event fired callback.
I can't figure out why everything works when deployed to a device, including a very old device such as a Nexus S, but it doesn't when deployed to an emulator.
It doesn't break. The pagecontainershow and pagecontainerbeforeshow simply doesn't get triggered.
Could it be something along the lines that the original page show events are consuming the event?
Any ideas?
Notes:
Jquery Mobile version: jquery.mobile-1.5.0-alpha.1.min.js
Figured it out - thanks deblocker.
tl;dr: Add the event listeners after the DOM ready event - in my case check for both DOM ready, and Cordova device ready.
$(function() { // DOM Ready
document.addEventListener("deviceready", onDeviceReady, false);
});
// Cordova device ready
function onDeviceReady() {
$(':mobile-pagecontainer').on('pagecontainerbeforeshow', function(event, ui) {
// This now works correctly
}
}
Cause
In my case, I wrongly interpreted the Cordova deviceready event, which says "However, JavaScript only loads once the DOM loads". I read this to mean that listening to the deviceready event would implicitly mean that the DOM is also ready - this is not the case.
Previous workaround
Change the Jquery selector to document:
$(document).on('pagecontainerbeforeshow', function (event, ui) {
console.log('I AM WORKING 1');
});
$(document).on('pagecontainershow', function(event, ui) {
console.log('I AM WORKING 2');
});
Now, all events are fired on my devices and in the Android emulator.
This works because document is available before the rest of the DOM is ready.
How can I refactor the below snippet to using jQuery.
window.onload = function () {
if (window.addEventListener) {
window.addEventListener("message", doSomething, false);
}
else {
if (window.attachEvent) {
window.attachEvent("onmessage", doSomething);
}
}
}
In jQuery, you can simply do this:
$(window).on("message", doSomething);
This attaches an event handler for the "message" event to the window object.
FYI, there's no need to wait for window.onload just to attach an event handler to the window object as it already exists so there's no need to wait.
If you did need to wait for some other reason, you could put it inside of:
// wait for all document resources to load
$(window).load(function() {
// code here
});
or
// wait for DOM to be loaded
$(document).ready(function() {
// code here
});
depending upon what you needed to wait for.
If 'onmessage' and 'message' are events specific to the window object, You can wrap the window in a jQuery wrapper $(window)
And then you can use jQuery's event system to bind those events with .on()
So it'd look something like this:
$(window).on('message', function(){ // do something });
$(window).on('onmessage', function(){ // do something });
You can read more about .on() at the jQuery API
Some people will tell you to use bind, but from the docs:
As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document. For earlier versions, the .bind() method is used for attaching an event handler directly to elements.
So, depending on your jQuery version, you'll either use on() or bind() accordingly.
Hope that helps!
I am loading an external script using jQuery's $.getScript function and it has something in it which I cannot understand:
if (!!window.addEventListener){ // FF
window.addEventListener('load', init, false);
} else if (!!window.attachEvent){ // IE
window.attachEvent('onload', init);
} else {
window.onclick = init;
}
Can someone please explain what this does?
I'm not sure but it adds some event listeners to check that the page is loaded.
But since I am loading the script with $.getScript function, I don't need those listeners anymore.
Is there a way to unbind them in the callback of the $.getScript function?
addEventListener adds event handlers, and attachEvent does the same for browsers that doesn't support addEventListener, which is just older IE.
The condition you have checks which one is available, and attaches an event handler to the window.onload event that calls the function init().
If none of the regular onload handler are available, it falls back to calling the init() function once the window is first clicked.
To remove the function, you'll have to try and do the opposite once the script has loaded.
You say you're using $.getScript, and that has a callback, so something like :
$.getScript('myscript.js', function() {
if (window.removeEventListener) {
window.removeEventListener( 'load', init, false );
}else if ( window.detachEvent ) {
window.detachEvent( 'onload', init );
}else{
window.onclick = function() {};
}
});
of course, it would be much easier and better to just remove the original event handler in the script you're loading if you no longer need that event handler.
I have strange problem for which I can't think of a solution. I have written some Javascript code to load some content through a AJAX call which also does some animation. To make the website functional I use jQuery with History.js. This is the script:
(function (window, undefined) {
getContent(true); // Function that gets the initial content via AJAX and does some animation
// The parameter specifies that the call to the function is onload
History.Adapter.bind(window,'statechange',function(event){
getContent();
});
function getContent(onload){
if(onload == true){
// Do onload stuff. Only slightly differs from other event calls
// If there is no state given define default one ie 'home'
alert('onload event triggered'); // For debug purposes
} else {
// Do other event stuff
alert('click event triggered'); // For debug purposes
}
}
somelinks.on('click',a,function(){ // Setup some eventlisteners that push the state });
})(window);
In browsers that support the HTML5 History/State API (Firefox, Chrome) this works flawless. On a load or reload of a specific url or on a click event the function does its work.
In IE it also works (with hashes ofcourse), however when I reload a page (ie example.com/#/test) the first as well as the second 'getContent()' function. So in Firefox a reload triggers the onload event alert, but in IE the onload event and the click event alert are triggered.
What I need is a way of structering my code or a logical check to prevent IE from calling the second getContent(). I've searched for similar problems (keywords: IE, History.js, etc.) but nothing to be found.
Hope somebody can help me with the problem.
(function (window, undefined) {
var getContentOK = true;
getContent(true);
History.Adapter.bind(window,'statechange',function(event){
getContent(false);
});
function getContent(onload){
if (getContentOK === true) {
if(onload == true){
// Do onload stuff. Only slightly differs from other event calls
// If there is no state given define default one ie 'home'
alert('onload event triggered'); // For debug purposes
} else {
// Do other event stuff
alert('click event triggered'); // For debug purposes
}
getContentOK = false;
setTimeout(function () {
getContentOK = true;
}, 500);
}
}
somelinks.on('click',a,function(){ // Setup some eventlisteners that push the state });
})(window);
This will throttle the statechange event handler to only run getContent() once every 500ms.
Notice that I added some boolean flags, one to throttle the statechange event handler and one to mimic your onload variable. firstRun will output true on the first run and then false on each subsequent runs.
This is not as good a solution as figuring out what is happening with the History.js plugin but I have no experience with it so I can't say why IE is firing two events.