cObject
---cWebObject
------cWebBaseUIObject
---------cWebBaseDEOServer
------------cWebBaseContainer
---------------cWebFloatingPanel
------------------cWebContextMenu
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.
The cWebContextMenu can be used in multiple ways:
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.
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
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
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
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
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
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
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.