Calling Default Phonegap Back Button Handler - javascript

I have a phonegap app that requires I capture the back button. This works swimmingly but when I am at the main screen and the back button is pressed I want to call the original event handler and let the app close or do whatever comes naturally to the platform with such a press. I know I can tell the app to quit but understand this is bad form for iPhone apps.
No matter what I try (and I have tried many things) I cannot get the original handler to fire. Any advice?
In my code I have a switch statement inside my backbutton event handler that directs the app as needed to the effect of:
switch blahBlah
{
case 'this' :
doThis() ;
break;
case 'main' :
// What do I do here that is well behaved for all platforms???
break;
default:
doFoo() ;
}

Detect whenever you land on the main screen and remove your custom event handler.
document.removeEventListener( "backbutton", function(){}, false );
and add the event listener on the other pages (or sections).
document.addEventListener( "backbutton", OverrideBackButton, false );
Hope that helps.

This is what I've used and it seems to work fine for my needs
function pageinit() {
document.addEventListener("deviceready", deviceInfo, true);
}
function deviceInfo() {
document.addEventListener("backbutton", onBackButton, true);
}
function onBackButton(e) {
try{
var activePage = $.mobile.activePage.attr('id');
if(activePage == 'Options'){
closeOptions();
} else if(activePage == 'Popup'){
closePopup();
} else if(activePage == 'HomePage'){
function checkButtonSelection(iValue){
if (iValue == 2){
navigator.app.exitApp();
}
}
e.preventDefault();
navigator.notification.confirm(
"Are you sure you want to EXIT the program?",
checkButtonSelection,
'EXIT APP:',
'Cancel,OK');
} else {
navigator.app.backHistory();
}
} catch(e){ console.log('Exception: '+e,3); }
}
Hope this helps...

Cordova 7.x, at least on Android, doesn't seem to properly update the override state. As a consequence, #SHANK's answer doesn't work anymore.
As a workaround, you can disable back button overriding manually, resulting in default behavior:
navigator.app.overrideBackbutton(false);
To re-active custom handling, analogously do:
navigator.app.overrideBackbutton(true);
I filed a bug report on Apache's issue tracker regarding this.

Related

jQuery - detect change event triggered programmatically

I have a jQuery change event for when a user changes a given SELECT element. However the event may also be triggered by a third party script. What I want to do is detect whether the event was triggered programmatically or by the user.
I have tried the accepted solution in this question Check if event is triggered by a human
But note the JSFiddle in this answer is for a click event rather than a change event.
To demonstrate I amended the fiddle and created this one: http://jsfiddle.net/Uf8Wv/231/
If you try this in latest Firefox or Chrome, you will see that the alert human is being shown even when the event was triggered programmatically.
I have tried event.originalEvent.isTrusted but that doesn't work in all browsers. Can anyone help?
I have added mouseenter and mouseleave events. The idea is that it's a human if the click coincided with a mousepointer being over the element. See:
http://jsfiddle.net/Uf8Wv/232/
$("#try").mouseenter(function(event) {
mouseover = true;
});
// ... etc.
I can't think of any other way.
You can find some vague difference between click and emulated click using this code:
$(document).on('change', "#try", function (event) {
//some difference appear in the next line
console.log(event.delegateTarget.activeElement);
//no difference
if (event.originalEvent === undefined) {
alert('not human')
} else {
alert(' human');
}
event.delegateTarget = null;//doesn't help
});
$('#click').click(function (event) {
$("#try").click();
});
Click on the checkbox logs <input id="try" type="checkbox">.
Click on the button logs <button id="click">.
But...
Run $("#try").click(); from console before any clicks logs <body> and after the click result of the last click.
Generally JS can always fake any client event. So isTrusted is never trusted.
You can listen to the click event as well, and modify a variable. The change event seems indeed to be quite similar wheter it's a real click or a script triggered click, but the click on #try event won't be the same. And since click is triggered before change, you have time to set a switch.
Like this for example:
var realClick;
$("#try").change(function(event) {
console.log('change')
if (!realClick) {
alert('not human')
} else {
alert(' human');
}
});
$("#try").click(function(event) {
console.log('click')
// originalEvent is one way, but there will be many differences
if (event.originalEvent) {
realClick = true;
} else {
realClick = false;
}
});
// Since this is called from outside, better not put
// any controls here.
$('#click').click(function(event) {
$("#try").click();
});
http://jsfiddle.net/2xjjmo09/3/
What really worked for me is:
if ((event.originalEvent.isTrusted === true && event.originalEvent.isPrimary === undefined) || event.originalEvent.isPrimary === true) {
//Hey hooman it is you
//Real CLick
}
Tested with jQuery version 3.5
You can easily detect whether the click event on the button is actually triggered by mouse click or not. By doing,
$('#click').click(function(ev) {
if (ev.which !== undefined && ev.button !== undefined) {
$("#try").click();
}
});
Here's the Fiddle
Note: Beware of either ev.which or ev.button could result in 0 on some browser for left-click.
You can check for if event.srcElement (which is source element on which event is triggered) is equal to event.currentTarget something like:
$("#try").change(function(event) {console.log(event,event.target,event.currentTarget,event.srcElement)
if (event.currentTarget=== event.srcElement) {
alert(' human')
} else {
alert(' not human');
}
});
Fiddle: http://jsfiddle.net/Uf8Wv/234/

Stop onclick method running with jQuery

I have a button similar to below
<button id="uniqueId" onclick="runMethod(this)">Submit</button>
What I'm trying to do is stop the runMethod from running, until after I've done a check of my own. I've tried using the stopImmediatePropagation function, but this doesn't seem to have worked. Here's my jQuery:
$j(document).on('click', '#uniqueId', function(event) {
event.stopImmediatePropagation();
if(condition == true) {
// continue...
} else {
return false;
}
return false;
});
Note: runMethod basically validates the form, then triggers a submit.
What you want to do, especially in the way that you want to do it, requires a some sort of workaround that will always be a bit fiddly. It is a better idea to change the way the button behaves (e.g. handle the whole of the click event on the inside of the jQuery click() function or something along those lines). However I have found sort of a solution for your problem, based on the assumption that your user will first hover over the button. I am sure you can extend that functionality to the keyboard's Tab event, but maybe it will not work perfectly for mobile devices' touch input. So, bear in mind the following solution is a semi-complete workaround for your problem:
$(document).ready(function(){
var methodToRun = "runMethod(this)"; // Store the value of the onclick attribute of your button.
var condition = false; // Suppose it is enabled at first.
$('#uniqueId').attr('onclick',null);
$('#uniqueId').hover(function(){
// Check your stuff here
condition = !condition; // This will change to both true and false as your hover in and out of the button.
console.log(condition); // Log the condition's value.
if(condition == true){
$('#uniqueId').attr('onclick',methodToRun); // Enable the button's event before the click.
}
},
function(){
console.log('inactive'); // When you stop hovering over the button, it will log this.
$('#uniqueId').attr('onclick',null); // Disable the on click event.
});
});
What this does is it uses the hover event to trigger your checking logic and when the user finally clicks on the button, the button is enabled if the logic was correct, otherwise it does not do anything. Try it live on this fiddle.
P.S.: Convert $ to $j as necessary to adapt this.
P.S.2: Use the Javascript console to check how the fiddle works as it will not change anything on the page by itself.
Your problem is the submit event, just make :
$('form').on('submit', function(e) {
e.preventDefault();
});
and it works. Don't bind the button click, only the submit form. By this way, you prevent to submit the form and the button needs to be type button:
<button type="button" .....>Submit</button>
Assuming there's a form that is submitted when button is clicked.
Try adding
event.cancelBubble();
Hence your code becomes:
$j(document).on('click', '#uniqueId', function(event) {
// Don't propogate the event to the document
if (event.stopPropagation) {
event.stopPropagation(); // W3C model
} else {
event.cancelBubble = true; // IE model
}
if(condition == true) {
// continue...
} else {
return false;
}
return false;
});
Your code is mostly correct but you need to remove J:
$(document).on('click', '#uniqueId', function(event) {...
You also need to remove the onClick event from the inline code - there's no need to have it there when you're assigning it via jQuery.
<button id="uniqueId">Submit</button>

Capture all click events and discard unallowed

I develop a web GUI for a special tablet. This tablet is running with Linux and the used browser is Chromium. The application is a web application with PHP, HTML5, JQuery and JavaScript. Now I run into a problem. The screen is a touchscreen and the user is able to navigate through the application by touch the screen. However now we decided to add a feature for saving electricity. This feature will shutdown the background light after three minutes. To turn on the backlight again, the user should touch the screen again. This leads to this problem, because on any touch the buttons are also pressed even if the background light is shutdown. I want to prevent this by discarding all clicks on the touchscreen if a cookie is set. If this cookie is not set the touchscreen and the application should work as desired. How can I solve this problem?
I installed an event listener to register all clicks and to reset the time.
window.addEventListener('mousedown', function(e){
$.get('php/timeupdate.php', function(){});
}, false);
Code used to stop the execution:
$(document).on('click', function(event) {
$.get('php/getwakeup.php', function(e){
if(e==='true'){
//event.preventDefault(); // I tried all three possibilities
//event.stopImmediatePropagation();
event.stopPropagation();
}
});
});
You can try this:
$(document).on('click', function(event) {
// get your cookie
if( cookie is set ) {
event.stopPropagation();
}
});
event.stopPropagation(); stops every event handling from where you called it =)
EDIT:
You have to set your $.get call synchronous or do it completely diffrent. Take a look at the jQuery.Ajax documenation. There is a parameter called "async".
But be careful unless the call is ready nothing else will be executed on you page! So if your script doesn't answer nothing else will work on your site.
The better solution would be setting ja recurring call that will get the information you need. Set it to every two seconds (setInterval is your friend here). If your response is true than set a global variable that you can check in your onDocumentClick event.
window.isBacklightOff = false;
setInterval(function() {
$.get('php/timeupdate.php', function(e) { window.isBacklightOff = !!e; })
}, 2000);
$(document).on('click', function(event) {
// get your cookie
if( window.isBacklightOff === true ) {
event.stopPropagation();
}
});
When the back light goes off you can set some flag handleEvents=false;
So when the flag is on don't handle any events.
Now when the back light is on you can set handleEvents = true.
$(document).on('click', function(event) {
// get your flag say handleEvents
if( !handleEvents ) {
event.stopImmediatePropagation();
return;
} else {
//do your biz logic send ajax..etc
}
});
Reason why your code above is not working:
$(document).on('click', function(event) {
$.get('php/getwakeup.php', function(e){
if(e==='true'){
//event.preventDefault(); // I tried all three possibilities
//event.stopImmediatePropagation();
event.stopPropagation();
}
});
});
The function inside $.get is async and called on success in that you are setting the event to stop propagating...well by that time when the success function is called the event is already complete and has called all the listeners.
So in short you must not do the event stop propagation inside the success function.

Phonegap backbutton event, detect first page in history?

Adding a backbutton event listener to my Phonegap 2.0 mobile app prevents the user from exiting using the back key.
Before adding the event listener this was working: if the user visited N pages and clicked back N+1 times, the app would close (or go in the background for android 4.0 or higher).
Please see my code bellow.
document.addEventListener("backbutton", function(){
if (window.history.length == 0) { // this does not work
function quitApp(){
navigator.app.exitApp();
}
navigator.notification.confirm(
"Are you sure you want to quit?",
quitApp,
'App Title',
'Cancel,Ok');
return;
}
if (typeof(window.activePage.onBack) === 'function') {
window.activePage.onBack();
} else {
window.history.back();
}
}, false);
Any idea how i can achieve this: allow the user to exit using the back button while keeping my event listener?
Thanks!
Try to bind the back button on your title page, maybe something like this:
$('#home-page-title').bind( 'pageinit',function(event){
document.addEventListener("backbutton", function(){
navigator.app.exitApp();
}, false);
});

jQuery preventDefault() doesn't work like I expect - is this a jQuery Bug?

This is simplified code to exactly reproduce a problem I'm having with jQuery.
I would expect it to cancel the original click, then trigger the click event again which in turn would cause the browser to load the href of the url.
<script type="text/javascript">
$( function()
{
var confirmed = false;
$('a').click( function( event )
{
if ( confirmed == false )
{
event.preventDefault();
confirmed = true;
$(event.target).trigger( 'click' );
}
});
});
</script>
Original Question Here
I do not want to change window.location. I want to trigger so that any event handlers that have been bound to the click event will fire too. It just so happens that I also want the browser to follow the link.
.trigger('click') won’t trigger the browser’s default action — it will just trigger jQuery event handlers bound to that event on that element.
Take a look at this answer — you need to create and fire a click event yourself. Here’s the code from that answer:
function fireEvent(obj,evt){
var fireOnThis = obj;
if( document.createEvent ) {
var evObj = document.createEvent('MouseEvents');
evObj.initEvent( evt, true, false );
fireOnThis.dispatchEvent( evObj );
} else if( document.createEventObject ) {
var evObj = document.createEventObject();
fireOnThis.fireEvent( 'on' + evt, evObj );
}
}
Your event handler will always be run when you trigger a "click" event, and before the default behavior happens. So no, it's not a bug.
edit — If you want the default action to happen when the element is clicked and your various conditions are satisfied, just return from your handler.
$('a').click( function( event )
{
if ( confirmed == false )
{
event.preventDefault();
confirmed = true;
}
else
return;
});
When your handler returns, the browser will carry on with the default behavior.
edit again — and of course if you want to simply carry out programmatically the default action of an <a> tag with an "href" attribute, it's just:
window.location = $(element).attr('href');
No need for a "click" event at all.
preventDefault() doesn't cancel the jquery bound click action; it cancels the 'default' click action that is inherent to an anchor tag. unbind() is the proper function for canceling any action/function that is bound to an object.
It looks like you have one state where you want to inhibit the default action (and update a flag), and another state where you simply want the default action to apply. Wouldn't removing the else case entirely do the trick? With no preventDefault() the default click action will still run.
Edit: Pointy's answer now shows your code updated similarly.
Edit: I'm still not entirely sure what you're going for, but if for some reason you must trigger manually, one way to prevent a stack overflow due to recursion would be to assign a custom event (i.e., not click), and then always suppress the default action. Then in your conditional, either do or don't fire the custom event.
So, something like this (untested):
$('a')
.bind('fancyclick', function () { // Your special click logic
changeStatusOf( confirmed );
doCrazyStuff();
location.replace( $(this).attr('href') ); // or whatever
})
.click( function (e) {
e.preventDefault(); // Always suppress natural click
if ( confirmed ){
$(this).trigger('fancyclick'); // Fire the special click
}
});
I'll simply write while I analyse, hoping it'll be easy to follow and easy to compare to your code. Kick me when I can optimize/enhance my replies in any way.
checking - part 1
Move the "preventDefault" outside of the "if" statement! If you don't move it outside of the "if", the code will skip the "preventDefault" if confirmed == true.
<script type="text/javascript">
$( function()
{
var confirmed = false;
$('a').click( function( event )
{
event.preventDefault();
if ( confirmed == false )
{
confirmed = true;
$(event.target).trigger( 'click' );
}
});
});
</script>
checking - part 2
Besides that, I'm wondering about the existence of "var confirmed" in general. The code would also work flawless without it since you're not using the confirmed variable in the function anywhere else...
<script type="text/javascript">
$( function()
{
$('a').click( function( event )
{
event.preventDefault();
$(event.target).trigger( 'click' );
});
});
</script>
checking - part 3
Knowing you can replace the trigger with a simple click, did you try that?
<script type="text/javascript">
$( function()
{
$('a').click( function( event )
{
event.preventDefault();
$(event.target).click();
});
});
</script>
checking - part 4
If the click still fails on the target element, it's definitely time to inspect (using "FireBug on Firefox" or alike) if "event.target" holds an object at all. You never know...
checking - part 5
One more thing: I don't see any Document Ready checking, so I hope you've put that script at the end of your file, right before the "</body>" tag. If you load it in the "<head>" without checking Document Ready, it might happen that javascript tries to bind the event to an element that is yet to be loaded into the dom... which would be like throwing feathers against a 9 Inch steel plate... nothing will happen. ;)
that's all
That's all that comes to mind as an answer to your question. One of them could fix the issue you're having. At least, that's what I hope. These little snippets here at stackoverflow leave massive probabilities related to what we don't see. It's hard to be sure what might be missing when you don't have the "complete view". ;)
How about doing something like creating a link offscreen that would handle the final click? That way, you can prevent the click of the original link, handle the code, then proceed to trigger the click of the hidden copy.

Categories