Class: cWebContextMenu

Properties  Events  Methods    Index of Classes

Menus that appear when right-clicking on elements

Hierarchy

cObject
---cWebObject
------cWebBaseUIObject
---------cWebBaseDEOServer
------------cWebBaseContainer
---------------cWebFloatingPanel
------------------cWebContextMenu

Library: Web Application Class Library

Package: cWebContextMenu.pkg

Mixins: cWebBaseMenu_mixin

Description

cWebContextMenus are menus that appear when right-clicking on elements.

cWebContextMenus are not supported on mobile devices.

Just like all other cWebMenu* controls, cWebContextMenus are nestable. cWebContextMenu functions exactly like a cWebMenuList from the menu interface perspective.

The concept of a cWebContextMenu is to provide a menu for another element/object and give options to interact with that object.

When implementing a ContextMenu, use two words; "scope", and "focus". The Scope (red) is the parent (scope) the Menu works in. Commonly the Menu would be attached to, for example, a cWebList and, as such, should only work within that List. The Focus (green) is the element or are the elements that provide the information for the Context.

In the cWebList's case, these would be the rows. Each row has one thing that is commonly unique, which is its RowId. When using a cWebList in a custom mode, you set these yourself, but in most cases, it is filled in by the table for that object. Using this RowId, you can find that record and do with it whatever you want as you will see in the General Outline.

General Usage Outline

The cWebContextMenu can be used in multiple ways:

Using object inheritance

For example, add a ContextMenu for a cWebList or cWebGrid, you can add a cWebContextMenu Object to the scope like you do with cWebColumns. Afterwards, set peContext to specify that it should use C_WebUIContextListRow. These predefined Contexts will help to set its focus to just the rows themselves and also provide the context references later.

From the OnContextMenuOpen event on, the psContextValue is filled with whatever the Context provides. In most cases, this is the RowId as a String.

You can also use OnContextMenuOpen to cancel the opening of the menu.

Sample

You can see this being used in the sample below. This sample fires only when right-clicking on a cWebList row, using a confirmation message we later remove that row from the cWebList (not from the DD).

Object oWebListExtention is a cWebContextMenu
    Set peContext to C_WebUIContextListRow
    
    Object oRemove is a cWebMenuItem
        Set psCaption to "Remove Row"
        
        Procedure ConfirmDelete Integer eConfirmMode
            String sRowId
            
            If (eConfirmMode=cmYes) Begin
                WebGet psContextValue of oContextMenu to sRowId
                Send RemoveRow of oDetailGrid sRowId
            End
        End_Procedure
        
        WebPublishProcedure ConfirmDelete
        
        Procedure OnClick
            Send ShowYesNo Self (RefProc(ConfirmDelete)) ;
                @"Are you sure you want to delete this entry!?" ;
                "Question"
        End_Procedure
    End_Object
End_Object  


Using phoControl

Web Objects are parent directed and disabling a parent will also disable the ContextMenu. To be able to use a ContextMenu while its parent is disabled, the ContextMenu can be moved to be a sibling and by then setting phoControl to its sibling; it will work completely the same but without the parent constrains.

Object oContextMenu is a cWebContextMenu
    Set phoControl to oCustomerName
    Set pbServerOnContextMenuOpen to True
    
    Procedure OnContextMenuOpen Boolean ByRef bCancel
        If (Customer.Name = "") Begin
            Move True to bCancel
        End
    End_Procedure
    
    Object oCall is a cWebMenuItem
        Set psCaption to "Call"
        
        Procedure OnClick
            Send ShowInfoBox ;
                (SFormat("Please Call: %1.", ;
                      Trim(Customer.Phone_Number)))
        End_Procedure
    End_Object
End_Object


Using it for the current "window"

psControlName is a property that designates the scope of the cWebContextMenu just like you would with phoControl, the only difference is that psControlName does it by WebObjectName(). This can be used with, for example, Dynamic Objects, but it can also be used to set it to the whole window.

While setting phoControl to the view might work for most cases, you might want the option to also cover the WebApp's menu and toolbars. In that case setting phoControl to "window" will cover that usecase.

Object oContextMenu is a cWebContextMenu
    Set psControlName to "window"
    
    Object oCall is a cWebMenuItem
        Set psCaption to "Call"
        
        Procedure OnClick
            Send ShowInfoBox "Call us at: +001 5521 166555"
        End_Procedure
    End_Object
End_Object


Using it for the whole WebApp

In some use cases, you might want to use a ContextMenu for the whole WebApp, for example the Clear, ClearAll, and Save buttons. By placing a ContextMenu in your oWebApp object, it will automatically attach and can be used anywhere. This mimics "window" but the WebApp method will work across all views and not just `that' one.

Object oWebAppContextMenu is a cWebContextMenu
    Object oClearAll is a cWebMenuItem
        Set psCaption to "Clear All"
        
        Procedure OnClick
            Handle hoFocus
            Get DEOFocusObject to hoFocus
            If hoFocus Begin
                Send Request_Clear_All of hoFocus
            End
        End_Procedure
    End_Object
End_Object


Advanced/Customization

By default, C_WebUIContextCustom is the peContext, this means is that the ContextMenu does not yet have a focus. As such, it will trigger for the whole scope, while not providing any psContextValue. By using the custom context, it can be used with controls that do not have a predefined C_WebUIContext*.

psContextCSSSelector is a Web Property we can manually set a Focus with. It can be set to a CSS selector (https://www.w3schools.com/cssref/css_selectors.asp). Using a previous sample, I wish the Menu to only appear at the text field itself. When looking at the HTML elements beneath, you will see it is an `input'. Setting the psContextCSSSelector to "input" will only make it appear within that element.

Object oContextMenu is a cWebContextMenu
    Set phoControl to oCustomerName
    Set pbServerOnContextMenuOpen to True
    Set psContextCSSSelector to "input"
    
    Procedure OnContextMenuOpen Boolean ByRef bCancel
        If (Customer.Name = "") Begin
            Move True to bCancel
        End
    End_Procedure
    
    Object oCall is a cWebMenuItem
        Set psCaption to "Call"
        
        Procedure OnClick                      
            Send ShowInfoBox ;
                (SFormat("Please Call: %1.", ;
                            Trim(Customer.Phone_Number)))
        End_Procedure
    End_Object
End_Object 


Sample

This sample shows how to implement a web context menu in a cWebHTMLBox.

Object oWebContextMenuMenuOptions is a cWebContextMenu
    Set psContextCSSSelector to "div"
    Set pbChildScopes to True
    Set pbShowIcons to True
    Set pbServerOnContextMenuOpen to True
    
    Procedure OnContextMenuOpen Boolean ByRef bCancel
        // Dynamically enable or disable some menu items
    End_Procedure
    
    Object oWebMenuItemDoStuff1 is a cWebMenuItem
        Set psCaption to "DoStuff1"
        Set psCSSClass to "MyIcon1"
        
        Procedure OnClick
            String sValue
            
            Forward Send OnClick
            
            Get ContextScope of oWebContextMenuMenuOptions to hoCurrentObject
            
            If (hoCurrentObject=C_WebUnresolvedObject) Begin
                // Just in case the handle is undefined
                Procedure_Return
            End
            
            WebGet psValue of hoCurrentObject to sValue
            Send ShowInfoBox sValue "DoStuff1"
        End_Procedure
    End_Object
    
    Object oWebMenuItemDoStuff2 is a cWebMenuItem
        Set psCaption to "DoStuff2"
        Set psCSSClass to "MyIcon2"
        
        Procedure OnClick
            String sValue
            
            Forward Send OnClick
            
            Get ContextScope of oWebContextMenuMenuOptions to hoCurrentObject
            
            If (hoCurrentObject=C_WebUnresolvedObject) Begin
                // Just in case the handle is undefined
                Procedure_Return
            End
            
            WebGet psTooltip of hoCurrentObject to sValue
            Send ShowInfoBox sValue "DoStuff2"
        End_Procedure
    End_Object
    
    Object oMyObject1 is a cWebHTMLBox
    // properties here
    End_Object
    
    Object oMyObject2 is a cWebHTMLBox
    // properties here
    End_Object
End_Object


Custom Controls

Sometimes you also want the cWebContextMenu to work with a custom control, like a WYSIWYG editor. To make this work, you can use psContextCSSSelector and multiple Menus; this will work for most cases since you would pretty much know what is clicked on.

But if you also need the Context-data. You might want to make it support a peContext and make it set psContextValue. This does require at least some JavaScript knowledge.

If a custom control is desired to support the WebUIContext interface, then it is advised to create a new WebUIContext identifier complimented by the implementation of the following interfaces on the Client-side:

determineSelectorForWebUIContext [eContext : WebUIContext] : String

This function returns the CSS selector (psContextCSSSelector) for the set context on the calling object (cWebContextMenu). If no selector is available for the passed context, then [null] should be returned.

verifyElementForWebUIContext [eElem : HTMLNode, eContext : WebUIContext] : Boolean

This interface is not required, but might be useful is cases where you need to further verify whether the element is valid at runtime.
This function is called just before the menu determines it should show itself. It returns true by default; should it return false then the context menu won't show itself.

retrieveValueFromWebUIContext [eElem : HTMLNode, eContext : WebUIContext] : Object/String

If peContext is not C_WebUIContextCustom and the control implemented the retrieveValueFromWebUIContext function, it will request the value from the previously validated element by WebUIContext.

If [null] is returned, the context handling object (cWebContextMenu) will throw an error.
A valid return value is either a JavaScript Object or a string. An object in this case will be serialized to JSON in String format. Afterwards the returned value is available in psContextValue.