Windows 8 adventures: getting to know context menus

In the previous post, I’ve talked about the new Flyout control. Today, we’ll take a quick look at the context menu. In practice, you’ll show a context menu when you need to show a menu which gives the user immediate access to actions on text or UI objects.

By default, there are predefined context menus for text and hyperlinks. For text, the default context menu ends up showing the traditional cut, copy and paste commands. For hyperlinks, you end up with commands which allow you to copy the link or to open the link in a new window. For instance, suppose you’ve got a textarea in your default landing page:

<p>
    <textarea rows="4" cols="50"></textarea>
</p>

After writing texto and right clicking over any text selection, you’ll end up with the following default context menu:

contextmenu

Now, it’s important to notice that the options shown may vary. For instance, if the text is read only, you’ll only see the copy option. To illustrate this option, lets add a new paragraph to our landing page:

<p id="paragraph1"  data-win-selectable="true">
    Some demo text just for testing purposes...
</p>

Now, you’ve probably noticed the use of the data-win-selectable attribute. You need to resort to this attribute when you want to make p’s content selectable. The next image shows the results:

contextmenu2 

If you’ve been paying attention to the HTML evolution, then you know that the HTML5 spec introduces the contenteditable attribute which can be used to make the content of an element editable. Even though the docs say that setting this attribute to true is enough for making the element selectable (and it is!), there’s a bug in the current preview release associated with the context menu: whenever you apply the contenteditable attribute to an element, you can select text, but right clicking over that selection will not show you the context menu. Since we’re talking about bugs, it’s also important to notice that right clicking over selected text will also end up showing the appbar (if there’s one). I expect to see both these problems solved until we get a final release.

Now that we’ve already discussed some of the basics, you might be wondering about the code needed to show a context menu. The strategy is rather simple:

  1. we start by setting up an event handler for the context menu event;
  2. we prevent the default behaviour from within that handler;
  3. we create a new PopupMenu control and populate it with the required UICommand entries;
  4. we show the menu in the appropriate place by using the showAsync or showForSelectionAsync method.

To illustrate these points, we’ll replace the default context menu shown when the user right clicks over the selected text of the paragraph presented in the beginning of this post. As I’ve said, the first thing we need to do is set up an event handler for the context menu event of our paragraph. This can be done from within an initialization function which, for instance, is called from within the DOMContentLoaded event handler:

document.getElementById("paragraph1").addEventListener(
    "context menu", showContextMenu, false);

Lets take a look at the code used inside the showContextMenu function:

function showContextMenu(evt) {
    evt.preventDefault();
    var menu = new Windows.UI.Popups.PopupMenu();
    menu.commands.append(
      new Windows.UI.Popups.UICommand("Copy", null, 1));
    menu.commands.append(
      new Windows.UI.Popups.UICommandSeparator());
    menu.commands.append(
      new Windows.UI.Popups.UICommand("Search", null, 1));
    menu.showAsync({ x: evt.screenX, y: evt.screenY }, "above")
        .then(function (cmd) {
                //handle command
        });
}

After preventing the default context menu from being shown, we start by creating the PopupMenu which will replace the default  context menu. This new context menu is populated with two UICommand instances and one separator (represented programmatically by a UICommandSeparator instance). All UICommand instances expect at least two parameters: a string which will be displayed in the menu and a callback function which will be invoked when that option is selection (which you can set to null!). Optionally, you can also pass a third parameter, which is used for setting the command identifier (in the previous example, I’ve resorted to an integer, but you can pass any object you want).

In this example, I’ve opted for using the showAsync method and for placing the menu according to the screen coordinates of the event object. Notice also that I’m passing a success callback to the then method, which will be called when the context menu is dismissed. The cmd parameter will only hold a valid value when you pick a command from the menu. When that happens, you’ll end up receiving the UICommand that has been selected by the user. You can then inspect that object and decide what you should do. The next image shows our new context menu in action:

contextmenu3

And that’s it for now. Stay tuned for more about Windows 8 Metro dev.

Advertisements

~ by Luis Abreu on January 12, 2012.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: