The importance of user experience should never be underestimated. Software not withstanding, user experience is important in everything that we interact with, both physical and digital. There is an
entire website dedicated just to user interaction fails with hilarious results. I captured one at the movie theater in my own small southern town.
A door leading to a 20 foot drop that ends in pavement is obviously a relic from a remodel with no place in the natural order of things anymore. However, sometimes we have to sacrifice less important features in order to get support for more critical ones. In this case, they may have chosen to raise the ceiling instead of having a second story space. The door is the painful reminder.
The web is all about sacrificing "perfect" in order to get "working". If there was ever a place in web development where we see this played out, it's with the Context Menu.
A Bit Of History
The Context Menu, like so many other things we know and love, was created by Xerox and first appeared in Smalltalk on the Xerox Alto, which interestingly enough had a portrait monitor. However, the menu was fixed to the screen and the user had to move the mouse across the screen to click and activate it.
Jobs and his band of rebels at NEXTSTEP took the idea a step further and allowed the menu to be brought up with a right mouse click which allowed the menu to be summoned right where the mouse was located.
Microsoft added their own bit of ingenuity when the allowed flyout and sub-menus in Word. Windows 7 changed the menu again, yet subtly, by activating the menu on release of the mouse button requiring two clicks to select a menu item. This was news to me as I have always clicked twice, but it is possible still on OS X to activate the menu with a right click and then select an item all in the same "click".
As native applications, browsers have always had context menus. The options in the menus have varied over time, but generally include Copy/Paste/Refresh and more recently the all hallowed "Inspect Element". While the contents of the context menu will change depending on what part of the browser you right-click on, clicking on the contents within the browser viewport always renders the same menu.
The trouble with Context Menus in browsers is that the browser has quickly morphed from a way to post Live Journal entries into a runtime for applications. That means that we expect the applications that are running inside of the browser to behave like desktop ones do, and desktop apps have context menus. Essentially, we want a application with context menus within an application with context menus.
The best solution would be a way to extend the built-in context menu so that we can add custom menu items to the existing list of system menu options. In that case we have a few options.
Believe it or not,
there is a spec for extending native context menus with the
<menu>
element that have a type of
context
and then referencing the id of that element with the
contextmenu
attribute wherever you want that context menu to appear.
<menu id="customMenu">
<menuitem label="Share On Live Journal" onclick="blog()"></menuitem>
<menuitem label="Check AOL Email" onclick="blog()"></menuitem>
<menuitem label="Publish To GeoCities" onclick="blog()"></menuitem>
</menu>
<div contextmenu="customMenu">
<h1>Native Context Menu?</h1>
</div>
Didn't work for you? That would be because
native context menus are only supported in FireFox. Here - I included a GIF of it for you so you won't feel completely left out.
Notice that the commands are simply appended to the top of the list. I find this a tad noisy, although the spec notes that maybe those default system commands would be
collapsed by default, which I think is a much more desirable experience.
It doesn't look like any other browser vendors plan on implementing this anytime soon. Why is that? I'm not entirely sure, but
Addy Osmani noted that
the FireFox implementation actually differs from the spec. However, when I looked at
the WHATWG spec, everything looks legit to me. Perhaps there is a different standard with the W3C.
The nice thing about standards is that you have so many to choose from
— Andrew S. Tanenbaum
David Walsh points out that this custom context menu in FireFox will work even if JavaScript is disabled. This is a problem since those menu items are rather dependent on JavaScript in order to work. I don't see that as a reason
not to implement them though.
To add a twist to this story, Chrome actually
does support custom context menus, just not on standard browser pages.
Chrome has
an API for creating custom context menu items, but
only in the confines of Chrome Apps and Extensions. Not only that, but it's completely different from what the WHATWG specifies and relies, instead, on a manifest JSON configuration file to specify the context menu structure.
Chrome's Context Menus are quite a bit more robust, allowing for different types of menu items, such as radio buttons, checkboxes and menu separators. Interestingly enough, they also did not decide to collapse the standard menu items by default as suggested by the spec.
Technically speaking, you
can add in custom menu items in IE, but it requires hacking the Windows Registry and then of course those menu items show up on every page. Probably not the solution you were looking for.
So What Do We Do?
While there is no way to extend the native menu across browsers, vendors do universally provide access to the
event that summons the context menu, providing developers a way to intercept and stop the native action so they can supplement it with their own.
There is no shortage of
jQuery context menu plugins, including
one from Rodney Rehm that was
then forked by Addy to act as a pollyfill, using the native implementation where available, and falling back to the jQuery based alternative.
Kendo UI Core added a
Context Menu in it's latest release. To create one, simply use an unordered list to construct the menu, initialize the plugin, and specify the target area where the plugin will be activated on right click.
<ul id="menu">
<li>Share On Live Journal</li>
<li><img id="aol" src="http://icons.iconarchive.com/icons/ncrow/mega-pack-2/256/AOL-icon.png">Email with AOL</li>
<li>Publish To GeoCities</li>
</ul>
<div id="target">
<h1>Right-Click Me For Some Options</h1>
</div>
(function() {
$('#menu').kendoContextMenu({
target: '#target',
select: function(e) {
alert('pfffft');
}
});
}());
By default Kendo UI Context Menus have a vertical orientation, but this is JavaScript, so why not have a horizontal one?
Of course, Context Menus can have nested menus just like the native ones. That's accomplished simply by nesting lists. Adding separators is done by including a class of
k-separator
on an
li
.
Since it's all JavaScript, we can even control how the thing is summoned. We can have it shown on a regular click, right click, or any other event.
Advantages And Disadvantages
Custom context menus are really neat and provide that missing "desktop-like" experience for users who are accustomed to working with that interaction. The downside is that highjacking the native context menu means you lose basic actions like copy/paste and you have to implement them all over again in JavaScript if you want them back.
Also remember that context menus are a desktop interaction. They do not exist on mobile devices natively.
Raymond Camden talks about
how you could implement the "touchhold" event on mobile to summon the popup list. That's actually a pretty neat idea and
Kendo UI does this for you automatically. Because we're always thinking mobile first baby.
Get Contextual
If you're in the market for a context menu, you can wait for browser vendors to implement it, which might blow your project timeline out of the water. OR, you could
grab Kendo UI Core and get one that works across browser and on mobile devices today. Say it with me now, "Thank you, JavaScript".