2

Using Durandal,

app.showMessage(message, title);

shows a modal dialog with the supplied message and title, and a single primary button OK. All this is styled by Bootstrap.

It doesn't seem to respect the keyboard. Clicking the OK button with the mouse works as expected, but neither the ESC nor ENTER keys clicks the OK button.

I have yet to find anything useful in the rather Spartan Durandal documentation, but sometimes that means it's covered by the documentation of a subsystem such as Knockout or Bootstrap.

Can anyone suggest a strategy or some pertinent reading on the customary browser independent way to bind buttons to keyboard shortcuts?

I find it so hard to believe that Durandal dialogs ignore the keyboard that I wonder whether I've screwed something up.

For a few moments I thought I had an answer in CSS specified behaviour. It was even specified in a W3C document. But it's obsolete and not supported.

No doubt I can present a view and view model modally. This will give me a chance to bind additional behaviour, and I can pass parameters, pretty much plug-in replacing app.showMessage() but it all seems rather heavy handed.


I noticed today that spacebar closes message dialogs. Presumably with only one focusable control, that's where the focus is. Given the Durandal habit of minimalism this might even be by design, it's hard to say.

Peter Wone
  • 17,965
  • 12
  • 82
  • 134

1 Answers1

3

You can use jwerty, which can be found here. We use jwerty in our Durandal project (as does Ayende Rahien in RavenDB's new HTML5 Raven Studio, which is also written with Durandal).

To see the rich keyboard support with jwerty in action, take a look at this video on my DropBox account of a Dropdown Datepicker that I wrote entirely with Durandal (and jwerty).

If you're interested, I can show you how to integrate jwerty into Durandal (pretty trivial).

[EDIT]

There are two strategies for using jwerty with Durandal: inline and custom Knockout binding.

INLINE

Below is a snippet directly from our CalendarNavigationEngine:

//Bind the directional keys
    CalendarNavigationEngine.prototype.bindDirectionalKeys = function () {
        var that = this;

        var kContainerClass = this.kContainerClass;

        //Bind directional keys
        jwerty.key('left', function () { that.prevItem(); }, kContainerClass);
        jwerty.key('up', function () { that.prevWeek(); }, kContainerClass);
        jwerty.key('pgup / ctrl+left', function () { that.prevPage(); }, kContainerClass);
        jwerty.key('right', function () { that.nextItem(); }, kContainerClass);
        jwerty.key('down', function () { that.nextWeek(); }, kContainerClass);
        jwerty.key('pgdown / ctrl+right', function () { that.nextPage(); }, kContainerClass);
        jwerty.key('home', function () { that.firstItem(); }, kContainerClass);
        jwerty.key('end', function () { that.lastItem(); }, kContainerClass);
        jwerty.key('enter / tab', that.select.bind(that), kContainerClass);
    };

We usually call bindDirectionalKeys Durandal's compositionComplete handler on the viewModel. In this case, the call chain is much deeper as CalendarNavigationEngine is not a viewModel.

By inline I mean to say that you are making the call directly from your viewModel (or module), as shown above. kContainerClass is the DOM class on the element, or elements, that has focus and should receive and process keyboard events.

With this approach, you need a corresponding unbind method:

//Unbind key bindings
    CalendarNavigationEngine.prototype.clearKeyBindings = function () {
        $(this.kContainerClass).unbind('keydown.jwerty');
    };

This would [eventually] be called from Durandal's detached handler, and cleans up all key bindings in the context of kContainerClass to avoid memory leaks. THIS IS NOT OPTIONAL.

CUSTOM KNOCKOUT BINDING

There are plenty of resources on StackOverflow on how to write custom Knockout bindings. But basically, the strategy involves binding the DOM element to a jwerty key binding. This is pretty trivial, although we did not take this approach (we are considering it).

There is one caveat: Knockout does not permit multiple identical bindings. So you cannot call a jwerty binding multiple times, which is what you would need to do in order to associate multiple key bindings with a single element (as in the example I gave above). However, what you can do is bind an array of key bindings to a single element, and then just have your custom Knockout binding, in its init handler, iterate over that array, binding with jwerty for each item. Again, still trivial.

Keithamus
  • 1,819
  • 17
  • 21
  • Interesting, I shall look into that. – Peter Wone Jun 11 '14 at 05:26
  • OK yes, I think I know how I would use it but I'm always keen to learn. How would you go about integrating jwerty with Durandal? – Peter Wone Jun 11 '14 at 13:28
  • @PeterWone If you could give me until this evening, that would be great. I have an incredibly busy day today. I'll outline in a new answer the two approaches you can take. –  Jun 11 '14 at 17:08
  • @PeterWone Take a look at my [EDIT]. I give you two strategies. If you choose the latter, I can help you with the custom binding. –  Jun 12 '14 at 16:34