Extension for ClassicUI
Customize an object's functions menu: CSMenu¶
Content Script can be used to perform changes to the standard object function menus, by adding new options or removing existing ones. This feature is enabled by defining a Content Script that “filters” the object menu and performs the desired modifications. The “amgui” service provides a user-friendly interface to perform modifications to the menu object.
As for most other features configured through the Content Script Volume, a convention-over-configuration approach has been adopted.
The target container in which to place the Content Scripts is CSMenu. The first level under this container identifies the objects to which the customizations are applied. The naming convention is one of the following:
-
D<nodeID>
-
S<subtype>
where nodeID identifies the node unequivocally and subtype identifies a specific object subtype on Content Server.
Examples:
D2000 will change the function menu of the Enterprise Workspace
S144 will change the function menu of Document type objects (subtype: 144)
The following example shows a menu customization script that includes:
-
fetching the original menu
-
filtering the original menu entries (removing entries that match a specific expression)
-
adding a divider row to split menu entries
-
adding a submenu
-
adding a custom menu entry to the new submenu
-
returning the modified menu
E.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | def csMenu = amgui.getCSMenu() //retrive the current object's menu try{ def node = docman.getNodeFast(nodeID) /** A filter is a closure that returns true if the menu item shall be kept, false otherwise. In the filter function scope the object "it" represent the menu item. A menu item has the following properties: - name (string) - url (string) - openInNewTab (boolean ) *available only on 10.5 - order (decimal) **/ csMenu.filter {it.name == "Open"} csMenu.appendDivider() //use appendDivider(position) to specify a position def submenu = csMenu.appendSubMenu("My sub-menu") //use appendSubMenu(name, position) to specify a position submenu.appendItem("My menu item", "${url}?func=ll&objAction=properties&objId=${nodeID}&nextUrl=${params?.nextUrl?.encodeURL()}") }catch(e){ log.debug("Unable to apply changes to add items menu",e) } return amgui.returnCSMenu(csMenu) |
Property | Type | Description |
---|---|---|
name | String | Label of the menu entry (only for menu items and submenus) |
openInNewTab | Boolean | If true opens a new target browser window (only for menu items) |
position | String | The order of the entry in the menu (available for menu items, submenus and dividers) |
url | String | The target URL (only for menu items) |
Notice that all operations are performed either through the amgui service or the CSMenu and CSSubMenu objects.
Return the proper value
The last operation performed in a CSMenu script should always be a call to the “returnCSMenu(...)” API of the amgui service
Customize a space's add-items menu: CSAddItems¶
Content Script can be used to perform changes to a container’s Add Item menu, by adding new options or removing existing ones. This feature is enabled by defining a Content Script that “filters” the menu and performs the desired modifications. The “amgui” service provides a user-friendly interface to perform modifications to the menu object.
As for most other features configured through the Content Script Volume, a convention-over-configuration approach has been adopted.
The target container in which to place the Content Scripts is CSAddItems. The first level under this container identifies the objects to which the customizations are applied. The naming convention is one of the following:
-
D<nodeID>
-
S<subtype>
where nodeID identifies the node unequivocally and subtype identifies a specific object subtype on Content Server.
Examples:
D2000 will change the add items menu of the Enterprise Workspace
The following example shows a menu customization script that includes:
-
filtering the original menu entries (removing entries that match a specific expression)
-
adding a custom menu entry
-
returning the modified menu
E.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | try{ //The current space def node = docman.getNodeFast(nodeID) /** Other possibile filter examples: it.name == "Folder" it.subtype == 0 **/ amgui.filterAddItems { it.name == "Folder" } /** Other possibile filter examples: it.name == "Folder" it.subtype == 0 **/ amgui.filterAddItems ({false}, true) amgui.addBrowseViewAddItem( amgui.newBrowseViewAddItemsMenu().builderUrl().setImg("${img}folder_icons/folder5.gif") .setName("My new object") .setPromoted(true) .setUrl("${url}?func=ll&objAction=create&objType=0&parentId=${node.ID}&nextUrl=${params?.myUrl?.encodeURL()}").create() ) }catch(e){ log.debug("Unable to apply changes to add items menu",e) } return amgui.returnAddItemsMenus() |
Invoke a Content Script
The url of the menu entry could be used to pass parameters to a custom Content Script that will perform the desired operations.
Return the proper value
The last operation performed in a CSAddItems script should always be a call to the “returnAddItemsMenu(...)” API of the amgui service
Customize a space's buttons bar: CSMultiButtons¶
Multi-action buttons can be added, removed or modified by using an approach similar to the CSMenu customization. In this case, customization scripts should be added in the CSMultiButtons container. The container structure is the same as the one described for the CSMenu.
As for most other features configured through the Content Script Volume, a convention-over-configuration approach has been adopted.
The target container in which to place the Content Scripts is CSMultiButtons. The first level under this container identifies the objects to which the customizations are applied. The naming convention is one of the following:
-
D<nodeID>
-
S<subtype>
where nodeID identifies the node unequivocally and subtype identifies a specific object subtype on Content Server.
Examples:
D2000 will change the buttons bar menu of the Enterprise Workspace
E.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | try{ amgui.addBrowseViewMultiItemButton( amgui.newBrowseViewMultiItemButton() .builder() .setOrder(1100) .setJavascriptFunctionName('runContentScript') .setJavascriptFile("anscontentscript/js/contentScriptMultifileBar.js") .setImageMap("anscontentscript/contentscriptmultifilebar.png") .setImageXPos(0) .setImageYPos(0) .setImageXPosAlternative(-268) .setImageYPosAlternative(0) .setDisplayName('My button') .create() ) /** Properties that can be used to filter the buttons bar: - action (the request handler to be executed e.g. ll.ProcessMultiCopy) - Order - Name - DisplayName - ExecutesOnClient **/ amgui.filterBrowseViewMultiItemButton {it.name == "mybutton"} }catch(e){ log.debug("Unable to apply changes to add multi items buttons bar",e) } return amgui.returnBrowseViewMultiItemButtons() |
where the following fields are mostly relevant:
Property | Type | Description |
---|---|---|
ImageMap | String | The path of the image map file (in the Support folder) containing the button icon |
ImageXPos, ImageXPos2, ImageYPos, ImageYPos2 | Integer | The coordinates of the portion of the image map to use for the button (normal and on mouse over) |
Order | String | The order of the button in the menu bar |
Type | String | The button type (should be “Content Script”) |
ExecutesOnClient | boolean | If the button logic is on the client side (should be “true”) |
DisplayName | String | The button label |
Name | String | The name of the button |
JavascriptFile | String | The javascript resource in which the function controlling the button behavior is defined |
JavascriptFunctionName | String | The javascript function defined in the JavascriptFile that controls the button behavior |
Invoke a Content Script
A sample Javascript file (contentScriptMultifileBar.js) is located in the Content Script Module support folder. Create a customized version of this file when adding new actions.
Customize a space's displayed columns: CSBrowseViewColumns¶
Content Scripts located in the CSBrowseViewColumns container can be used to perform modifications to how columns are presented in the standard Content Server Browse View.
The modifications can be limited to specific portions of Content Server. This feature is enabled by defining a Content Script that “filters” the browse view columns configuration and performs the desired modifications. The “amgui” service provides a user-friendly interface to perform the modifications.
As for most other features configured through the Content Script Volume, a convention-over-configuration approach has been adopted.
The target container in which to place the Content Scripts is CSBrowseViewColumns. The first level under this container identifies the objects to which the customizations are applied. The naming convention is one of the following:
-
D<nodeID>
-
S<subtype>
where nodeID identifies the node unequivocally and subtype identifies a specific object subtype on Content Server.
Examples:
D2000 will change the columns visible in the Enterprise Workspace
The following example shows a browse view columns customization script that includes:
-
create a new column using the builder
-
filtering the original columns list (removing entries that match a specific expression)
-
adding the column to the view
-
returning the modified columns list
E.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | try{ /** A browse view column is quite a complex object. The amgui service provides you with a builder in order to help you in creating it. **/ def columnBuilder = amgui.newBrowseViewColumn().builder() .setColumnName("type") // Column name corresponds to the property //from the browse view row that will be used //to populate the column. .setDisplayName("Type") // Column display name is the label used for the column. .setAlignment("left") .setSortable(true) // If sortable the Javascript sorting //function will look for a property named: // columnName+'SortStr' or columnID+'SortStr' // to perform sorting .setColumnEMWidth(1.0) .setDisplayAsLink(true) .setNewWindow(true) .setUrl("${url}?param=%value%") // The url to be opened. // The following placeholder // can be used in the expression: // %value%, %objid%, %rawvalue%, %nexturl%" .setFormatValueMask("Type :%value%") // The format mask to be used to // present the column value. // The following placeholder // can be used in the expression: // %value%, %objid%, %rawvalue%, %nexturl%" /** A filter is a closure that returns true if the column shall be kept, false otherwise. In the filter function scope the object "it" represent the column object. For default columns the only attribute available is columnID (string) which might have one out the following values (checkBoxColumn, typeColumn, nameWthPrmtdCmdsColumn ("name with promoted commands column"), sizeColumn, dataidColumn, dateColumn, arbitraryColumn, columnWithURL, userColumnWithURL) All the other columns have the following properties: DisplayAsLink (boolean), DisplayValue (string), NewWindow (boolean), NewWindowTitle (string), URL (string), alignment (string), columnID (string), columnName (string), displayName (string) **/ amgui.filterBrowseViewColumn { it.columnID != "dateColumn" } amgui.addBrowseViewColumn(columnBuilder.create()) }catch(e){ log.debug("Unable to apply changes to add items menu",e) } return amgui.returnBrowseViewColumns() |
The following properties are available for each column object (they are managed through a builder the CSBrowseViewColumnBuilder
obtained :
Property | Type | Description |
---|---|---|
isDefault | boolean | True if the column has a Javascript definition |
sortable | boolean | True if the column has a Javascript definition |
DisplayAsLink | boolean | The value of the column will be wrapped into an HTML link |
DisplayValue | String | The column's value |
NewWindow | boolean | If DisplayAsLink = true, opens the link in a new window |
NewWindowTitle | String | If DisplayAsLink = true, the title of the window in which link will be opened |
Url | String | If DisplayAsLink = true, the URL to be used for building the link |
alignment | String | Column alignement. One out: 'left', 'right', 'center' |
columnID | String | Column unique identifier |
columnName | String | Column name |
displayName | String | Column name as it will be displayed in the page |
displayName | String | Column name as it will be displayed in the page |
Filtering columns - lines from 39 to 41
A filter is a closure that returns true if the column shall be kept, false otherwise.
Default Columns¶
Default columns are columns for which a Javascript column definition exists. Default columns Javascript definitions can be found in webnode/browse.js file. The following default columns definition should exist in your environment:
Value | Description |
---|---|
checkBoxColumn | Used for selecting multiple nodes |
typeColumn | Represents the node's type in the form of a web-icon |
nameWthPrmtdCmdsColumn | Name with promoted commands column |
sizeColumn | Size of the document or number of items in the space |
dataidColumn | Node's unique system identifier |
dateColumn | Node's last modification date |
arbitraryColumn | Template for other columns (ABSTRACT) |
columnWithURL | Template for other columns (ABSTRACT) |
userColumnWithURL | Node's owner |
The amgui service features a method that can help you in creating your own custom column Javascript definition on the basis of a template that is stored in the Content Script Volume (CSVolume:CSGui:BrowseViewColumnDefinition
). The custom Javascript column's definition can be rendered, for example, as part of a customview, an appearance or a Content Script
1 2 3 4 5 6 7 8 9 | amgui.getBrowseViewColumnDefinition( String columnID, //The id of the column Map templateContext, // A map to be used as model for // the column's definition template [,CSDocument param ] // An optional template document. // If none is provided the default // CSVolume:CSGui:BrowseViewColumnDefinition // will be used ) |
Here below a real-world usage example. The Script is used to create a custom view within the space in which is stored.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | jsAddCell = """ var cell; try { cell = rowStruct.insertCell( cellCount++ ); cell.className = this.cellClassName; if ( true === this.nowrap ) { cell.style.whiteSpace = 'nowrap'; } cell.innerHTML = this.getCellValue( dataRow, rowNo ); } catch(e) { exceptionAlert( e, "Issue occured in browse.js/htmlColumn.AddCell." ); } return cellCount; """ jsGetCellValue =""" var val = dataRow[ 'pstatus' ]; if ( val == undefined ) { val = ""; } return val; """ def customView = docman.getTempResource("customView", ".html") customView.content.withWriter{ it << amgui.getBrowseViewColumnDefinition("pstatus", ["jsAddCell":jsAddCell, "name":"Status", "jsGetCellValue":jsGetCellValue, "cellWidth":"10%"]) } def cv = docman.createCustomView(self.parent, "customView", customView.content) cv.setIsHidden() cv.update() |
For default columns (listed in the table above) the only attribute available is columnID (string).
Customize a space content view: CSBrowseView¶
Content Scripts located in the CSBrowseView container can be used to perform modifications on the content of a browse view.
The target container in which to place the Content Scripts is CSBrowseView. The first level under this container identifies the objects to which the customizations are applied. The naming convention is one of the following:
-
D<nodeID>
-
S<subtype>
where nodeID identifies the node unequivocally and subtype identifies a specific object subtype on Content Server.
The following example shows a browse view customization script that will iterate on each row in the browse view and perform modifications for objects of subtype 43200 (Content Scripts)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | try{ /** Properties that can be used to filter the browse view rows: - dataId (Numeric) - name (String/Html will be rendered inside an 'a' tag) - link (String) - size (String/Html e.g. '1 KB') - date (String e.g. - imgStr (String) - imgLargeStr (String) - imgThumbnailStr - promotedCmds (Html) - modifiedImgs (Html) - imgStatus (String) - statusName (String) **/ amgui.filterBrowseView { row -> // Just for Content Scripts if(row.type == "43200"){ row.checked = true row.name = "${row.name.toUpperCase()}" row.promotedCmds = """ <div style="font-weight:bold;background-color:#EFEFEF;padding:10px;">${row.promotedCmds} </div>""" row.modifiedImgs = "<img src='${img}webnode/new.gif' />" row.imgStatus = "${img}webnode/new.gif" row.statusName = "Ready to be executed" row.link ="http://www.answermodules.com/products/content-script" row.size = "not so big afterall..." row.date = amgui.formatDateForBrowseView(new Date()) //This is a shortcut to format data row.imgStr = "${img}anscontentscript/lib/img/icons/product-design.png" row.imgLargeStr = "${img}anscontentscript/lib/img/icons/product-design_large.png" row.imgThumbnailStr = "http://www.answermodules.com/img/content-script/content-script-banner.png" } // This to be sure that the rows will be rendered return true } }catch(e){ log.debug("Unable to filter browse view rows for node {}", nodeID, e) } return amgui.returnBrowseViewRows() |
Filtering rows - lines from 20 to 42
The filtering closure passed as parameter to the amgui.filterBrowseView(...) method should return a boolean value of “true”. If “false”, the row will not be rendered.
Add a new row
It is possible to add new rows from scratch by using the amgui.addBrowseViewRow(...) method. A blank row template can be obtained through the amgui.newBrowseViewRow() method
The following properties are available for filtering or modification on each row object that is being iterated:
Property | Type | Description |
---|---|---|
dataId | Numeric | The node's unique identifier |
name | String/HTML | The node's name Html will be rendered inside an 'a' tag |
link | String | The link to be associated to the node's name |
size | String/HTML | The node's side e.g. '1 KB' |
date | String | The node's last modification date |
imgStr | String | The url for the node's icon |
imgLargeStr | String | The url for the node's icon when the node is featured |
imgThumbnailStr | String | The url for the node's thumbnail |
promotedCmds | HTML | The HTML code containing links to the node's promoted functions (can be any HTML) |
modifiedImgs | HTML | The HTML code to be used to notify users that the node's has been modified |
imgStatus | String | The url for the node's status icon |
statusName | String | The node's status name |
Create a custom column backed by Content Script: CSDataSources¶
Since version 1.5 Content Scripts can be used as Column Data sources. Content Scripts placed in the CSDataSources Template Folder will automatically be available as Column Data Sources.
The CSDataSource scripts will automatically be invoked by Content Server for each node of the system, and the resulting value will be used as a column value.
Return the proper value
A CSDataSource Content Script MUST always return a String object.
In the Content Script code, the execution context will be enriched by the framework with the following information related to the current node:
-
volumeID
-
parentID
-
dataID
-
createDate
-
modifyDate
As per standard column data sources the developer is in charge of defining and implement a reliable updating strategy. Most of the time the task can be accomplished implementing either a synchronous or an asynchronous (see Managing events) event script.
As a matter of fact, Content Script features two different APIs that can be used to update columns' datasources values.
1 2 3 4 5 6 7 8 9 10 | docman.updateColumnValue( CSNode node, //The node for which you want to update the column's value String dataSourceId, // The standard identifier for the column's datasources String columnValue // The new value for the column ) docman.updateContentScriptColumnValue( CSNode node, //The node for which you want to update the column's value String scriptName, // The name of the Content Script script that serves // datasource String columnValue // The new value for the column ) |
The first one is supposed to be used with standard columns’ datasources, the latter with Content Script backed columns' datasources.
The updateContentScriptColumnValue takes as secondo parameter the name of the Script used to implement the column’s datadasouce.
The updateColumnValue method takes as second parameter a dataSourceIdentifier, which can be easily determined inspecting the ExtendedData column’s value of the corresponding Column object on the DTree table (property “dataSource”).
E.g.
1 2 3 4 5 6 7 8 9 10 | def exData = sql.runSQL( """ select ExtendedData EXT from DTree where DataId = %1 """, false, false, -1, 2109 //The column object DataId ).rows[0].EXT out << extData.getMapFromOscript().dataSource //Returns sys_CreateDate //(on most of the systems) |