Adding context menu for a WinJS custom control

Published August 12, 2013 1:18 pm

Recently, we were adding a WinJS custom control for image selection. It needs to handle things like – show progress ring during image load; show load error if image failed to load; allow user to select a new image; etc. The custom control also needs to display a context menu.

Windows.UI.Menu provides the way to show context menu as flyout and quite straight forward. Need to define the menu in the html, and show the flyout in an event handler on user gesture. Example html:

<div id="imageSelectControlMenu" data-win-control="WinJS.UI.Menu">
    <button data-win-control="WinJS.UI.MenuCommand" 
      data-win-options="{ extraClass: 'delete', label: 'Delete' }"></button>
    <button data-win-control="WinJS.UI.MenuCommand" 
      data-win-options="{ extraClass: 'undo-delete', label: 'Undo Delete' }"></button>
    <button data-win-control="WinJS.UI.MenuCommand" 
      data-win-options="{ extraClass: 'clear-new-selection', label: 'Clear New Selection' }"></button>
</div>

Example js:

 
_initializeEventHandlers: function initializeEventHandlers()
{
    this.element.addEventListener('contextmenu', this._oncontextmenu.bind(this));
},
_oncontextmenu: function oncontextmenu(event)
{
    var menu = document.querySelector('#imageSelectControlMenu');
    menu.winControl.show(this.element, 'right', 'center');
},

so far so good. This is where I hit the issue of context menu showing and hiding immediately. Context menu will show up and hide immediately in less than a sec. In process to get to the root cause of the issue, I tried GestureRecognizer which exposes high level gesture events when passed the mouse events for an element. There is a good sample available for it. It takes few minutes to digest what Gesture Recognizer provides. Few notes from my usage:

  1. Typically, it will come handy for a custom control where you want to control how to raise gesture events for mspointer events.
  2. I only used it to get ‘tapped’, ‘righttapped’ events. I did not use it for manipulation events or custom gesture events. DOM ‘click’ and ‘contextmenu’ events give the same functionality as ‘tapped’ and ‘righttapped’ events respectively.
  3. Sample code gives feel how to pass it mouse pointer events.

After using the GR, I found that the issue did not go away. After few minutes of debugging, root cause was found. It was missed ‘preventDefault()’ call in the handler for ‘contextmenu’ event.

 
_oncontextmenu: function oncontextmenu(event)
{
    var menu = document.querySelector('#imageSelectControlMenu');
    menu.winControl.show(this.element, 'right', 'center');
    event.preventDefault();
},

I need to this css to fix the layout of the context menu.

.my-custom-control .win-menu
{
    width: 10em;
    padding-left: 1em;
}