I have a cordova (android) app with window popout using window.open javascript that override with cordova inAppBrowser when device is ready refer to the code below:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
window.open = cordova.InAppBrowser.open;
}
Then i want to set an event when user press phone back button or press "x" button to close the popout a dialog will pop out and asked "Are you sure? Y/N" before closing window popout. The code look like this:
var newwindow;
newwindow = window.open('something', '_self ', 'location=no');
newwindow.addEventListener('exit', function(event){ Exit() });
function Exit(){
navigator.notification.confirm(
'Are you sure?',
function(i){
if(i==2)
{
//exit the window popout
}
},
'App Name',
'Cancel,Exit'
);
But it doesn't work as i wanted, the popout window closed then dialog is prompt to user...How can i show a dialog and decides whether to close popout window.
Note: Sorry for bad grammar, i try my best to explain my problem.
I have found a fairly easy solution (android) for simple prompt like "Are you sure" "yes/no?" by editing the inappbrowser.dialog.java file. This solution is only prompting for confirmation before closing inappbrowser, which is suitable for my case.
Modify the java file InAppBrowserDialog.java in this location:
[your cordova project]/platforms/android/src/org/apache/cordova/inappbrowser/
ADD REQUIRED IMPORTS:
import android.content.DialogInterface;
MODIFY THE onBackPressed() FUNCTION
FROM:
public void onBackPressed () {
if (this.inAppBrowser == null) {
this.dismiss();
} else {
// better to go through the in inAppBrowser
// because it does a clean up
if (this.inAppBrowser.hardwareBack() && this.inAppBrowser.canGoBack()) {
this.inAppBrowser.goBack();
} else {
this.inAppBrowser.closeDialog();
}
}
}
TO:
public void onBackPressed() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context)
.setTitle("Exit")
.setMessage("You are about to exit, are you sure?")
.setPositiveButton("Exit", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
if (inAppBrowser == null) {
dismiss();
}
else {
// better to go through the in inAppBrowser
// because it does a clean up
if (inAppBrowser.hardwareBack() && inAppBrowser.canGoBack()) {
inAppBrowser.goBack();
} else {
inAppBrowser.closeDialog();
}
}
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog,int which){
dialog.cancel();
}
});
alertDialogBuilder.create();
alertDialogBuilder.show();
}
I basically just create an alert dialog on top of checking for inappbrowser when back button is pressed.
Related
I make a fullcalendar in my tapestry 5.4 web page.
When I make a new Event or I click an existing event, the fullcalendar's method is called (select or eventClick). In these methods tapestry js method is called (zoneManager.deferredZoneUpdate("formZone", listenerURIWithValue);), because I want to refresh my jQuery dialog div (#formZone) what is a tapestry zone. And it works well functionally, the data appears.
However, I always see the refreshing "procedure" because after the zone-update part, the jQuery dialog is opened, but the refresh is not ending (I know because ajax call is asynchronous) and it causes an "ugly" refresh after the jQuery dialog is opened.
My goal is to define a callback function for deferredZoneUpdate or make this code sequence:
...
zoneManager.deferredZoneUpdate("formZone", listenerURIWithValue);
$('#wsDialog').dialog('open');
...
Thanks for the answers in advance!
Update:
calendar-init.js:
define(["jquery" , "t5/core/zone"], function($, zoneManager) {
return function(modifyEventLink, newEventLink, pageTurnLink, allDayText) {
$(document).ready(function() {
var calendarDiv = $('#calendar');
calendarDiv.fullCalendar({
//....init
eventClick: function(calEvent, jsEvent, view) {
// create modifyeventlink with id param
var listenerURIWithValue = appendQueryStringParameter(modifyEventLink, 'eventID', calEvent.id);
// ajax zone update
zoneManager.deferredZoneUpdate("formZone", listenerURIWithValue);
// open the worksheet dialog
$('#wsDialog').dialog('option', 'title', calEvent.title);
},
//...init
});});}}) // the code syntacs is good dont bother these :D
backend:
void onModifyEventLink() {
if(request.isXHR()) {
logger.debug("ModifyEventLink on.");
String eventID = (String) request.getParameter("eventID");
if(eventID == null) {
logger.error("wsDialog was not able to load because eventID is NULL!");
} else {
try{
wSheet = sheetService.find(Integer.valueOf(eventID));
if(wSheet != null) {
ajaxResponseRenderer
.addCallback(new JavaScriptCallback() {
#Override
public void run(JavaScriptSupport javascriptSupport) {
javascriptSupport.require("wsdialogs");
}};)
.addRender(formZone);
} else {
logger.warn("Worksheet with " + eventID + " not found.");
}
} catch (NumberFormatException e) {
logger.error("wsDialog was not able to load beacause eventID was not a number.");
logger.error("Exception: ", e.getLocalizedMessage());
}
}
} else {
logger.debug("ModifyEventLink on, request is not XHR (ajax)");
}
}
(module) wsdialogs.js:
define(["jquery" , "t5/core/zone"], function($, zoneManager) {
console.log("wsdialog-js run");
$("#wsDialog").dialog('open');
});
tml:
<t:container
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p="tapestry:parameter">
<t:jquery.dialog t:clientId="wsDialog" t:id="wsDialog" title="${message:wsheet-new}" style="display: none;">
<t:zone t:id="formZone" id="formZone">
<t:form t:id="worksheetForm" t:type="form" t:zone="^">
....
</t:form>
</t:zone>
</t:jquery.dialog>
</t:container>
public class ComponentWithZone {
#Inject
private AjaxResponseRenderer ajaxResponseRenderer;
...
public void onSomeEventFromClient() {
ajaxResponseRenderer.addRender("zone-id-to-update", zone.getBody()).addCallback(new JavaScriptCallback() {
#Override
public void run(JavaScriptSupport javascriptSupport) {
javascriptSupport.require("modal").invoke("showModal").with("#dialog-id");
}
});
}
}
This example is with bootstrap modal included as tapestry module.
When tapestry refresh zone div with content it will trigger showModal function.
UPD: Forgot to mention that this example assumes that you have modal module.
Here is example of mine:
(function(){
define(["jquery", "bootstrap/modal"], function($, modal) {
return {
showModal: function(id) {
$('#'+id).modal('show');
},
hideModal: function(id) {
$('#'+id).modal('hide');
}
};
});
}).call(this);
Instead of bootstrap/modal you can use any module, but don't forget to include it in META-INF/modules.
I'm developing an android app using HTML & JS, (will use PhoneGap after successful development) and I want the app to alert the user if his device is not connected to WiFi or Mobile data, and the app should close after the alert.
I tried this for reference:
How to alert the user when there's no internet connection
However, it doesn't seem to work for me.. Please suggest some other alternative for the same.
Sorry because I don't have enough repulation to comment.
To close the app, you could use:
navigator.app.exitApp();
public void onCreate(Bundle obj)
{
super.onCreate(obj)
setContextView(layout);
if (isOnline())
//do your task
else
{
try {
AlertDialog alertDialog = new AlertDialog.Builder(con).create();
alertDialog.setTitle("Info");
alertDialog.setMessage("Internet not available,try again later.");
alertDialog.setIcon(android.R.drawable.ic_dialog_alert);
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDialog.show();
}
catch(Exception e)
{
Log.d(Constants.TAG, "Show Dialog: "+e.getMessage());
}
}
}
I've got a function that makes use of the back button on Android Phones but for some reason when I use it, the app goes back 2 pages instead of the intended one.
This is what my code looks like at the moment:
function onBackKeyDown()
{
currentPage = $.mobile.activePage.attr('id');
if(currentPage == "createUser")
{
$.mobile.changePage("#logIn");
alert("Return To Login Page");
currentPage = "";
}
else if(currentPage == "cardDetails")
{
$.mobile.changePage("#createUser");
alert("Return To Create User");
currentPage = "";
}
else if(currentPage == "mainMenu")
{
$.mobile.changePage("#logIn");
alert("Return To Log In");
currentPage = "";
}
else if(currentPage == "locationPage")
{
$.mobile.changePage("#mainMenu");
alert("Return To Main Menu");
currentPage = "";
}
else if(currentPage == "editUserPage")
{
$.mobile.changePage("#mainMenu");
alert("Return To Main Menu");
currentPage = "";
}
else if(currentPage == "editCardDetailsPage")
{
$.mobile.changePage("#editUserPage");
alert("Return To Edit User");
currentPage = "";
}
else
alert("TEST");
}
For example if I were to be incardDetailsand I pushed the back button it would go back tocreateUserand continue back tologIn. Is there anything in my code that would cause this, I've tried resetting the currentPage to empty and added in else thinking that it was going though each of them individually when they were just if statements
EDIT: Requested Java Code:
import android.os.Bundle;
import org.apache.cordova.DroidGap;
public class FnBApp extends DroidGap {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
super.loadUrl("file:///android_asset/www/index.html");
}
}
Any help would be appreciated
John
You need to overload the android back button instead of just detecting and acting on it.
remove your key listener or return true when you have KEY_BACK
you just need the following to catch back key (make sure not to call super)
Also, if you plan on having a service run in the background, make sure to look at startForeground() and make sure to have an ongoing notification or android will kill your service if it needs to free memory
#Override
public void onBackPressed() {
Log.d("CDA", "onBackPressed Called");
Intent setIntent = new Intent(Intent.ACTION_MAIN);
setIntent.addCategory(Intent.CATEGORY_HOME);
setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(setIntent);
}
Update: Changes for app specific psuedocode
public class FnBApp extends DroidGap {
....
#Override
public void onBackPressed() {
Log.d("CDA", "onBackPressed Called");
//if super.getUrl shows a specific page:
if() {
super.loadUrl("file://android_asset/www/index.html#login");
};
}
Android - How To Override the "Back" button so it doesn't Finish() my Activity?
If you are using Cordova, maybe you want to use your code in other devices apart from Android? In which case you don't want to use any Java at all. Going back to the original question, would this help?:
function onDeviceReady() {
// Register the event listener
document.addEventListener("backbutton", onBackKeyDown, false);
}
(taken from this post)
I have created a webview in Android in which i am loading my html file.At the time of clicking a button i am displaying a pop up like alert dialog which is developed in html itself.
Now problem is as soon as i press back button on android phone,application is returning to previous page.But with identical behavior only dialog should be closed and application should be on same page.
How can i achieve it?
Thanks
I think you do not need the JavascriptInterface (as #Henil posted). I would do it like so:
in Java - onBackPressed:
if (webView.getUrl.equals("yourPopupUrl.com")) {
webView.loadUrl("javascript:goAwayPopup();");
return;
}
in JS:
function goAwayPopup() {
var popUp = document.getElementById("popUp"); // in my case popUp is just a <div>
var isVisible = popUp .offsetWidth > 0 || popUp .offsetHeight > 0;
if (isVisible) {
popUp.style.display = 'none';
}
}
EDIT:
Solution with JavascriptInterface:
in JS - function which is called when dialog popups:
function popUp() {
if (typeof Android != "undefined"){
if (Android.popUp!= "undefined") {
Android.popUp();
}
}
}
in Java:
define a inner class and a boolean field in your Activity
declare the bridge to your webview
override onBackPressed
private boolean isPopUpVisible = false;
// some code...
webView.addJavascriptInterface(new MyJavascriptBridge(), "Android");
// some code...
class MyJavascriptBridge {
public void popUp() {
if (isPopUpVisible)
isPopUpVisible = false;
else
isPopUpVisible = true;
}
}
onBackPressed:
if (isPopUpVisible) {
webView.loadUrl("javascript:goAwayPopup();");
return;
}
JS, again:
function goAwayPopup() {
// close alert here...
popUp(); // sets isPopUpVisible to false
}
Here is a post of closing a alert: How to "auto close" Alert boxes
Use java script interface and handle html page from that interface
I have a webview that shows a message to confirm an user interaction. That message should fade out after any user interaction somewhere else on that page. To do this I detect any onTouchEvent and inject back a call to the webpage to trigger the message to fade out.
This works well for the first time but if I do it a second time (the webpage is not reloaded but the message is shown again through javascript by setting opacity back to 1 and display to "block") the message appears again but then fades out immediately w/o any user interactions. From the log statement I can see that the onTouchEvent does not get triggered and I do not inject the javascript.
I suspect that the loadURL creates some resilient call in the webpage that sticks around and somehow activates again.
Is there any way to clear this and see this executed only once ?
I catch the onTouchEvent in my WebView like this:
final class MyWebView extends WebView {
...
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.v(TAG,"onTouchEvent");
if (mUndoActive && (event.getAction() == MotionEvent.ACTION_DOWN)) {
mUndoActive = false;
mLastAction = LAST_ACTION_NONE;
Log.v(TAG,"send hide message");
handler.sendEmptyMessageDelayed(CLICK_ON_WEBVIEW, 300);
}
return super.onTouchEvent(event);
}
}
In the parent activity I override the handleMessage and inject a javascript to my webview to trigger the javascript that fades out a message element like this:
#Override
public boolean handleMessage(Message msg) {
Log.v(TAG,"handleMessage triggered");
if (msg.what == CLICK_ON_WEBVIEW){
Log.v(TAG,"handle message registerd click from stack view web page");
webview.loadUrl("javascript:hideMessage()");
return true;
}
return false;
}
and the javascript in the webview is:
function hideMessage() {
var message = document.getElementById("message");
if (message != null) {
if (!message.style.opacity) {
message.style.opacity = 1;
}
var fader = setInterval(function(){
message.style.opacity -= .02;
if (message.style.opacity <= 0) {
clearInterval(fader);
message.style.display = "none";
}
}, 25);
}
}
I found a soulution myself: Preceding the 2 Interval calls with window, ie. window.clearInterval(fader) did fix the issue. I don't quite understand why but it looks like the interval timer did keep running permanently and was not properly turned off.