It's What's For Dinner
Application-Level Menus for HTML
A little while back you might recall that Paul Rouget posted a little demo about
Experimenting with HTML5 and native
controls.
The title is broad but much of the content is about a cool demo of what can be done if browsers
implement the HTML menu
element. Allowing a site to integrate with the native UI
is a powerful approach to making the web easier to use and increase its world domination but
it naturally comes with its share of potential security issues.
Right before that demo, we had a little conversation with Paul about various ideas as to how
this could be done. No definitive findings of any kind came up, but the different options are,
I think, quite interesting. This is particularly relevant since an API to manage application
menus
is one of the items that are part of the
plan for the new Device APIs Working Group. (This was previously bundled under User
Interaction API
but that's a really big bag and not very meaningful. It was even
discussed
but
we've had a lot of things on our plate.)
There are several ways in which site menus could be integrated into browsers: pure API, pure declarative, or a mix of both. There are also constraints in that it needs to be implementable in a device independent manner (you don't want to enforce the same menus with the same rendering everywhere); in fact it should be implementable in a completely different way by different browsers on the same device. When you enter native land you get to play by native rules. And of course, you want to be careful with bad things that could happen such as tricking the user into using a menu they think is from their system when it comes from the site.
The pure API approach is frankly quite inelegant — building user interfaces with just API calls
is a
pain in the arse and can be hard to scale. Additionally, if you really want an API for
this,
it's a lot easier to (in current browsers) to wrap an API around a declarative approach (i.e.
manipulating
the DOM) than it is to build a declarative approach to an API (since it requires listening to
document
mutations). Besides, there's a HTML menu
that's right there for the taking and it
would be
a shame not to reuse it.
The menu
element captures the general semantics of menus in a fairly
straightforward fashion
(see the
spec). You can
easily build context menus and toolbars with it. But it currently has no provision for
application-level
menus. How could these be added?
The most straightforward manner is to stick to the pure declarative approach. You add
application
to the list of supported types, define it to represent application-level menus, and let
implementations
worry about the rest (how to present them but also what to do when multiple such menus are
defined in a single
app). In fact, those of you seasoned enough to have enjoyed using the Mozilla browser (from back
when there was
no Firefox) might remember that it would generate its own application-level menus for
<link rel=next>
and other such niceties. It's not such a new idea.
An alternative, would be to have an API to promote an existing menu element to an application
menu, à la
navigator.addAppMenu(document.getElementById("your-menu"));
.
My first instinct would be to go for the declarative option. It's sweetly simple to author, it
has rather clear
built-in semantics, and it seems pretty low impact. But things may not be so simple. First, you
need to
be able to feature-detect. A very typical usage scenario would be make this an application
menu if you
can, otherwise keep it visible in the page as a regular web application menu
:
if (navigator.addAppMenu) { someMenu.style.display = "none"; navigator.addAppMenu(someMenu); }
I could certainly be missing something, but I don't see an obvious way of performing feature
detection with
the menu
element as currently specified. I guess that implementations that accept
the menu
being
added at the application level could automatically hide it but that seems like a kludge (and
reusing hidden
for this seems like a misuse of it). A better way could be to dispatch an event when a
menu
is accepted as an
application menu — that's worth mulling over.
Second, the security model also needs to be figured out. As noted above, adding an application-level menu is a potential security threat, and a browser could be justified in refusing to do so even if it supports the feature. This does not necessarily mean that using application menus would require a security prompt (the web's favourite mood-killer) — it could for instance always accept them in special "application" or "pinned" tabs and always reject them in regular use. This points to your familiar asynchronous security entry point:
navigator.addAppMenu(someMenu, menuOK, menuRejected); function menuOK () { someMenu.hidden = true; } function menuRejected () { // attach some fancy animation code to your menu // because it's staying in the page }
Additionally, this latter approach would also work with the Feature Permissions API (initiated by the Web Notification people, now in DAP's lap) as well as with its weird cousin FRAC (currently not on anyone's lap, but feedback is very welcome).
At the end of the day I'm not sure which approach is best but I like the feature. As usual, thoughts and comments are welcome, either below, on Twitter, and of course on the DAP mailing list (which is open to all).