I have a problem concerning the notificationBox. I create a notification using
appendNotification( label , value , image , priority , buttons, eventCallback )
and supply a button in the buttons argument.
Now, I want to prevent the notificationBox from closing when I hit the button. The XUL Documentation states that this can be done by throwing an error in the eventCallback function:
This callback can be used to prevent the notification box from closing on button click. In the callback function just throw an error. (For example: throw new Error('prevent nb close');)
This does not work for me, however, it works when I add the throw-statement to the callback function of the button itself.
Is this a bug in XUL or an inconsistency with the documentation?
Is there any harm done by adding it to the button's callback function?
In my opinion, this is an error in the documentation not a bug in the code. However, throwing an error in your button callback to prevent closure is not the best way to accomplish that goal.
Looking at the source code, there were clearly multiple discrepancies between the code and the documentation regarding how buttons work on a notification.
There is a specifically coded method of preventing the notification closing from within the button callback (return true from the callback).
Throwing an error in order to accomplish a normal functionality is usually a bad programming practice. Doing so also results in an error showing in the console every time your button is pressed. Having errors intentionally showing in the console under normal operation is bad. It also can result in your add-on not being approved in review.
As it was documented (not as operational), if you wanted to close when one button was pressed and not close when another was pressed, you would have to store in a global variable which button callback was last called and then choose based on that information if you wanted to prevent closure when your notificationBox callback was executed. That would be an inappropriately complex way to design operation of these notification buttons.
Given all that, I would say that intentionally throwing an error in order to prevent closure is not the "correct" way to do it. While, trowing an error to prevent closure doesn't cause any harm to the operation of the notification box, it does show the error in the console, which is bad.
The correct way to prevent the notification from closing from within the notification button callback is to return a True value from the callback.
While it is possible that the previously inaccurately documented way of doing this the way they intended to have it operate, it is not the way it actually works. Given
It is easier to update the documentation than it is to make changes to the code.
The code works in a way that is better than the documented method.
There were other inaccuracies in the documentation that would have prevented people from using functionality which was supposedly working (popups/menu buttons).
I have, therefore, updated the documentation to reflect what is actually in the source code and copied, with some modification, the code from this answer to an example there.
Here is some code I used to test this:
function testNotificationBoxWithButtons() {
//Create some common variables if they do not exist.
// This should work from any Firefox context.
// Depending on the context in which the function is being run,
// this could be simplified.
if (typeof window === "undefined") {
//If there is no window defined, get the most recent.
var window=Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator)
.getMostRecentWindow("navigator:browser");
}
if (typeof gBrowser === "undefined") {
//If there is no gBrowser defined, get it
var gBrowser = window.gBrowser;
}
function testNotificationButton1Callback(theNotification, buttonInfo, eventTarget) {
window.alert("Button 1 pressed");
//Prevent notification from closing:
//throw new Error('prevent nb close');
return true;
};
function testNotificationButton2Callback(theNotification, buttonInfo, eventTarget) {
window.alert("Button 2 pressed");
//Do not prevent notification from closing:
};
function testNotificationCallback(reason) {
window.alert("Reason is: " + reason);
//Supposedly prevent notification from closing:
//throw new Error('prevent nb close');
// Does not work.
};
let notifyBox = gBrowser.getNotificationBox();
let buttons = [];
let button1 = {
isDefault: false,
accessKey: "1",
label: "Button 1",
callback: testNotificationButton1Callback,
type: "", // If a popup, then must be: "menu-button" or "menu".
popup: null
};
buttons.push(button1);
let button2 = {
isDefault: true,
accessKey: "2",
label: "Button 2",
callback: testNotificationButton2Callback,
type: "", // If a popup, then must be: "menu-button" or "menu".
popup: null
};
buttons.push(button2);
//appendNotification( label , value , image (URL) , priority , buttons, eventCallback )
notifyBox.appendNotification("My Notification text", "Test notification unique ID",
"chrome://browser/content/aboutRobots-icon.png",
notifyBox.PRIORITY_INFO_HIGH, buttons,
testNotificationCallback);
}
Related
We recently discovered that Chrome no longer supports window.showModalDialog which is problematic because our enterprise application uses this method.
There is, apparently, a short term workaround that allows you to restore showModalDialog but it involves modifying the registry which is too complicated (and risky) four our average user. Therefore I'm not a big fan of this workaround.
The long term solution is obviously to remove all calls to this obsolete method and replace them with a convenient jQuery plugin (such as VistaPrint's Skinny Modal Dialog plugin, for example. Other suggestions are welcome by the way).
The typical scenario we use the modal dialog is to ask the user for Yes/No confirmation before executing an action that cannot be undone, ask the user to agree to terms and condition before proceeding, etc. Typically the onclick event on the "Yes" or "Ok" button in the modal dialog looks like this:
window.returnValue = true;
window.close();
Similarly, the "Cancel" or "No" button looks like this:
window.returnValue = false;
window.close();
The fact that we can return a value from the dialog is very convenient because it allows the "parent" window to be notified whether the user has clicked the "Ok" or the "Cancel" button like so:
var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
... proceed ...
}
The last thing I'm going to mention about the showModalDialog is that it works great even when the document displayed in the dialog is from a different domain. It's very common for us to have our javascript running from http://the-client.com but the "Terms of Service" web page is from http://the-enterprise-vendor.com
I need a temporary solution that I can deploy ASAP while we work on the long term solution. Here are my criteria:
minimal code change in existing JavaScript
the pop up window must be able to return a value to the "parent". Typically this value is a Boolean but it could be any simple type (e.g.: string, int, etc.)
solution must work even if the URL of the content is from different domain
Here's what I have so far:
1) Add the following method in my JavaScript:
function OpenDialog(url, width, height, callback)
{
var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
var timer = setInterval(function ()
{
if (win.closed)
{
clearInterval(timer);
var returnValue = win.returnValue;
callback(returnValue);
}
}, 500);
}
As you can see in this method, I try to make the pop up window look as similar to a dialog as possible by hiding the menu and the toolbar, I setup a time every 500 milliseconds to check if the window has been closed by the user and if so, get the 'returnValue' and invoke a callback.
2) replace all calls to showModalDialog with the following:
OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
if (termsOfServiceAccepted)
{
... proceed ....
}
});
The fourth parameter to the method is the callback where I check if the user has clicked the "Ok" button before allowing her to proceed.
I know it's a long question but basically it boils down to:
What do you think of the solution I propose?
In particular, do you think I'll be able to get a returnValue from a window that was opened with window.open?
Any other alternative you can suggest?
I have two ideas that could help you but the first one is tied to CORS, so you won't be able to use it from different domains at least you can access both services and configure them.
FIRST IDEA:
The first one is related to this native api. You could create on the parent window a global function like this:
window.callback = function (result) {
//Code
}
As you can see it receives a result argument which can hold the boolean value you need. The you could open the popup using the same old window.open(url) function. The popup's onlick event handler could look like this:
function() {
//Do whatever you want.
window.opener.callback(true); //or false
}
SECOND IDEA: Solves the problem
The other idea I got is to use this other native api to trigger an event on the parent window when the popup resolves (better known as cross-document messaging). So you could do this from the parent window:
window.onmessage = function (e) {
if (e.data) {
//Code for true
} else {
//Code for false
}
};
By this way you are listening to any posted message on this window, and checking if the data attached to the message is true (the user clicks ok in the popup) or false (the user clicks cancel in the popup).
In the popup you should post a message to the parent window attaching a true or a false value when corresponds:
window.opener.postMessage(true, '*'); //or false
I think that this solution perfectly fits your needs.
EDIT
I have wrote that the second solution was also tied to CORS but digging deeper
I realized that cross-document messaging isn't tied to CORS
I have a problem understanding the documentation for the WebExtensions notification.onClicked event.
Ultimately, I'm trying to get the text of the notification copied to the clipboard when you click on it. However, right now I am having a problem understanding the callback thing, or where I have to insert the notification.onClicked function.
At the moment, I don't know why the notification.onClicked listener does nothing.
My code (all the code needed to demonstrate the problem as a WebExtension Firefox add-on):
manifest.json
{
"description": "Test Webextension",
"manifest_version": 2,
"name": "Σ",
"version": "1.0",
"permissions": [
"<all_urls>",
"notifications",
"webRequest"
],
"background": {
"scripts": ["background.js"]
}
}
background.js
'use strict';
function logURL(requestDetails) {
notify("Testmessage");
chrome.notifications.onClicked.addListener(function() {
console.log("TEST TEST");
});
}
function notify(notifyMessage) {
var options = {
type: "basic",
iconUrl: chrome.extension.getURL("icons/photo.png"),
title: "",
message: notifyMessage
};
chrome.notifications.create("ID123", options);
}
chrome.webRequest.onBeforeRequest.addListener(
logURL, {
urls: ["<all_urls>"]
}
);
First, you need to be testing this in Firefox 47.0+, as support for chrome.notifications.onClicked() was added in version 47.0. While this is probably not your problem, it is one contributing possibility.
There are multiple issues with your code. Some are in your code, but primarily you are running into a Firefox bug.
Firefox Bug:
Your primary issue is that you are running into a Firefox bug where Firefox gets confused if you try to create notifications too rapidly. Thus, I have implemented a notification queue and rate limited the creation of notifications. What is "too rapidly" is probably both OS and CPU dependent, so you are best off erroring on the side of caution and set the delay between calls to chrome.notifications.create() to a higher value. in the code below, the delay is 500ms. I have added a note regarding this issue in the chrome.notifications.create() page on MDN and on the Chrome incompatibilities page.
Adding multiple copies of the same listener:
The main thing that you are doing wrong in your code is that you are adding an anonymous function as a listener, using chrome.notifications.onClicked.addListener(), multiple times to the same event. This is a generic issue with event handlers. When you use an anonymous function it is a different actual function each time you are trying to add it, so the same functionality (in multiple identical functions) gets added multiple times. You should not be adding functions, which do the exact same thing, multiple times to the same event. Doing so is almost always an error in your program and results in unexpected operation.
In this case, the multiple functions would have ended up outputing multiple lines of TEST TEST to the console each time the user clicked on a notification. The number of lines output per click would increase by one for each web request which resulted in a call to logURL.
The way to prevent doing this is to be sure to add the listener only once. If you are using an anonymous function, you can only do this by being sure you only execute the addListener (or addEventlistener) once (usually by only adding the listener from your main code (not from within a function), or from a function that is only called once. Alternately, you can name/define your listener function directly within the global scope (or other scope accessible to all places where you try to add the listener) (e.g. function myListener(){...}). Then, when you are adding myListener you are always referring to the same exact function which JavaScript automatically prevents you from adding in the same way to the same event more than once.
It should be noted that if you are trying to add a anonymous function as a listener from another listener, you are almost always doing something wrong. Adding copies of identical anonymous listeners multiple times to the same event is a common error.
Access to the notification text:
While you do not implement anything regarding using the text of the notification, you state that you want to add the text of the notification to the clipboard when the user clicks on the notification. You can not obtain the notification text from any portion of the chrome.notifications API. Thus, you have to store that information yourself. The code below implements an Object to do that so the text can be accessed in the chrome.notifications.onClicked() handler.
Example code:
The code below implements what I believe you desire. It is just creating and clicking the notification while having access to the notification text in the chrome.notifications.onClicked() listener. It does not implement the part about putting the text into the clipboard, as that was not actually implemented in the code in your Question. I have added liberal comments to the code to explain what is happening and provided quite a bit of console.log() output to help show what is going on. I have tested it in both Firefox Developer Edition (currently v51.0a2) and Google Chrome.
background.js (no changes to your manifest.json):
'use strict';
//* For testing, open the Browser Console
var isFirefox = window.InstallTrigger?true:false;
try{
if(isFirefox){ //Only do this in Firefox
//Alert is not supported in Firefox. This forces the Browser Console open.
//This abuse of a misfeature works in FF49.0b+, not in FF48
alert('Open the Browser Console.');
}
}catch(e){
//alert throws an error in Firefox versions below 49
console.log('Alert threw an error. Probably Firefox version below 49.');
}
//*
//Firefox gets confused if we try to create notifications too fast (this is a bug in
// Firefox). So, for Firefox, we rate limit showing the notifications.
// The maximum rate possible (minimum delay) is probably OS and CPU speed dependent.
// Thus, you should error on the side of caution and make the delay longer.
// No delay is needed in Chrome.
var notificationRateLimit = isFirefox ? 500:0;//Firefox:Only one notification every 500m
var notificationRateLimitTimeout=-1; //Timeout for notification rate limit
var sentNotifications={};
var notificationsQueue=[];
var notificationIconUrl = chrome.extension.getURL("icons/photo.png");
function logURL(requestDetails) {
//console.log('webRequest.onBeforeRequest URL:' + requestDetails.url);
//NOTE: In Chrome, a webRequest is issued to obtain the icon for the notification.
// If Chrome finds the icon, that webRequest for the icon is only issued twice.
// However, if the icon does not exist, then this sets up an infinite loop which
// will peg one CPU at maximum utilization.
// Thus, you should not notify for the icon URL.
// You should consider excluding from notification all URLs from within your
// own extension.
if(requestDetails.url !== notificationIconUrl ){
notify('webRequest URL: ' + requestDetails.url);
}
//Your Original code in the Question:
//Unconditionally adding an anonymous notifications.onClicked listener
// here would result in multiple lines of 'TEST TEST' ouput for each click
// on a notification. You should add the listener only once.
}
function notify(notifyMessage) {
//Add the message to the notifications queue.
notificationsQueue.push(notifyMessage);
console.log('Notification added to queue. message:' + notifyMessage);
if(notificationsQueue.length == 1){
//If this is the only notification in the queue, send it.
showNotificationQueueWithRateLimit();
}
//If the notificationsQueue has additional entries, they will get
// shown when the current notification has completed being shown.
}
function showNotificationQueueWithRateLimit(){
if(notificationRateLimitTimeout===-1){
//There is no current delay active, so immediately send the notification.
showNextNotification();
}
//If there is a delay active, we don't need to do anything as the notification
// will be sent when it gets processed out of the queue.
}
function showNextNotification() {
notificationRateLimitTimeout=-1; //Indicate that there is no current timeout running.
if(notificationsQueue.length === 0){
return; //Nothing in queue
}
//Indicate that there will be a timeout running.
// Neeed because we set the timeout in the notifications.create callback function.
notificationRateLimitTimeout=-2;
//Get the next notification from the queue
let notifyMessage = notificationsQueue.shift();
console.log('Showing notification message:' + notifyMessage);
//Set our standard options
let options = {
type: "basic",
//If the icon does not exist an error is generated in Chrome, but not Firefox.
// In Chrome a webRequest is generated to fetch the icon. Thus, we need to know
// the iconUrl in the webRequest handler, and not notify for that URL.
iconUrl: notificationIconUrl,
title: "",
message: notifyMessage
};
//If you want multiple notifications shown at the same time, your message ID must be
// unique (at least within your extension).
//Creating a notification with the same ID causes the prior notification to be
// destroyed and the new one created in its place (not just the text being replaced).
//Use the following two lines if you want only one notification at a time. If you are
// actually going to notify on each webRequest (rather than doing so just being a way
// to test), you should probably only have one notification as they will rapedly be
// off the screen for many pages.
//let myId = 'ID123';
//chrome.notifications.create(myId,options,function(id){
//If you want multiple notifications without having to create a unique ID for each one,
// then let the ID be created for you by using the following line:
chrome.notifications.create(options,function(id){
//In this callback the notification has not necessarily actually been shown yet,
// just that the notification ID has been created and the notification is in the
// process of being shown.
console.log('Notification created, id=' + id + ':: message:' + notifyMessage);
logIfError();
//Remember the text so we can get it later
sentNotifications[id] = {
message: notifyMessage
}
//Show the next notification in the FIFO queue after a rate limiting delay
// This is called unconditionally in order to start the delay should another
// notification be queued, even if one is not in the queue now.
notificationRateLimitTimeout = setTimeout(showNextNotification
,notificationRateLimit);
});
}
function logIfError(){
if(chrome.runtime.lastError){
let message =chrome.runtime.lastError.message;
console.log('Error: ' + message);
}
}
chrome.webRequest.onBeforeRequest.addListener(
logURL, {
urls: ["<all_urls>"]
}
);
//Add the notifications.onClicked anonymous listener only once:
// Personally, I consider it better practice to use a named function that
// is defined in the global scope. Doing so prevents inadvertantly adding
// it multiple times. Although, your code should be written such that you
// don't do that anyway.
chrome.notifications.onClicked.addListener(function(id) {
//We can not get the notification text from here, just the ID. Thus, we
// have to use the text which was remembered.
console.log('Clicked notification message text: ', sentNotifications[id].message);
//In Firefox the notification is automatically cleared when it is clicked.
// If you want the same functionality in Chrome, you will need to clear() it
// yourself:
//Always do this instead of only when not in Firefox so that it remains consistent
// Even if Firefox changes to match Chrome.
chrome.notifications.clear(id);
//This is the last place we use the text of the notification, so we delete it
// from sentNotifications so we don't have a memory leak.
delete sentNotifications[id];
});
//Test the notifications directly without the need to have webRequests:
notify('Background.js loaded');
notify('Second notification');
In the process of working on this, I found multiple incompatibilities between Chrome and Firefox. I am in the process of updating MDN to mention the incompatibilities in the documentation on MDN.
I have the following code in a javascript file:
if(dojo.byId('WC_selectedColorNumber') == null && this.defaultColor != null)
{
dijit.byId('WC_color_selection').domNode.style.display = 'block';
dojo.html.set(dojo.query(".message__button .add"), "Add product with only base color " + this.defaultColor + "?");
var userResponse = true;
dojo.connect(WC_add_color_yes, "onclick", function(evt){
userResponse = true;
});
dojo.connect(WC_add_color_no, "onclick", function(evt){
userResponse = false;
});
//var userResponse = confirm("Add product with only base color " + this.defaultColor + "?");
//I WANT TO WAIT HERE FOR THE RESPONSE
if(userResponse == false) //if user clicks Cancel or 'no', display a message and leave the function.
{
alert("Remember to select a color before adding to cart."); //should be a tooltip/popup (not javascript alert) with the same message
return; //return so item doesn't get added to cart
}
}
Firstly, the logic behind this code is correct and it works perfectly well when using javascript confirm's.
As of now, everything comes up and displays correctly, and clicking the buttons perform the correct actions (if I put a console.log in the onclick dojo events, they do indeed print to the console when I click the buttons). However, the program doesn't wait for the responses and continues beyond the dojo.connect methods before it sees the user's input.
I need it to wait until either the yes or no button have been pressed, but I cannot figure out how to do it. I've tried using a
while(userResponse == null);
but a) it's generally a terrible idea and b) it didn't work anyways.
How can I make my code wait until the user has clicked one of the two buttons?
If you can make a jsfiddle I'd be able to help you more, I think, but your dojo.connect calls shouldn't be inside a logic flow like this. Instead, set up your connects on widget startup, and have them act generically.
In your example code, it looks to me like saying "Yes" means "Use default color", and "No" means "User must specify color". So...
startup: function () {
this.inherited(arguments);
dojo.connect(WC_add_color_yes, "onclick", dojo.hitch(this, function(evt){
this.useDefaultColor();
}));
dojo.connect(WC_add_color_no, "onclick", dojo.hitch(this, function(evt){
this.displayColorPicker();
}));
}
And then... only display those two buttons (or the dialog they're hopefully in) when applicable.
There is no "wait" or "sleep" function in javascript and each invocation of javascript code executes to completion (it does not get interrupted in mid execution by a response to some other event). You have correcly identified the historical execeptions that overcome this - global alert and confirm functions execute in browser native code and wait on user input.
Because of this your code will have to be restructured in some way, e.g. an event handler for "add to cart" validates the color choice and calls a function to really add it to the cart if valid. If it is not valid it modifies the DOM to present user with some buttons. The handler for the "yes" option would likewise call the same function to really add it to the cart.
Specific code is outside the scope of this answer - there must be many methods in page and code design to achieve the desired result. For example only: breaking up the sequential code and putting it in separate event handlers, coding using Promise objects defined in EC6 but not supported in MSIE, or perhaps even providing an option of "none - base color only" in the color selection logic.
FYI the dojo 1.10 toolkit documentation reports support for Dojo Promises but I leave research to determine its suitability with you.
We recently discovered that Chrome no longer supports window.showModalDialog which is problematic because our enterprise application uses this method.
There is, apparently, a short term workaround that allows you to restore showModalDialog but it involves modifying the registry which is too complicated (and risky) four our average user. Therefore I'm not a big fan of this workaround.
The long term solution is obviously to remove all calls to this obsolete method and replace them with a convenient jQuery plugin (such as VistaPrint's Skinny Modal Dialog plugin, for example. Other suggestions are welcome by the way).
The typical scenario we use the modal dialog is to ask the user for Yes/No confirmation before executing an action that cannot be undone, ask the user to agree to terms and condition before proceeding, etc. Typically the onclick event on the "Yes" or "Ok" button in the modal dialog looks like this:
window.returnValue = true;
window.close();
Similarly, the "Cancel" or "No" button looks like this:
window.returnValue = false;
window.close();
The fact that we can return a value from the dialog is very convenient because it allows the "parent" window to be notified whether the user has clicked the "Ok" or the "Cancel" button like so:
var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
... proceed ...
}
The last thing I'm going to mention about the showModalDialog is that it works great even when the document displayed in the dialog is from a different domain. It's very common for us to have our javascript running from http://the-client.com but the "Terms of Service" web page is from http://the-enterprise-vendor.com
I need a temporary solution that I can deploy ASAP while we work on the long term solution. Here are my criteria:
minimal code change in existing JavaScript
the pop up window must be able to return a value to the "parent". Typically this value is a Boolean but it could be any simple type (e.g.: string, int, etc.)
solution must work even if the URL of the content is from different domain
Here's what I have so far:
1) Add the following method in my JavaScript:
function OpenDialog(url, width, height, callback)
{
var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
var timer = setInterval(function ()
{
if (win.closed)
{
clearInterval(timer);
var returnValue = win.returnValue;
callback(returnValue);
}
}, 500);
}
As you can see in this method, I try to make the pop up window look as similar to a dialog as possible by hiding the menu and the toolbar, I setup a time every 500 milliseconds to check if the window has been closed by the user and if so, get the 'returnValue' and invoke a callback.
2) replace all calls to showModalDialog with the following:
OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
if (termsOfServiceAccepted)
{
... proceed ....
}
});
The fourth parameter to the method is the callback where I check if the user has clicked the "Ok" button before allowing her to proceed.
I know it's a long question but basically it boils down to:
What do you think of the solution I propose?
In particular, do you think I'll be able to get a returnValue from a window that was opened with window.open?
Any other alternative you can suggest?
I have two ideas that could help you but the first one is tied to CORS, so you won't be able to use it from different domains at least you can access both services and configure them.
FIRST IDEA:
The first one is related to this native api. You could create on the parent window a global function like this:
window.callback = function (result) {
//Code
}
As you can see it receives a result argument which can hold the boolean value you need. The you could open the popup using the same old window.open(url) function. The popup's onlick event handler could look like this:
function() {
//Do whatever you want.
window.opener.callback(true); //or false
}
SECOND IDEA: Solves the problem
The other idea I got is to use this other native api to trigger an event on the parent window when the popup resolves (better known as cross-document messaging). So you could do this from the parent window:
window.onmessage = function (e) {
if (e.data) {
//Code for true
} else {
//Code for false
}
};
By this way you are listening to any posted message on this window, and checking if the data attached to the message is true (the user clicks ok in the popup) or false (the user clicks cancel in the popup).
In the popup you should post a message to the parent window attaching a true or a false value when corresponds:
window.opener.postMessage(true, '*'); //or false
I think that this solution perfectly fits your needs.
EDIT
I have wrote that the second solution was also tied to CORS but digging deeper
I realized that cross-document messaging isn't tied to CORS
As in the title,
how can i close a MessageDialog from code in HTML5 Windows Store app?
my code so far:
var msg = new Windows.UI.Popups.MessageDialog("Please wait");
msg.commands.append(new Windows.UI.Popups.UICommand("OK",
function (command) {
...
}));
msg.showAsync();
and then i would like to close this popup FROM THE CODE, i have not found any methods
in the specification like
msg.close();
is there a way?
thanks
The fact that your message is "Please wait" suggests to me that you might want to use a different tool for this job.
If what you're trying to do is inform the user that you're doing something in the background that they need to wait for, consider using a Progress control instead, as documented here:
http://msdn.microsoft.com/en-us/library/windows/apps/hh465487.aspx
If you use a Progress control, you can both include a text label with your desired text, and dismiss the progress control when you've finished whatever task it is you're asking the user to wait for.
And to answer your original question, I don't believe there's any API for dismissing a MessageDialog programmatically, as that would break the interaction pattern of this control, which is for the app to display a message, and then allow the user to dismiss it when they're ready to.
Hope that helps.
For more information on Windows Store app development, register for App Builder.
I think you want to use a flyout, similarly to this answer. The link solves a slightly different problem in that it closes the flyout after a timeout.
However, you should be able to define a flyout that you, as well as the user, can close. In both cases, you end up calling something like:
flyout.winControl.hide(); // Dismiss the flyout
Take a look at this...
(function(){
"use strict";
var page = WinJS.UI.Pages.define("/html/cancelcommand.html", {
ready: function (element, options) {
document.getElementById("cancelCommand").addEventListener("click", cancelCommand_Click, false);
}
});
// Click handler for the 'cancelCommand' button.
// Demonstrates setting the command to be invoked when the 'escape' key is pressed.
// Also demonstrates retrieval of the label of the chosen command and setting a callback to a function.
// A message will be displayed indicating which command was invoked.
// In this scenario, 'Try again' is selected as the default choice, and the 'escape' key will invoke the command named 'Close'
function cancelCommand_Click() {
// Create the message dialog and set its content
var msg = new Windows.UI.Popups.MessageDialog("No internet connection has been found.");
// Add commands and set their command handlers
msg.commands.append(new Windows.UI.Popups.UICommand("Try again", commandInvokedHandler));
msg.commands.append(new Windows.UI.Popups.UICommand("Close", commandInvokedHandler));
// Set the command that will be invoked by default
msg.defaultCommandIndex = 0;
// Set the command to be invoked when escape is pressed
msg.cancelCommandIndex = 1;
// Show the message dialog
msg.showAsync();
}
function commandInvokedHandler(command) {
// Display message
WinJS.log && WinJS.log("The '" + command.label + "' command has been selected.", "sample", "status");
}
}());
http://code.msdn.microsoft.com/windowsapps/Message-dialog-sample-00c928f5/sourcecode?fileId=50972&pathId=1064922824