Context menus in Sciter

Context menu is a standard UI feature and in order to support them Sciter has following mechanisms on board:

  1. custom CSS property named context-menu. It defines location of DOM element ( usually it is one of <menu class=context> ) that will appear on context menu activation.
  2. Menu behaviors and their DOM events associated with menus.
  3. Context menu activation and initialization mechanism.

context-menu style property

Sciter specific context-menu is non-inheritable CSS property that accepts one of the following values:

  • none – default value, the element has no context menu;
  • selector(...) – defines selector of existing DOM element that is used as a menu ( usually it is one of <menu class=context> elements);
  • url(...) – defines URL of [partial] HTML containing menu definition.

Example:  

  <style>
  
    div.bar { context-menu: selector(menu#foo); }
    div.baz { context-menu: url(for-baz.htm); }
  
  </style>

  <div class="bar">With #foo context menu</div> 
  <div class="baz">With for-baz.htm context menu</div> 

  <menu class=context id="foo">
    <caption>#foo menu for .bar elements</caption>
    <li id="i1">First item</li>
    <li id="i2">Second item</li>
    <li id="i3">Third item</li>
    <li id="i4">Fourth item</li>
  </menu>

external-menu

There are two elements that will have context menu in this markup:

  • <div class=bar>   – will have context menu#foo and   
  • <div class=baz>   – will have context menu created by loading for-baz.htm partial HTML document.

Content of that for-baz.htm document may look like as:

<menu>  
  <caption>External menu:</caption>
  <li id="mi1">First item</li>
  <li id="mi2">Second item</li>
  <li id="mi3">Third item</li>
  <li id="mi4">Fourth item</li>
</menu>

behavior:menu and its events

By default each <menu class=context> (or simply <menu.context> ) has behavior:menu; attached to it.  

Main purpose of behavior:menu is to support basic menu operations:

  • navigation, including hierarchical menus navigation;
  • generation of menu click events.

When user clicks on one of menu options the behavior generates bubbling Event.MENU_ITEM_CLICK with:

  • Event.target , DOM element – clicked menu item element;
  • Event.owner, DOM element – owner of the menu – element that has context-menu defined on it.

MENU_ITEM_CLICK events are dispatched using special bubbling rules:  MENU_ITEM_CLICK will be received not by physical DOM parents but by [logical] owners of the menu – by elements – owners of the context menus.

Therefore in order to handle menu clicks you can subscribe either to raw control events:

var elemWithMenu  = self.select("div.baz");

elemWithMenu.onControlEvent = function(event) {
  if( event.type == Event.Event.MENU_ITEM_CLICK )  {
      var menu_item = event.target; 
      ...
  }
}

or by using jQuery alike mechanism:

elemWithMenu.subscribe("click", "menu > li", function(event) {
   var menu_item = event.target;
   var owner = event.owner;
});

Context menu activation and initialization

Context menu activation starts from receiving of WM_CONTEXTMENU  on Microsoft Windows or Right-Mouse-click on Mac OS X.

When Sciter receives context menu activation request it does the following:

  1. Finds element under the mouse or element in focus (topmost mouse hover element) and sends bubbling Event.CONTEXT_MENU_REQUEST to it.
    • If some element in parent/child chain consumes the event (returns true from that event handler ) and sets element.source = someMenuElement to some existing DOM element then that element is used as a context menu. Any CSS context-menu declarations are ignored in this case.
    • If Event.CONTEXT_MENU_REQUEST is not handled by user’s code then the engine creates menu by inspecting context-menu declarations in elements of child-parent chain of topmost mouse hover element. First element in the chain that has context-menu defined is declared as menu owner and menu is created for it.
  2. As last step before showing the menu the engine sends bubbling Event.CONTEXT_MENU_SETUP to the menu owner and all its parents. By handling Event.CONTEXT_MENU_SETUP the menu owner and all its containers can participate in setting up the menu. The Event.CONTEXT_MENU_SETUP is being sent with:
    • event.target == menu owner element;
    • event.source ==  the menu.

Check context menu sample in Sciter SDK: /samples/menu/context-menu.htm

Note that context menu as any other popup element is Sciter may have arbitrary markup and styles. For example context menu may have items organized horizontally. Or may have <input|text> inside if needed.

Leave a Reply

Your email address will not be published. Required fields are marked *