I am using the following piece of code in my PhoneGap app.
function registrationCallBack(button){
if(button == 2) {
window.location.href = "login.html";
}
}
navigator.notification.confirm("Are you sure ?", registrationCallBack, "Confirmation", "Cancel, Ok");
The order of the buttons is coming properly as "Cancel" and "Ok" in iPhone.
But for Android the order of buttons are reversed. Its coming as "Ok" and then "Cancel".
As a result the button indices are getting changed in the callback method.
All suggestions are welcomed :)
Thanks,
Try using the following solutions:
function showConfirm(message, callback, buttonLabels, title){
//Set default values if not specified by the user.
buttonLabels = buttonLabels || 'OK,Cancel';
title = title || "default title";
//Use Cordova version of the confirm box if possible.
if(navigator.notification && navigator.notification.confirm){
var _callback = function(index){
if(callback){
callback(index == 1);
}
};
navigator.notification.confirm(
message, // message
_callback, // callback
title, // title
buttonLabels // buttonName
);
//Default to the usual JS confirm method.
}else{
invoke(callback, confirm(message));
}
}
And here is how you would use it:
var message = "Would you like to proceed?";
var title = "Important Question";
//The first element of this list is the label for positive
//confirmation i.e. Yes, OK, Proceed.
var buttonLabels = "Yes,No";
var callback = function(yes){
if(yes){
alert('Proceed');
}else{
alert('Do Not Proceed');
}
};
showConfirm(message, callback, buttonLabels, title);
This is not an Issue. What ever you are getting is native behavior of respective platform. In iOS, "Cancel" button will appear on left side and in Android you will get it on Right side. If the problem is only button index, then you can handle it in your code. But you cannot change the sequence of the buttons on screen.
I haven't tried this in iphone. But have tried this in android. I didn't face any such issues with phonegap 1.4.1. Hence i suggest you to upgrade your phonegap version. Issue you faced might be fixed in their new release. :)
I'm a bit late but I had the same problem, however what I did was change them around so "Cancel" goes where "Ok" is and "Ok" goes where "Cancel" is. That worked for me.
Related
I'm building a little browser app using android webview and I've been using window.getSelection() in javascript to get the nature of any text selected by the user and show a custom context menu based on the type of the selection i.e. whether it's a range, a carat, whether it's in a contenteditable etc.
This works fine unless the selection is in an iframe, then the browser security measures kick in and prevent me sniffing what has been selected using window.getSelection(). How can I workaround this?
Ideally I need a way to get better information about what was selected from the webview or if that's not possible I need a way to sniff whether the selection occurred in an iframe so I can disable my custom context menu logic and fallback to the default android context menu.
UPDATE/FURTHER CLARIFICATION 07/05/2019:
Seems I wasn't clear enough in my initial description...
My goal is to have a visually and functionally custom menu when selecting content in the webview that can cut/copy/paste as the standard context menu does in any part of the page/iframes etc. e.g.
I realised my original approach using javascript to detect the type of selection and to perform the cut/copy/paste was wrong because it will be blocked by cross origin security in iframes.
What I need is a native android/webview based approach. I've discovered that I can sniff the type of selection in the webview by looking at the items in mode.getMenu() on onActionModeStarted. This will allow me to show the correct buttons in my custom menu UI but I have been unable to manually trigger the same logic that gets called when cut/copy/paste is clicked. I thought I found the solution with webView.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CUT, null); but this doesn't work for some reason so I guess my question really is how can I manually trigger cut/copy/paste on the selected text from webview without using javascript? or any other approach that will allow me to have a custom selection menu with lots of options based on what was selected without hitting the browser security limitations?
Okay I figured out how roughly how to do this.
Step 1) In your activity, override onActionModeStarted and check the menu items available in the default context menu. This gives you a clue as to what the type of selection is and which buttons you will need to show in your custom menu. Also it gives you a reference to the item ID which you can use to later to trigger the action e.g.
systemSelectionMenu = mode.getMenu(); // keep a reference to the menu
MenuItem copyItem = systemSelectionMenu.getItem(0); // fetch any menu items you want
copyActionId = copyItem.getItemId(); // store reference to each item you want to manually trigger
Step 2) Instead of clearing the menu, use setVisible() to hide each menu item you want a custom button for e.g.
copyItem.setVisible(false);
Step 3) In your custom button onclick event you can trigger the copy action using:
myActivity.systemSelectionMenu.performIdentifierAction(myActivity.copyActionId, 0)
You can retrieve iframe's selection only if it has the same origin. Otherwise, you have no chances to track any iframe's events(clicks, touches, key presses, etc.).
const getSelectedText = (win, doc) => {
const isWindowSelectionAvailable = win && typeof win.getSelection != "undefined";
if (isWindowSelectionAvailable) {
return win.getSelection().toString();
}
const hasDocumentSelection = doc && typeof doc.selection != "undefined" && doc.selection.type == "Text";
if (hasDocumentSelection) {
return doc.selection.createRange().text;
}
return '';
}
const doIfTextSelected = (win, doc, cb) => () => {
const selectedText = getSelectedText(win, doc);
if (selectedText) {
cb(selectedText);
}
}
const setupSelectionListener = (win, doc, cb) => {
doc.onmouseup = doIfTextSelected(win, doc, cb);
doc.onkeyup = doIfTextSelected(win, doc, cb);
}
const getIframeWinAndDoc = (iframe) => {
try {
const doc = iframe.contentDocument || iframe.contentWindow.document;
const win = iframe.contentWindow || iframe.contentDocument.defaultView;
return { win, doc };
} catch (e) {
console.error(`${e}`);
return {};
}
}
const callback = console.log;
setupSelectionListener(window, document, callback);
document.querySelectorAll('iframe').forEach(iframe => {
const { win, doc } = getIframeWinAndDoc(iframe, console.log);
// Only for same origin iframes due to https://en.wikipedia.org/wiki/Same-origin_policy
if (win && doc) {
setupSelectionListener(win, doc, callback);
}
})
<h3>Select me</h3>
<div class="container">
<iframe src="https://teimurjan.github.io"></iframe>
</div>
This issue varying from browser to other if it works with internet explorer so it may fall with chrome
Try this
App.util.getSelectedText = function(frameId) {
var frame = Ext.getDom(frameId);
var frameWindow = frame.contentWindow;
var frameDocument = frameWindow.document;
if (frameDocument.getSelection) {
return frameDocument.getSelection();
}
else if (frameDocument.selection) {
return frameDocument.selection.createRange().text;
}
};
Hope it runs fine
Main problem is the window.getSelection() will return selection only for the main context/window. As iframe is the other window and other context, you should call getSelection() from iframe which is "current".
When I use this code:
function dialogConfirm() {
var message = "Am I Confirm Dialog?";
var title = "CONFIRM";
var buttonLabels = "YES,NO";
navigator.notification.confirm(message, confirmCallback, title, buttonLabels);
function confirmCallback(buttonIndex) {
navigator.notification.alert("You clicked " + buttonIndex + " button!",null,"helo","Nic");
}
}
However on android when I deploy with Cordova and I click on one of the btns of confirm the alert does not popUp so I tried with some text and I found out that the function confirmCallBack is never called whatever btn I click so does anyone know what can I do to call the confirmCallBack function or is it just a bug with the plugin in android. I remind you that on Windows Browser it works perfectly so the issue is either with the library or with my device it is a Moto G 3rd Generation android 7.0.1 Thanks in advance!
Your options buttons are a string instead of an array.
message: Dialog message. (String)
confirmCallback: Callback to invoke with index of button pressed (1,
2, or 3) or when the dialog is dismissed without a button press (0).
(Function)
title: Dialog title. (String) (Optional, defaults to Confirm)
buttonLabels: Array of strings specifying button labels. (Array)
(Optional, defaults to [OK,Cancel])
Try this sample from the original Dialogs plugin documentation:
function onConfirm(buttonIndex) {
console.log('You selected button ' + buttonIndex);
navigator.notification.alert('You selected button ' + buttonIndex);
}
navigator.notification.confirm(
'You are the winner!', // message
onConfirm, // callback to invoke with index of button pressed
'Game Over', // title
['Restart','Exit'] // buttonLabels
);
I am running this using phonegap. When i run in Android the logout box is correct and its showing "confirm" as title in the logout box. Even in ios everything is perfect but the logout box shows title as "index.html"(which is the current page name)
$rootScope.logout=function()
{
response=confirm(GetLocalString("HMLOGOUTMSG",_language));
if(response==true)
{
logout();
}
else
{
menuchk();
}
}
I dont want the title as "index.html". Can you suggest a method to not display the title as "index.html"
In ios PhoneGap pages will show the page name in alert, you need to use a plugin for notification.
To add the plugin run this code.
cordova plugin add cordova-plugin-dialogs
Usage
navigator.notification.confirm(message, confirmCallback, [title], [buttonLabels])
message: Dialog message. (String)
confirmCallback: Callback to invoke with index of button pressed (1,
2, or 3) or when the dialog is dismissed without a button press (0).
(Function)
title: Dialog title. (String) (Optional, defaults to Confirm)
buttonLabels: Array of strings specifying button labels. (Array)
(Optional, defaults to [OK,Cancel])
Example
function onConfirm(buttonIndex) {
alert('You selected button ' + buttonIndex);
}
navigator.notification.confirm(
'You are the winner!', // message
onConfirm, // callback to invoke with index of button pressed
'Game Over', // title
['Restart','Exit'] // buttonLabels
);
The callback takes the argument buttonIndex (Number), which is the index of the pressed button. Note that the index uses one-based indexing, so the value is 1, 2, 3, etc.
Documentation
Now its working fine,
$rootScope.logout = function () {
function onConfirm(buttonIndex) {
if (buttonIndex == 1) {
logoutfunc();
}
else {
menuopenchk();
}
}
navigator.notification.confirm(
'Are you sure to logout?',
onConfirm,
'Logout',
['Yes', 'Not Now']
);
}
I am using the SDL-2.0.3 along with NDK-r10e, I'm attempting to make the return button switch the app to the background so I tried to use the function SDL_MinimizeWindow() but It does nothing ! is this a bug or do I miss something ?
here is my code :
if(event.key.keysym.sym == SDLK_AC_BACK)
{
SDL_MinimizeWindow(window);
SDL_Log("window minimized !\n");
}
everything just work fine and I get the log message when the button is pressed but the window is not minimized
That doesn't appear to be supported on Android (there's not really anything corresponding to minimizing a "window" on Android, unless you count finishing an Activity).
The SDL_MinimizeWindow function looks like this:
void
SDL_MinimizeWindow(SDL_Window * window)
{
CHECK_WINDOW_MAGIC(window, );
if (window->flags & SDL_WINDOW_MINIMIZED) {
return;
}
SDL_UpdateFullscreenMode(window, SDL_FALSE);
if (_this->MinimizeWindow) {
_this->MinimizeWindow(_this, window);
}
}
Where _this is an SDL_VideoDevice *, which is set to point to an SDL_VideoDevice for the appropriate platform at runtime. The Android video driver only sets up the following 3 Window-related functions:
device->CreateWindow = Android_CreateWindow;
device->SetWindowTitle = Android_SetWindowTitle;
device->DestroyWindow = Android_DestroyWindow;
Trying to perform any other operations on an SDL_Window on Android is likely to do nothing.
Some further information in the form of a couple of lines of code from SDL_androidwindow.c:
window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizeable */
window->flags |= SDL_WINDOW_FULLSCREEN; /* window is always fullscreen */
When alert/confirm box is popped up on screen and I press device's back button, then the poped up alert/confirm box is getting close(without firing any event). How can I avoid this?
Below is the calling code:
**var buttons = [
{
text : Messages.LBL_OK,
handler : doLogout
}
];
showSuccess(Messages.ALERT_FILING_CONFIRMATION,buttons);**
function showSuccess(text,buttons){
showDialog(Messages.LBL_CMN_DOALOG_SUCCESS_TITLE, text, buttons);
}
function showDialog(title,text,buttons){
if(title == null || title == undefined){
title = Messages.LBL_CMN_DOALOG_TITLE;
}
if(buttons == null || buttons == undefined){
buttons = [
{
text : Messages.LBL_OK,
handler : defaultOK
}
];
}
WL.SimpleDialog.show(title,text,buttons);
}
This is the expected behavior in Android.
However, if you'd like to avoid this default behavior, you could use the WL.App.overrideBackButton API in key locations in your code so that the button will 'do nothing'. When you're done, you can then use WL.App.resetBackButton to reset the back button's behavior back to its default state.
For example:
WL.App.overrideBackButton(callback);
function callback(){
// doing nothing...
}
You could use the above before calling WL.SimpleDialog.show() and dismiss it in the dialog's button callback.