KeyPressed Events, WebPages, and WebDialogs ... oh my!

I’d like to add some keyboard shortcuts to a Web app. Very easy when only Web pages are involved - can use the KeyPressed event.

However, I make fairly heavy use of Webdialogs in my app. When a Webdialog is being is displayed and a key is pressed, the KeyPressed event for the underlying Web page fires, not the one for the dialog. From what I’ve read, that’s just the Way It Is.

Question is - is it possible to have keyboard shortcuts processed by code in a dialog when it’s showing? And by the underlying Web page when a dialog isn’t showing?

I’ve seen various ways round this posted elsewhere, such as Michel B’s fiendishly cunning Javascript hashtag-changing solution near the end of https://forum.xojo.com/19105-keypressed-event-issues. But everything I’ve seen so far regarding keyboard shortcuts in Webdialogs requires code outside the Webdialog object in question, and it would be nice to be able to keep everything together if it’s possible.

One way to do this would be to have the webpage event call a method on your webdialog. Or an interface.

Basically, something like

If myDialog <> nil then myDialog.triggerKeyMethod(key) end if

Thanks Michel. I just gave that a try, and “myDialog <> nil” evaluated as True before and after the webdialog was displayed.

Sample project here.

Be careful with how you check for existence of the web dialog. If you’ve added it to the webPage (static) it will always be other than nil. If you create them dynamically they could be nil.

If you’re doing the first method (static) you probably want to have track which dialog is open as I’m not sure if the visible property actually works like we expect it to. Wherever you show the dialog you’d want to add tracking.

We tend to do dynamic web dialogs - especially with large complex dialogs - as those are added to the webpage thus slowing the load of the web page. So having a dialog variable local in the page is doable.

Edit: I did not look at your sample project so apologies if you’ve got it covered.

Actually, Bob, you put the finger where it hurts.

David, don’t drag the dialog onto the web page.

  • Add a Sheet2 as Sheet1 property to the webpage.
  • In the button, do :

Sheet2 = new Sheet1 Sheet2.Show

That way you can test Sheet2, which will be nil before you display it, and not nil when instantiated.

Thanks Bob - makes sense that a static Webdialog would be instantiated along with the WebPage it’s on, and thus would never be nil. I tried:

if StaticWebDialogInstance.visible = True then <do Webdialog keyboard shortcut stuff> end if

…but that didn’t work as you suspected it mightn’t. It seems like it ought to work, though…?

Michel, thanks for recipe. It works in that keypresses are ignored when the WebPage is initially displayed, and handled once the WebDialog is displayed. To develop it further, I added a “Close” button to the WebDialog so that I could see what happened when the dialog was dismissed. And then ran into 2 more issues:

  1. When the Webdialog was displayed, the newly-added button had focus, and the WebPage’s KeyPressed event didn’t fire as a result. After clicking on the background of the WebDialog to remove the focus from the button, keypresses caused the WebPage’s KeyPressed event to fire again. As an experiment, I tried adding code to the KeyPressed event of the button, but that doesn’t seem to fire at all, even when the button has focus!

  2. In your suggestion, Sheet2 is nil before it’s instantiated. But when the dialog is closed, the Sheet2 instance still exists. Is there some way of destroying the Sheet2 instance when the dialog is closed? Add “Me = nil” to the Dismissed event of the Sheet1 class, or something like that?

Here’s an update to the Sample Project, incorporating suggestions so far.

[quote=310644:@David McKenzie]. In your suggestion, Sheet2 is nil before it’s instantiated. But when the dialog is closed, the Sheet2 instance still exists. Is there some way of destroying the Sheet2 instance when the dialog is closed? Add “Me = nil” to the Dismissed event of the Sheet1 class, or something like that?
[/quote]

I would try to catch the key in the KeyPressed event of the button. The other way would be to set focus to the webpage. I would prefer catching keys in the button, to keep keyboard access for people needed this kind of assistance.

I would try putting Sheet2 = nil in the close event. I hope it won’t create an exception.

For dynamically created web dialogs I use AddHandler to put the Dismissed event in the webpage. That should be sufficient to set the dialog variable to nil and thus trying to stop sending keypresses to a non-existent dialog.

Thanks Bob - using AddHandler does the trick and I can set the dialog object back to nil.

So the only remaining issue is that when the Webdialog is displayed, the button on it has focus by default (tested in 3 different browsers). I would have thought that given that’s the case, the KeyPressed event for the button would fire when a key is pressed, but it doesn’t. The KeyPressed event for the underlying WebPage doesn’t fire either. If I click on the background of the WebDialog to remove focus from the button, then the WebPage’s KeyPressed event fires when I press a key.

In fact, I can’t persuade the KeyPressed event handlers for the WebDialog or the button on the WebDialog to fire under any circumstances.

Here’s an update to the sample project incorporating the AddHandler idea, and showing the problem with the button on the WebDialog.

This is much harder than I expected it to be! Do you guys use keyboard shortcuts in your Web apps?