Méthode Swing documentation
Context Object Reference
The Context Object is a Javascript object available throughout the Swing Extensions. In every extension point, the context object can be accessed and its methods called.
The Context Object is composed of public methods (see Public methods), object-specific methods (see Object class methods), and user-specific methods (see User class methods). If the context object is referred to a specific object, an activeObject property is available (see activeObject). To support object panel bulk mode use activeObjects instead. If the context object is inside a supported Editor, the activeDocument property is available (see activeDocument). Starting from version 5.2020.11 if the context object is inside a supported Editor, the activeDocumentV2 property is available (see activeDocumentV2)
Through a new shared object will be available a set of api(s) to handle the document with new logics to support the report case. These api(s) will be supported among Swing, Prime and Swing Mobile.
Public methods
List of methods
Name |
Description |
Obtains the application info. |
|
Obtains the area info. |
|
Returns an array containing the string XML fragments obtained from the evaluation in the siteConfig.cfg file of the provided xpath. |
|
Obtains the communication status. |
|
Obtains the component info. |
|
Reads a file given its filename, and returns it in a particular format. |
|
Executes a Methode query. |
|
Reads a user data content given its filename. |
|
Adds a new JSON object to the specified user data content. |
|
Set a new JSON array to the specified user data content. |
|
Obtains a content of a document, given its path |
|
Obtains the current user |
|
Obtains a Methode object, given its id |
|
Obtains a Methode object, given its path |
|
Obtains the Platform information |
|
Obtains a user, given its name |
|
Obtains the list of member names, given a group name |
|
Open a Methode document, given its id |
|
Open the new content dialog, with the selected options |
|
Open a Methode document, given its id, in readonly mode |
|
Opens a popup panel |
|
return the last selected element in the editor context in the form of Object Class instances. |
getApplicationInfo
Retrieves the application info and returns a JSON object containing the context and the name of the application.
{
context: "/swing",
name: "Swing"
}
Syntax
ctx.getApplicationInfo()
Returns
Type |
Description |
{JSON Object} |
A json object containing the context and the name of the application. |
Example
var applicationInfo = ctx.getApplicationInfo();
getAreaInfo
Retrieves the area info and returns a JSON object containing the area type and the area name.
{
name: "story",
type: "editor"
}
Syntax
ctx.getAreaInfo()
Returns
Type |
Description |
{JSON Object} |
A json object containing the area type and the area name. |
Example
var areaInfo = ctx.getAreaInfo();
getSiteConfigFragment
Returns an array containing the string XML fragments obtained from the evaluation in the siteConfig.cfg file of the provided xpath.
Syntax
ctx.getSiteConfigFragment(xpath);
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
|
Example
var presetCropsArray = ctx.getSiteConfigFragment('/siteConfiguration/presetCrops');
/*
presetCropsArray:
[ "<presetCrops>
<crop channel="Globe-Web,Globe-Print,Globe-WireNews" favorite="yes" height="719px" name="Homepage-Main" width="107px"/>
<crop height="667px" name="iPhone 6" width="375px"/>
<crop height="512px" name="iPad 4" width="384px"/>
</presetCrops>" ]
*/
getCommunicationStatus
Retrieves the communication status of the application (useful when working in offline mode). The object returned contains the following fields:
-
applicationOnline: true if the application is in online mode, false otherwise.
-
isOnline: true if the application reaches the server and the application is in online mode, false otherwise.
-
offlineServer: enabled : true if the offline server is available, enabled: false otherwise.
-
serverReachable: true if the server is reachable, false otherwise.
{
applicationOnline: true,
isOnline: true,
offlineServer: {
enabled: false
},
serverReachable: true
}
Syntax
ctx.getCommunicationStatus()
Returns
Type |
Description |
{JSON Object} |
A json object containing the communication status of the application. |
Example
var communicationStatus = ctx.getCommunicationStatus();
getComponentInfo
Retrievest the conponent info and returns a JSON object containing the type and the subType of the current component. e.g.
{
type: "objectpanel",
subType: ""
}
Syntax
ctx.getComponentInfo()
Returns
Type |
Description |
{JSON Object} |
A json object containing the type and the subType of the current component. |
Example
var componentInfo = ctx.getComponentInfo();
readFile
Reads a file given its filename, and returns it in a particular format.
Syntax
ctx.readFile( options, callback )
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Yes |
A list of options. See below |
|
{Function} |
No |
A callback function. See Callback definition for further information. |
Important
|
The options object is a Javascript object with the following properties:
|
Returns
Type |
Description |
{JSON} or {XML} |
The content of the object in the format specified in the options parameter. |
Example
var file = ctx.readFile( { 'filename': '/SysConfig/Common/Data/Sections.xml',
'format': 'xml',
'resolveEntities': true
});
executeQuery
Executes a Methode query given the query content as String, and returns a query result as JSON.
Syntax
ctx.executeQuery( settings, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String or Object} |
Yes |
If a string is passed, it represents the query content to be executed. Else, represents a set of arguments. |
|
{Function} |
No |
A callback function. See Callback definition for further information. |
Important
|
settings can be either a string or a Javascript Object. If it is a string, it represents the query content to be executed. Elsewhere, if a Javascript object is passed, the following properties are supported:
|
Returns
Type |
Description |
{JSON Object} |
The query execution result. |
Example
var settings = {
"limit":70,
"query":"<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE EOMSearch><EOMSearch version=\"1.0\" xmlns=\"http://EidosMedia.com/EOM/SearchEngine\" xmlns:se=\"http://EidosMedia.com/EOM/SearchEngine\" xmlns:q=\"http://EidosMedia.com/EOM/SearchEngine/query\" xmlns:qm=\"http://EidosMedia.com/EOM/SearchEngine/query/macro\" xmlns:qa=\"http://EidosMedia.com/EOM/SearchEngine/query/alias\" xmlns:qui=\"http://EidosMedia.com/EOM/SearchEngine/query/UI\" xmlns:i=\"http://EidosMedia.com/query/interpolate\"><q:Query type=\"INDEX\"><q:Properties><q:MaxResultItems value=\"70\"/><q:Sort on=\"ObjectInfo/created\" type=\"NDESCENDING\"/><q:Index name=\"@meth01_eomjse1\"/></q:Properties><q:Boolean><q:OR><se:Content q:op=\"INC\" xmlns=\"\">obama</se:Content><se:Attributes q:op=\"INC\">obama</se:Attributes></q:OR></q:Boolean></q:Query></EOMSearch>"
}
var result = ctx.executeQuery(settings);
getUserData
Reads a user data content given its filename. If the file does not exist the system creates it in the following path "eomfs:/Configurations/Profiles/{currentUserName}/{filename}.json", and returns an empty JSON array.
Syntax
ctx.getUserData( filename, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The user data file’s name without extension. |
|
{Function} |
No |
A callback function. See Callback definition for further information. |
Returns
Type |
Description |
{JSON Array} |
The content of user’s data in JSON format or an empty JSON array if is a new file. |
Example
var friends = ctx.getUserData('friends');
addUserData
Adds a new JSON object to the specified user data content, denoted by the filename input parameter.
Syntax
ctx.addUserData( filename, data, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The user data file’s name without extension. |
|
{JSON Object} |
Yes |
The data object to be added to the user data file. |
|
{Function} |
No |
A callback function. See Callback definition for further information. |
Returns
Type |
Description |
{JSON Array} |
The updated list with the new added data object. |
Example
var friends = ctx.addUserData('friends', {
'fullName': 'Carroll Walke'
});
setUserData
Set a new JSON array to the specified user data content, denoted by the filename input parameter.
Syntax
ctx.setUserData( filename, list, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The user data file’s name without extension. |
|
{JSON Array} |
Yes |
The JSON array to replace the current user data content. |
|
{Function} |
No |
A callback function. See Callback definition for further information. |
Returns
Type |
Description |
{JSON Array} |
The updated list with the specified JSON array |
Example
var friends = ctx.setUserData('friends', [
{
"fullName": "Mitchell Henson"
},
{
"fullName": "Carroll Walker"
},
{
"fullName": "Carla Sargent"
},
{
"fullName": "Sara Savage"
},
{
"fullName": "Beach Workman"
},
{
"fullName": "Courtney Roberts"
},
{
"fullName": "Abby Hood"
},
{
"fullName": "Belinda Acosta"
}
]);
getContentByPath
Obtains a content of a document, given its path.
Syntax
ctx.getContentByPath( path, options, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The path of the object. E.g. 199$/SysConfig/columnCatalogCfg.swing.xml |
|
{Object} |
No |
An optional list of options. See below |
|
{Function} |
No |
A callback function. See Callback definition for further information. |
Important
|
The options object is a Javascript object with the following properties:
|
Returns
Type |
Description |
{string} |
The content of the object as a string. |
Example
ctx.getContentByPath('199$/SysConfig/columnCfgCatalogs.swing.xml', { cached: true }, function(err, content) {
if (err) {
ctx.showError(err);
return;
}
console.log(content);
});
Note
The method can also be called synchronously, but this usage is not recommended.
getCurrentUser
Obtains the current user.
Syntax
ctx.getCurrentUser( callback )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Yes |
A callback function. See Callback definition for further information. |
Returns
Type |
Description |
{User object} |
An instance of the User Class. See User class methods for further information on the methods available. |
Example
ctx.getCurrentUser(function(err,User) {
if (err) {
ctx.showError(err);
return;
}
// Do something with the user...
alert(User.getName());
});
Note
The method can also be called synchronously, but this usage is not recommended.
getObject
Obtains a Methode object, given its id
Syntax
ctx.getObject( id, callback );
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The document id. Format is [<databaseId>$]<loid>. |
|
{Function} |
Yes |
A callback function. See Callback definition for further information. |
Returns
Type |
Description |
{Object class} |
An instance of the Object Class. See Object class methods for further information on the methods available. |
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
// Do something with the object...
Obj.openReadonly();
});
Note
The method can also be called synchronously, but this usage is not recommended.
getObjectByPath
Obtains a Methode object, given its path
Syntax
ctx.getObjectByPath( path, callback );
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The document path. |
|
{Function} |
Yes |
A callback function. See Callback definition for further information. |
Returns
Type |
Description |
{Object class} |
An instance of the Object Class. See Object class methods for further information on the methods available. |
Example
ctx.getObjectByPath('/Globe/Stories/Test.xml', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
// Do something with the object...
Obj.openReadonly();
});
Note
The method can also be called synchronously, but this usage is not recommended.
getPlatformInfo
Obtains the Platform information
Syntax
ctx.getPlatformInfo();
Parameters
No parameters required.
Returns
Type |
Description |
{Object} |
A generic Javascript Object containing the platform information. |
Example
var platformInfo = ctx.getPlatformInfo();
if (platformInfo.application.indexOf('Swing') > -1) {
// Do something only if it's Swing/SwingApp
}
getUserByName
Obtains a user, given its name.
Syntax
ctx.getUserByName( name, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The user name to look for. |
|
{Function} |
Yes |
A callback function. See Callback definition for further information. |
Returns
Type |
Description |
{User object} |
An instance of the User Class. See User class methods for further information on the methods available. |
Example
ctx.getUserByName( 'user.test1', function(err,User) {
if (err) {
ctx.showError(err);
return;
}
// Do something with the user...
alert(User.getName());
});
Note
The method can also be called synchronously, but this usage is not recommended.
getGroupMembers
Obtains the list of member names, given a group name
Syntax
ctx.getGroupMembers( groupName, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The group name to look for. |
|
{Function} |
Yes |
A callback function. See Callback definition for further information. |
Returns
Type |
Description |
{JSON Array} |
The callback function will be called with the list of users belonging to the requested group, as an array of user names. |
Example
ctx.getGroupMembers( 'group.test1', function(err, members) {
if (err) {
ctx.showError(err);
return;
}
// Do something with the user names...
for (var i = 0; i < members.length; i++) {
console.log(members[i]);
}
});
openDocument
Open a Methode document, given its id
Syntax
ctx.openDocument( id, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The document id to open. Format is [<databaseId>$]<loid>. |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The methods does not return any information. The callback is called when the document is opened.
Example
ctx.openDocument( '199$1.0.893734064', function(err,User) {
if (err) {
ctx.showError(err);
return;
}
// Document has opened correctly
});
openNewContentDialog
Open the new content dialog, with the selected options
Syntax
ctx.openNewContentDialog( options, callback )
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Yes |
The options with which the dialog is loaded. |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Important
|
The options parameter is a javascript object in which it is possible to define:
|
Returns
The methods does not return any information. The callback is called when the document is created.
Example
ctx.openNewContentDialog( {
template: '/SysConfig/Globe/Templates/poll.xml',
contentType: 'story'
}, function(err,data) {
if (err) {
ctx.showError(err);
return;
}
// Document has been created correctly
alert( data.name );
});
openReadonly
Open a Methode document, given its id, in Readonly mode
Syntax
ctx.openReadonly( id, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The document id to open. Format is [<databaseId>$]<loid>. |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The methods does not return any information. The callback is called when the document is opened.
Example
ctx.openReadonly( '199$1.0.893734064', function(err,data) {
if (err) {
ctx.showError(err);
return;
}
// Document has opened correctly
});
openPopupPanel
Opens a custom HTML panel developed and specified by the user.
Syntax
ctx.openPopupPanel( panelName );
Method |
|
Parameter |
|
Returns |
|
Example
var panelName = 'myTestPanel';
ctx.openPopupPanel( panelName );
getSelection
Retrieves the last selected element in the editor context, for example DWP and Report editor.
Syntax
ctx.getSelection()
Returns
Type |
Description |
{JSON Object} |
A json object containing the last selected element in the contex editor in the form of Object Class instances. |
Example
var selection = ctx.getSelection();
Registration of the custom panel
The custom panel must be registered via Javascript. The namespace of reference is the following:
eidosmedia.webclient.extensions.popups
A call to the register
method must be done as follows:
eidosmedia.webclient.extensions.popups.register( name, settings );
-
{String} name
: the name of the custom popup ( same as the one called from thectx.openPopupPanel()
method. -
{Object} settings
: a javascript object with the settings. It has the following parameters:-
{String} icon
: the icon css class. -
{String} title
: the title of the custom dialog. -
{String} containerStyle
: the style of the container. See info box below. -
{String} template
: the path to the HTML file. It is relative to the application context. -
{Function} ready
: a function which is called when the popup is loaded. The function is called with two parameters:-
ctx
- the Context Object ( with the activeDocument if you are in the Story Editor context ) -
$modal
- the jQuery reference to identify the modal. The example below will show some possible uses.
-
-
eidosmedia.webclient.extensions.popups.register('testpopup', {
icon: 'icon-plus',
title: 'Custom panel title',
containerStyle: 'background-color:red;',
template: '/config/templates/customTemplates/testpopup.html',
ready: function( ctx, $modal ) {
// Popup is visible.
console.log( ctx );
// CUSTOM EXAMPLE
/*
In the footer example, we added a 'data-modal-action' to the OK button.
We now intercept the click inside the modal.
*/
// Add modal listeners.
$modal.on('click', '[data-modal-action]', function( event ) {
var action = $(this).attr('data-modal-action');
switch(action) {
case 'ok':
alert('Button clicked!');
// To close the modal, use $modal.modal('hide');
$modal.modal('hide');
break;
}
event.preventDefault();
event.stopPropagation();
});
}
});
Tip
|
The popup panel is built around a classical Bootstrap Modal. In particular, the HTML code in your template will be placed INSIDE the So, the modal will be basically created as follows:
No predefined style is given for the footer, but it is recommended to be as follows:
So, considering that your code is wrapped inside the modal-body, if you want to use a footer, close a Example:
IMPORTANT: as it is a bootstrap modal, by adding |
Shared Object
A set of api(s) to handle the document supporting the report case. These api(s) will be available among Swing, Prime and Swing Mobile.
Document
The shared document object contains a set of api(s) to operate with the document\report editor. These api(s) will refer to the single story editor or the full report stories editor depening on each case.
List of methods
Name |
Description |
Save the document \ report |
|
Close the document \ report |
|
Get the document \ report text content |
|
Get the document \ report xml content |
|
Select an element from the editor |
|
Add the specified tags in the document \ report |
|
Clear all occurrences of a set of tags in the document \ report, preserving content |
|
Insert an annotation into a document’s element |
|
Get the document \ report outline |
|
Get the text content of a document based on the xpaths provided \ for report the results will be divided by section |
|
Add specific tags based on the provided xpaths list |
save
Save the document in a single editor story case. Save all the report’s documents in the report case.
Accept a single object parameter and returns a promise.
Parameters
Name |
Type |
Required |
Description |
|
{Boolean} |
Optional |
If true close all the report’s documents after save. Ignored in single story editor case. |
Syntax
ctx.shared.document.save({ close })
Returns
A promise resolved when the operation is finished
Example
ctx.shared.document.save({close: true})
.then( result => {
console.log(result)
})
.catch( err => {
console.error(err);
});
close
Close the current report \ document.
Returns a promise.
Syntax
ctx.shared.document.close()
Returns
A promise resolved when the operation is finished. The promise is rejected if the closing operation is cancelled (for example if the user choose "cancel" on save dirty document alert)
Example
ctx.shared.document.close()
.then( result => {
// The window is closing, no operation execution granted here
console.log(result)
})
.catch( err => {
// Closing operation cancelled
console.error(err);
});
getTextContent
Returns the complete text content of the document or report. The text has newline at end of each paragraph. Accept an object parameter specifying the hash optional flag.
Parameters
Name |
Type |
Required |
Description |
|
{Boolean} |
false |
To return a hash of the document / report. To be specified in the addTags api to verify the document changed since getTextContent invocation. |
Syntax
ctx.shared.document.getTextContent()
Returns
A promise resolved when the operation is finished
Example
ctx.shared.document.getTextContent()
.then( result => {
console.log(result)
})
.catch( err => {
console.error(err);
});
getXmlContent
Returns the xml content of the document or report. In case of report an array of objects with id and xml attributes is returned.
Syntax
ctx.shared.document.getXmlContent()
Returns
A promise resolved when the operation is finished
Example
ctx.shared.document.getXmlContent()
.then( result => {
console.log(result)
})
.catch( err => {
console.error(err);
});
selectElement
Select an element from the story editor\report.
Accepts an object parameter to define the selection and returns a promise with information on the selection operation.
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Yes |
An object with the (optional) property tag for the tag name and an (optional) object property attributes to define the key\values attributes to look up in the selection. If more than one element match the selection criterias the first one will be selected. |
Syntax
ctx.shared.document.selectElement(element)
Returns
A promise resolved when the operation is finished and at least one element is selected. The promise is rejected if no elements are selected.
Example
const element = { tag: "byline", attributes: { id: "U77274655343ool" } };
ctx.shared.document.selectElement(element)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});
addTags
Add the specified tags in a document or report.
Accept an object parameter specifying the list of tags with related tag name, start, size, attributes (optional) and virtual flag (optional). If the optional virtual flag (true by default) is set to false, the tag will be saved in the document / report. An optional lock flag can be specified. An optional hash parameter can be specified (the one retrieved by the getTextContent api), it will be used to verify if the document / report changed, in case of changes the api will fail. The api returns a promise. If the promise succeeds, it returns a boolean indicating wether any tag has been added.
Parameters
Name |
Type |
Required |
Description |
|
{Array} |
Yes |
An array of object specifying the tag name, the start and size of text to be tagged and an optional attributes object. |
|
{Boolean} |
No |
To lock the document, true by default. |
|
{String} |
No |
To verify the document / report changes since the hash retrieval via getTextContent api. |
Syntax
ctx.shared.document.addTags({tags: [{tag: 'mark1', start:0, size:2}, {tag: 'mark2', start:4, size:6, attributes: {class: 'highlight'}}] })
Returns
A promise resolved when the operation is finished
Example
ctx.shared.document.addTags({tags: [{tag: 'mark', start:0, size:2}]})
.then( result => {
console.log(result)
})
.catch( err => {
console.err(err);
});
clearTags
Remove all the occurrences of the specified set of tags preserving their content, in a document or report.
Accept an object parameter specifying the list of tags and optionally a lock flag, returns a promise. If the promise succeeds, it returns a boolean indicating wether any occurrence of the tags has been matched and cleared.
Parameters
Name |
Type |
Required |
Description |
|
{Array} |
Yes |
An array of object specifying the tag name. |
|
{Boolean} |
No |
To lock the document, true by default. |
Syntax
ctx.shared.document.clearTags({tags: [{tag: 'mark'}, {tag:'highlight'}] })
Returns
A promise resolved when the operation is finished
Example
ctx.shared.document.clearTags({tags: [{tag: 'mark'}]})
.then( result => {
console.log(result)
})
.catch( err => {
console.err(err);
});
annotateElement
Add an annotation to an element from the story editor\report.
Accepts parameters to define where add the annotation and returns a promise with information on the annotation operation.
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Yes |
An object with the (optional) property tag for the tag name and an (optional) object property attributes to define the key\values attributes to look up for the annotation. If more than one element match the selection criterias the first one will be annotated. |
|
{String} |
Yes |
The annotation string |
|
{Object} |
Optional |
Additional parameters (see the table below) |
Name |
Type |
Required |
Description |
|
{Boolean} |
Optional |
If true the selected text element is unwrapped from its parent tag before adding the annotation |
Syntax
ctx.shared.document.annotateElement(element, text, options)
Returns
A promise resolved if one element was annotated. The promise is rejected if no elements for annotation are found.
Example
const element = { tag: "mark", attributes: { type: "player" } };
const options = { unwrap: true };
ctx.shared.document
.annotateElement(element, "This is my annotation", options)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});
getOutline
Returns information on the whole document or report. The information returned is ObjectInfo and optionally text and xml. In case of report an array of object is returned.
Parameters
Name |
Type |
Required |
Description |
|
{Boolean} |
No |
To get document xml, false by default. |
|
{Boolean} |
No |
To get document text, false by default. |
Syntax
ctx.shared.document.getOutline({xml: true, text: false})
Returns
A promise resolved when the operation is finished
Example
ctx.shared.document.getOutline()
.then( result => {
console.log(result)
})
.catch( err => {
console.error(err);
});
getTextContentByXpath
Get text content based on the xpath list provided.
Accept an options object containing an array of xpath to collect the text content. The text has newline at end of each paragraph. In the options object it’s possible to specify the hash optional flag. The api returns a promise. If the promise succeeds, it returns an array with the id of the section and an object containing the text content, the attributes of the objects are the list of xpaths provided.
Parameters
Name |
Type |
Required |
Description |
|
{Array} |
Yes |
An array of object specifying the xpath. |
|
{String} |
No |
To return a hash of text content for each single xpath. To be specified in the addTagsByXpath api to verify the document changed since getTextContentByXPath invocation. |
Syntax
ctx.shared.document.getTextContentByXpath({ xpaths: ['/doc/story/grouphead', '/doc/story/summary', '/doc/story/text'], hash: true})
Returns
A promise resolved when the operation is finished
Example
ctx.shared.document.getTextContentByXpath({ xpaths: ['/doc/story/grouphead', '/doc/story/summary', '/doc/story/text'], hash: true})
.then( result => {
console.log(result)
})
.catch( err => {
console.err(err);
});
addTagsByXpath
Apply tags based on the xpath list provided.
Accept an options object containing an array of documentList where to apply the tags. An optional lock flag can be specified. For each tag element: If the optional virtual flag (true by default) is set to false, the tag will be saved in the document / report. An optional hash parameter can be specified (the one retrieved by the getTextContentByTags api), it will be used to verify if the document / report changed, in case of changes the api will fail. The api returns a promise. If the promise succeeds, it returns an array with the id of the section and and teh result of the operation for each xpath.
Parameters
Name |
Type |
Required |
Description |
|
{Array} |
Yes |
An array of document where to apply the tags. |
|
{String} |
No |
If true each document will be locked, if not already locked, default true. |
Syntax
ctx.shared.document.addTagsByXpath({ documentList: ['/doc/story/grouphead', '/doc/story/summary', '/doc/story/text'], lock: false})
Returns
A promise resolved when the operation is finished
Example
ctx.shared.document.addTagsByXpath({ {
"lock": false,
"documentList": [
{
"storyId": "33$1.0.1468130003",
"xpaths": [
{
"xpath": "/doc/section/text",
"tags": [
{
"tag": "mask",
"start": 1,
"size": 4
},
{
"tag": "mask",
"start": 10,
"size": 3
}
],
"hash": true
}
]
},
{
"storyId": "33$1.0.1470737318",
"xpaths": [
{
"xpath": "/doc/section/text",
"tags": [
{
"tag": "mask",
"start": 5,
"size": 8
},
{
"tag": "mask",
"start": 20,
"size": 4
}
],
"hash": true
},
{
"xpath": "/doc/story/text",
"tags": [
{
"tag": "mask",
"start": 1,
"size": 10
}
],
"hash": true
}
]
}
]
})
.then( result => {
console.log(result)
})
.catch( err => {
console.err(err);
});
/* example of return value */ result =
[
{
storyId: '33$1.0.1468130003',
addTagsResult: {
"/doc/section/text": {
success: true
}
}
},
{
storyId: '33$1.0.1470737318',
addTagsResult: {
"/doc/section/text": {
"success": true
},
"/doc/story/text": {
success: false,
errorCode: 404,
errorMessage: 'node element not found'
}
}
]
Object class methods
List of methods
Name |
Description |
Add the collaborators to an object |
|
Execute an EOMDB action for the current object |
|
Returns the collaborators of an object |
|
Returns the correlations of an object |
|
Returns the object id |
|
Returns the object info |
|
In case of a report or a DWP returns the container of the selected object |
|
In case of a report or a DWP, returns the documents linked. |
|
In case of a report or a DWP, returns the zones and eventually the documents linked to each zone. |
|
Returns the object locker |
|
Returns the metadata of the object |
|
Returns the object name |
|
Returns the object status information |
|
Returns the system attributes of the object, in XML format |
|
Returns the object type |
|
Checks if the object is typeof the given type |
|
Returns the usage tickets of the object |
|
Returns the role information of the object |
|
Returns the virtual attributes of the object, in XML format |
|
Open the current object |
|
Open the current object in Readonly mode |
|
Lock the current object |
|
Unlock the current object |
|
Register to all the EOMDB events of an item |
|
Refresh the current object information |
|
Remove the collaborators of an object |
|
Set the metadata of an object |
|
Update the status of the current object |
|
Set the system attributes of an object |
|
Gets the bundle information of the current object |
|
Unset a metadata field of the current object |
|
Gets the channel copies list of the current object - Restricted for EOM::CompoundStory objects |
|
Create a channel copy of the current object - Restricted for EOM::CompoundStory objects |
addCollaborators
Add the collaborators to an object
Parameters
Name |
Type |
Required |
Description |
|
{String or Array} |
Yes |
A list made of user names. |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Syntax
Object.addCollaborators(collaborators, callback)
Returns
The method returns the an array of collaborators as string.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.addCollaborators(['user.3', 'user.4'], function(err, data){
if (err) {
ctx.showError(err);
return;
}
// data is now ['user.1', 'user.2', 'user.3', 'user.4'];
var User = ctx.getUserByName(data[0]).getInfo()
});
});
The method can also be called synchronously, but this usage is not recommended.
executeAction
Execute an EOMDB action for the current object
Syntax
Object.executeAction( settings, callback )
Parameters
Name |
Type |
Required |
Description |
|
{String or Object} |
Yes |
If a string is passed, it represents the name of the action to execute. Else, represents a set of arguments. |
|
{Function} |
Yes |
A callback function. See Callback definition for further information. |
Important
|
settings can be either a string or a Javascript Object. If it is a string, it will interpreted as the actionId, and the action will be executed with no other params. Elsewhere, if a Javascript object is passed, the following properties are supported:
|
Returns
The method returns the action response.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
// Or... Obj.executeAction({ actionId: 'postToTwitter', args: 'arguments here');
Obj.executeAction('postToTwitter', function(err, data) {
//.. Do something here.
});
});
The method can also be called synchronously, but this usage is not recommended.
getId
Returns the object id
Syntax
Object.getId()
Returns
The method returns the object id as a string.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
// Well, we already knew that...
var objectId = Obj.getId();
});
getCollaborators
Get the collaborators of an object
Syntax
Object.getCollaborators(callback)
Returns
The method returns the an array of collaborators as string.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.getCollaborators(function(err, data){
if (err) {
ctx.showError(err);
return;
}
// data is now ['user.1', 'user.2'];
var User! = ctx.getUserByName(data[0]).getInfo()
});
});
The method can also be called synchronously, but this usage is not recommended.
getCorrelations
Get the correlations of an object
Syntax
Object.getCorrelations(linkName, callback)
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Optional |
The name of the linkName to show. |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The method returns the an array of correlations as Ctx Objects.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
// Without linkName
Obj.getCorrelations(function(err, data){
/*
* With linkName,
* Obj.getCorrelations('see_also', function(err, data){
*/
if (err) {
ctx.showError(err);
return;
}
// data is an array of Objects
for (var j = 0; j < data.length; j++) {
console.log(data.getName());
}
});
});
The method can also be called synchronously, but this usage is not recommended.
getInfo
Returns the object info
Syntax
Object.getInfo()
Returns
The method returns the object information as JSON.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var objInfo = Obj.getInfo();
// Obj info is now a JSON containing all the information.
});
getContainer
In the context of DWP and Report editor returns the container of the selected object (activeObject).
Syntax
Object.getContainer()
Returns
The method returns the container in the form of Object Class instances.
Example
var container = ctx.activeObject.getContainer();
// container is an Object Class instance.
});
getLinks
In case of a report or a DWP, returns the documents linked.
Syntax
Object.getLinks(callback)
Returns
The method returns the an array of links in the form of Object Class instances.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.getLinks(function(err, links){
if (err) {
ctx.showError(err);
return;
}
// Each link is an Object Class instance.
// So, it is possible to do so.
for (var j = 0, ln = links.length; j < ln; j++) {
console.log( links[j].getLocker() );
}
});
});
getZones
In case of a report or a DWP, returns the zones and eventually the documents linked to each zone.
Syntax
Object.getZones(options, callback)
Name |
Type |
Required |
Description |
|
{Object} |
Yes |
An optional list of options. See below |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Important
|
The options object is a Javascript object with the following properties:
|
Returns
The method returns an array of zones in the form of Object Class instances.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.getZones({includeLinks: true}, function(err, zones){
if (err) {
ctx.showError(err);
return;
}
// Each link is an Object Class instance.
// So, it is possible to do so.
for (var j = 0, ln = zones.length; j < ln; j++) {
console.log( zones[j].getInfo() );
var links = zones[j].getLinks();
for (var z = 0, ll = zones.length; z < ll; z++) {
console.log( links[z].getInfo() );
}
}
});
});
getLocker
Returns the object locker
Syntax
Object.getLocker()
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var lockerBy = Obj.getLocker();
});
getMetadata
Returns the metadata of the object
Syntax
Object.getMetadata()
Returns
The method returns the metadata information as String
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var objMetadata = Obj.getMetadata();
var $objMetadata = $.parseXML(objMetadata);
});
getName
Returns the object name
Syntax
Object.getName()
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var name = Obj.getName();
});
getStatusInfo
Returns the object statusInformation
Syntax
Object.getStatusInfo()
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var statusInfo = Obj.getStatusInfo();
// Now
// statusInfo.name is the status name
// statusInfo.comment
// statusInfo.identifier is the RGB color
});
getSystemAttributes
Returns the system attributes of the object, in XML format (as string)
Syntax
Object.getSystemAttributes()
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var objSysAttr = Obj.getSystemAttributes();
var $sysAttr = $.parseXML(objSysAttr);
});
Use the refresh method to get up to date object information before call this method.
getType
Returns the object type
Syntax
Object.getType()
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var type = Obj.getType();
});
isType
Checks if the object is typeof the given type
Syntax
Object.isType(testtype)
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
The type to test against the object type. |
Returns
The method returns true if and only if the object type is type of the testtype else the method returns false.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var type = Obj.isType('EOM::Story');
});
getUsageTicket
Returns the usage tickets of the object, as an XML String
Syntax
Object.getUsageTicket()
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var usageTicket = Obj.getUsageTicket();
var $usageTicket = $.parseXML(usageTicket);
});
Use the refresh method to get up to date object information before call this method.
getRoles
Returns the roles information of the object, as an XML String
Syntax
Object.getRoles(settings, callback)
Parameters
Name |
Type |
Required |
Description |
|
{JSON} |
Yes |
The roles settings to retrieve:
|
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The method returns the roles information as XML String.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.getRoles({roleType: 'EOM::WebContainerLinks', roleName: '1.0.232702264'}, function(err, role){
if (err) {
ctx.showError(err);
return;
}
console.log(role);
});
});
getVirtualAttributes
Returns the virtual attributes of the object, as an XML String
Syntax
Object.getVirtualAttributes()
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var virtualAttributes = Obj.getVirtualAttributes();
var $virtualAttributes = $.parseXML(virtualAttributes);
});
Use the refresh method to get up to date object information before call this method.
open
Open the current object in editing mode
Syntax
Obj.open( id, callback )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The methods does not return any information. The callback is called when the document is opened.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.open(function(err, data) {
// Callback after the document is opened
});
});
lock
Lock the current document
Syntax
Obj.lock( callback )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The methods does not return any information. The callback is called when the document is locked.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.lock(function(err, data) {
// Callback after the document is locked
});
});
unlock
Unlock the current document
Syntax
Obj.unlock( callback )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The methods does not return any information. The callback is called when the document is unlocked.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.unlock(function(err, data) {
// Callback after the document is unlocked
});
});
openReadonly
Open the current document in Readonly mode
Syntax
Obj.openReadonly( callback )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The methods does not return any information. The callback is called when the document is opened.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.openReadonly(function(err, data) {
// Callback after the document is opened
});
});
registerToEvents
Register to all the EOMDB events of an item
Syntax
Obj.registerToEvents(eventCallback)
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Yes |
A callback function which is called at any event. See the example for further information. |
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
// Register to all the events.
Obj.registerToEvents(function(eventName, data) {
// eventName contains the name of the event
// "unlock", "lock", "check in"...
// data contains the information regarding the event.
// Eventually, if needed, call a refresh for the object.
Obj.refresh().getLocker();
});
});
refresh
Refresh the current object information and returns a new Object class.
Syntax
Obj.refresh()
Returns
Type |
Description |
{Object class} |
An instance of the Object Class. See Object class methods for further information on the methods available. |
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
// Perform very complex operations
// Such as saving the document or setting the document metadata
// To obtain the new metadata... do this.
Obj = Obj.refresh();
Obj.getMetadata();
});
removeCollaborators
Remove the collaborators from an object
Parameters
Name |
Type |
Required |
Description |
|
{String or Array} |
Yes |
A list made of user names. |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Syntax
Object.removeCollaborators(collaborators, callback)
Returns
The method returns the an array of collaborators as string.
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.removeCollaborators(['user.1'], function(err, data){
if (err) {
ctx.showError(err);
return;
}
// data is now ['user.1'];
var User = ctx.getUserByName(data[0]).getInfo()
});
});
The method can also be called synchronously, but this usage is not recommended.
setMetadata
Set the metadata of an object
Syntax
Obj.setMetadata(options, callback);
Parameters
Name |
Type |
Required |
Description |
|
{Object or Array} |
Yes |
An object made of xpath and content properties. Can be an array of those properties. |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var request = { xpath: '/ObjectMetadata/General/Priority', content: 'High title'};
// Or an array
// var request = [ { xpath: '/ObjectMetadata/General/Priority', content: 'High title'},
{ xpath: '/ObjectMetadata/General/Priority2', content: 'High title2'}
{ xpath: '/ObjectMetadata/General/Priority3', content: 'High title3'} ];
Obj.setMetadata(request, function(err, data) {
if (err) {
ctx.showError(err);
return;
}
// Success...
});
});
The method can also be called synchronously, but this usage is not recommended.
setStatus
Update the status of the current object
Syntax
Obj.setStatus('NewsFlow/Editing', callback); Obj.setStatus({ name: 'NewsFlow/Editing', comment: 'My comment'}, callback)
Returns
Type |
Description |
{Object class} |
An instance of the Object Class. See Object class methods for further information on the methods available. |
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.setStatus('NewsFlow/Editing', function(err, data) {
if (err) {
ctx.showError(err);
return;
}
// Success...
});
});
The method can also be called synchronously, but this usage is not recommended.
setSystemAttributes
Set the system attributes of an object
Syntax
Obj.setSystemAttributes(options, callback);
Parameters
Name |
Type |
Required |
Description |
|
{Object or Array} |
Yes |
An object made of xpath and content properties. Can be an array of those properties. |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
var request = { xpath: '/props/title/', content: 'High title'};
// Or an array
// var request = [ { xpath: '/props/title/', content: 'High title'},
{ xpath: '/props/summary/', content: 'Summary'} ];
Obj.setSystemAttributes(request, function(err, data) {
if (err) {
ctx.showError(err);
return;
}
// Success...
});
});
The method can also be called synchronously, but this usage is not recommended.
cleanMetadataField
Unset a metadata field of the current object
Syntax
Obj.cleanMetadataField(xpath, callback);
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
A metadata field xpath to remove. |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Example
ctx.getObject('199$1.0.893734064', function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
Obj.cleanMetadataField('/ObjectMetadata/General/Priority', function(err, data) {
if (err) {
ctx.showError(err);
return;
}
// Success...
});
});
The method can also be called synchronously, but this usage is not recommended.
getBundleInfo
Gets the bundle information of the current object
Syntax
Obj.getBundleInfo(callback);
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The bundle information:
[
{
"id": "99$1.0.287059148",
"name": "Obama.xml",
"baseName": "Obama",
"path": "/Globe/Stories/Globe/Stories/Politics/2019-03-18/Politics/Obama.xml",
"channel": "Globe-Web",
"edition": null,
"section": null,
"issueDate": "20190318",
"subFolder": null,
"workFolder": "/Globe/Politics",
"channelIdentifier": "Globe-Web"
},
{
"id": "99$1.0.287059376",
"name": "Obama@Globe-Print-USA.xml",
"baseName": "Obama@Globe-Print-USA",
"path": "/Globe/Stories/Globe/Stories/Politics/2019-03-18/Politics/Obama.xml/Obama@Globe-Print-USA.xml",
"channel": "Globe-Print",
"edition": "USA",
"section": null,
"issueDate": "20190318",
"subFolder": null,
"workFolder": "/Globe/Politics",
"channelIdentifier": "Globe-Print/USA"
}
]
Example
ctx.activeObject.getBundleInfo(function(err, list) {
if (err) {
ctx.showError(err);
return;
}
//Success
});
The method can also be called synchronously, but this usage is not recommended.
getChannelCopiesList
Gets the channel copies list of the current object - Restricted for EOM::CompoundStory objects
Syntax
Obj.getChannelCopiesList(callback);
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The list of the created channel copies:
[
{
"id": "41$1.0.107332121",
"channel": null,
"info": {
"id": "41$1.0.107332121",
"name": "story.xml",
"baseName": "story",
"path": "/Globe/Stories/Art/story.xml",
"channel": null,
"edition": null,
"section": null,
"issueDate": "20190111",
"subFolder": null,
"workFolder": "/Globe/Art",
"channelIdentifier": "none"
},
"master": true
},
{
"id": "41$1.0.107314527",
"channel": "Globe-Print",
"info": {
"id": "41$1.0.107314527",
"name": "story@Globe-Print.xml",
"baseName": "story@Globe-Print",
"path": "/Globe/Stories/Art/story.xml/story@Globe-Print.xml",
"channel": "Globe-Print",
"edition": null,
"section": null,
"issueDate": "20190111",
"subFolder": null,
"workFolder": "/Globe/Art",
"channelIdentifier": "Globe-Print"
}
}
]
Example
ctx.activeObject.getChannelCopiesList(function(err, list) {
if (err) {
ctx.showError(err);
return;
}
//Success
});
The method can also be called synchronously, but this usage is not recommended.
createChannelCopy
Create a channel copy of the current object - Restricted for EOM::CompoundStory objects
Syntax
Obj.createChannelCopy(channel, callback);
Parameters
Name |
Type |
Required |
Description |
|
{String} |
Yes |
A string containing the channel in form of "Product/Edition". |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The method returns the object information of the new channel copy as JSON.
Example
ctx.activeObject.createChannelCopy('Product/Edition', function(err) {
if (err) {
ctx.showError(err);
return;
}
//Success
});
The method can also be called synchronously, but this usage is not recommended.
User class methods
List of methods
Name |
Description |
Returns the user groups |
|
Returns the user info |
|
Returns the usermetadata |
|
Returns the username |
|
Returns the system attributes of the user, in XML format |
|
Returns the user teams. |
|
Sets the system attributes of the user |
|
Sets the metadata of the user |
getGroups
Returns the groups which the user belongs to
Warning
|
The method returns an error for users other than the current one. |
Syntax
User.getGroups( [callback] )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Example
ctx.getCurrentUser(function(err,User) {
var groups = User.getGroups();
console.log(teams);
});
The method can be called either synchronously or asynchronously. It is indifferent.
getInfo
Returns the user info
Syntax
User.getInfo( [callback] )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The user information in JSON.
{
"name": "john.doe",
"description": "Star Software",
"ucount": 13159,
"databaseId": 199,
"id": "1.0.532488046",
"fullName": "John Doe",
"phoneNumber": "(01) 5748584456)",
"mobileNumber": "(001) 5476987496798)",
"twitter": "johndoe",
"role": "Reporter",
"homeEmail": "john.doe@google.com",
"businessEmail": "john.doe@star.com",
"statusMessage": "I am available",
"workDir": "workFolder:///Globe/Art",
"location": "London",
"lastLoggedOn": 1494418598,
"initials": "JD",
"signature": "john doe",
"homePath": "/Users/john.doe",
"calendars": [
{
"color": "#32AE0C",
"id": "U12001806763ERC",
"name": "UK Holidays",
"url": "https://www.gov.uk/england-and-wales.ics",
"icon": "icon-calendar",
"private": false
}
],
"status": "busy",
"disabled": false
}
Example
ctx.getCurrentUser(function(err,User) {
var userInfo = User.getInfo();
// Or, if you prefer,
User.getInfo(function(err, userInfo){
console.log(userInfo.name);
});
});
The method can be called either synchronously or asynchronously. It is indifferent.
getMetadata
Returns the user metadata, as a string.
Warning
|
The method returns an error for users other than the current one. |
Syntax
User.getMetadata( [callback] )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Example
ctx.getCurrentUser(function(err,User) {
var metadata = User.getMetadata();
console.log(metadata);
});
The method can be called either synchronously or asynchronously. It is indifferent.
getName
Returns the user name
Syntax
User.getName( [callback] )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The user name as string.
Example
ctx.getCurrentUser(function(err,User) {
var userName = User.getName();
console.log(userName);
});
The method can be called either synchronously or asynchronously. It is indifferent.
getSystemAttributes
Returns the system attributes of the user, in XML format (as string)
Warning
|
The method returns an error for users other than the current one. |
Syntax
User.getSystemAttributesXML( [callback] )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The system attributes of the User, as a XML string.
Example
ctx.getCurrentUser(function(err,User) {
var systemAttributesXml = User.getSystemAttributes();
var $sysAttr = $.parseXML(systemAttributesXml);
console.log(systemAttributesXml);
});
The method can be called either synchronously or asynchronously. It is indifferent.
getTeams
Returns the teams which the user belongs to
Warning
|
The method returns an error for users other than the current one. |
Syntax
User.getTeams( [callback] )
Parameters
Name |
Type |
Required |
Description |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Example
ctx.getCurrentUser(function(err,User) {
var teams = User.getTeams();
console.log(teams);
});
The method can be called either synchronously or asynchronously. It is indifferent.
setSystemAttributes
Sets the system attributes of the user
Warning
|
The method returns an error for users other than the current one. |
Syntax
User.setSystemAttributes( systemAttributes, [callback] )
Parameters
Name |
Type |
Required |
Description |
|
{String or object} |
Yes |
A string or an object to represent the system attributes |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The system attributes of the User, as a XML string.
Example
ctx.getCurrentUser(function(err,User) {
var systemAttributes = '<props><principalInfo><email type="business">johndoe@star.comw</email><initials>JD</initials><signature>john doe</signature><statusMessage>I am available</statusMessage><color type="revision" value="#008080"/><color type="annotation" value="#800000"/><location>London</location><email type="home">johndoe@google.com</email><twitter>johndoe</twitter><facebook>aaaa</facebook><mobileNumber>(01) 7834684587438</mobileNumber><phoneNumber>(001) 54753754765375</phoneNumber><status>busy</status><workDir>workFolder:///Globe/Art</workDir><calendar><id>U12001806763ERC</id><icon>icon-calendar</icon><color>#32AE0C</color><name>UK Holidays</name><url>https://www.gov.uk/bank-holidays/england-and-wales.ics</url><private>false</private></calendar></principalInfo><role>Reporter</role><OutputChannels><channel name="Globe-Print"/></OutputChannels></props>';
User.setSystemAttributes(systemAttributes, function(err, data) {
if (err) {
// Do something...
return;
}
);
});
setMetadata
Sets the metadata of the user
Warning
|
The method returns an error for users other than the current one. |
Syntax
User.setMetadata( metadata, [callback] )
Parameters
Name |
Type |
Required |
Description |
|
{String or object} |
Yes |
A string or an object to represent the metadata |
|
{Function} |
Optional |
A callback function. See Callback definition for further information. |
Returns
The system attributes of the User, as a XML string.
Example
ctx.getCurrentUser(function(err,User) {
var attributes = '<test><secondtest>hello</secondtest></test>';
User.setMetadata(attributes, function(err, data) {
if (err) {
// Do something...
return;
}
);
});
activeObject
In various contexts, such as the toolbars, editors, Diagram workflow, etc., there is an additional property available, named activeObject.
The activeObject is actually an instance of the Object Class and contains all methods of this class. See Object class methods for further information.
To be compliant with object panel bulk mode please use activeObjects array property.
Important
|
The old activeObj property is being discontinued from Swing 4 and will not be available in Prime. Please use the new activeObject property instead. |
activeObjects
Same as activeObject but returned as an array of all selected items. In single mode array length is 1.
activeDocument
*Deprecated: please use activeDocumentV2
Inside the editor context, it is possible to access the activeDocument. Please refer to Editor API methods reference.
activeDocumentV2
Starting form version 5.2020.11 inside the editor context, it is possible to access the activeDocumentV2. Api(s) from this object are cross platform compatible (Swing, Swing Mobile, Prime).
Please refer to Editor API methods reference.
Callback definition
Important
|
The callback parameter, when specified, is always defined as follows:
|
Basic structure of the Context Object
The Context object is made of a specific list of properties, and a number of publicly available methods.
{
application: {
getId: function()
},
area: {
getType: function(),
getName: function()
},
component: {
getType: function()
},
activeObject: {
// Methods of the single object.
},
activeObjects: [{activeObject}] // An array of activeObject
selection: [ ] // Array of objects. See below.
}
Parameter | Value type | Description | Values |
---|---|---|---|
application.getId() |
String |
Returns the application Id. |
"swing", … |
area.getType() |
String |
Returns the area type. |
"main" (for the main views), "editor" |
area.getName() |
String |
Returns the area name. |
"explorer", "dashboard", "myarea", "liveblogmanagement" (for "main" areas). "story", "gallery" (for editors). |
component.getType() |
String |
Returns the component type. |
"toolbar", "grid", "objectpanel"… |
activeObject |
Object |
Returns an object with a set of methods. |
|
activeObjects |
Array |
Returns an array of activeObject(s). In bulk selection mode all selected items are returned here as array. In single selection mode array length is 1. |
|
selection |
Array of Object |
Returns an array with the currently selected items. Each item has the same set of methods available. |
Tip
|
Each context has a different value for these properties. |
Custom menu and actions
In Methode Swing it is possible to configure custom menus and custom object actions.
Prepare the plugin to add menus and action
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Add a custom menu
In order to add a custom menu to Methode Swing, it is necessary to use the following namespace:
eidosmedia.webclient.extensions.header.newcontentmenu
New menus will be added in the next versions.
The syntax is the following:
eidosmedia.webclient.extensions.header.newcontentmenu.add(name, options);
Where:
-
name [string] is the name of the custom menu, alias a unique identifier.
-
options [optional, object] is a Javascript object containing the properties of the custom actions.
The options parameter can be omitted. In this case, Swing will use the previously registered command with the same name property. See example below.
If options is specified, it must follow the guidelines of a generic Swing command. See Commands documentation for further information.
Example
eidosmedia.webclient.commands.add({
name: 'complex',
icon: 'icon-compass',
label: 'Perform some complex operation...',
action: function( ctx, params, callback ) {
if ( ctx.component.getType() === 'menu') {
alert('hello menu');
// perform same difficult operations...
if (callbacks && callbacks.success) {
callbacks.success( /*...*/ );
}
}
}
});
eidosmedia.webclient.extensions.header.newcontentmenu.add('complex');
Add a custom action to an object
In a conceptually similar way, it is possible to add custom actions to objects. They will be shown in the search results, in the detailed preview of the object, and generally speaking everytime the object is available.
The syntax is the following:
eidosmedia.webclient.extensions.objectactions.add(name, options);
Where:
-
name [string] is the name of the custom menu, alias a unique identifier.
Please note that the name parameter will be also used for the action label localization. The key toolbar.name will be to be used in order to retrieve a translated string from Swing translation files.
-
options [optional, object] is a Javascript object containing the properties of the custom actions.
The options parameter can be omitted. In this case, Swing will use the previously registered command with the same name property. See example below.
If options is specified, it must follow the guidelines of a generic Swing command. See Commands documentation for further information.
Example
eidosmedia.webclient.commands.add({
name: 'complex',
icon: 'icon-compass',
label: 'Perform some complex operation...',
isActive: function( ctx ) {
// For some buttons ctx.activeObject is not available.
return ctx.activeObject && ctx.activeObject.getType() === 'Image';
},
action: function( ctx, params, callback ) {
if ( ctx.component.getType() === 'menu') {
alert('hello menu');
// perform same difficult operations...
if (callbacks && callbacks.success) {
callbacks.success( /*...*/ );
}
}
}
});
eidosmedia.webclient.extensions.objectActions.add('complex');
Validators
Méthode Swing can be extended by providing the so called validators, that is a set of function to validate the input before it is sent to the Server to be saved.
Location of the Validators extensions
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Supported validators
With the evolution of Méthode Swing, more validators will be added. At the moment, the application supports the following validators.
renameFile validator
As the name suggests, the renameFile validator is called whenever the user tries to rename a file. This happens in an opened editor, or in the Explorer area, or during a Worflow/Release action.
To add a renameFile validator, it is necessary to register it inside Swing by calling the following Javascript function, inside your Javascript file:
eidosmedia.webclient.extensions.validators.addValidator('renameFile', function( ctx, onSuccess, onError ) { /* ... */ } );
The function requires three parameters:
-
ctx: The ctx is a JSON object which represents the object’s context. See Basic structure of the Context Object for further details. See the code for further details on the available properties.
-
onSuccess: function to be called when the validation has passed. It wants a single parameter, newName, which is optional. See the code for further details on the parameters.
-
onError: function to be called when the validation failed. It wants a single parameter, errorMessage. See the code for further details.
Example and explanation of parameters
eidosmedia.webclient.extensions.validators.addValidator('renameFile', function( ctx, onSuccess, onError ) {
// The ctx object contains the following properties.
// context: 'application'
// activeObject->getInfo() : {
// id: the story id,
// newName: the name specified by the user
// originalName: the originalName of the file
// }
// We obtain the information
var info = ctx.activeObject.getInfo(); // { id, newName, originalName }
// SAMPLE IMPLEMENTATION.
if ( info.newName === "FORBIDDEN.xml" ) {
// onError = function (errorMessage). Call it with the error message to be shown.
onError( "This name is absolutely forbidden!" );
return;
} else {
// The parameter is optional. If not passed, the document will be saved with the name specified
// by the user. Passing the parameter, it is possible to change the name in the validator.
onSuccess(); // Same as: onSuccess( info.newName );
// OR
onSuccess( "VALIDATED_" + info.newName );
}
});
Editor URL Redirect validator
As the name suggests, the Editor URL Redirect validator is called whenever the user tries to add or edit a url in the Editor Url Redirect.
To add a Editor URL Redirect validator, it is necessary to register it inside Swing by calling the following Javascript function, inside your Javascript file:
eidosmedia.webclient.extensions.validators.addValidator('url-redirect', function( ctx, urlInfo, callback ) { /* ... */ } );
The function requires three parameters:
-
ctx: The ctx is a JSON object which represents the object’s context. See Basic structure of the Context Object for further details. See the code for further details on the available properties.
-
urlInfo: a Javascript object containing all the information regarding the selected url. See the code for further details on the available properties.
-
callback: function to be called when the validation has been completed. See the code to know how to call it.
Example and explanation of parameters
eidosmedia.webclient.extensions.validators.addValidator('url-redirect', function( ctx, urlInfo, callback ) {
// The ctx object contains the following properties.
// context: 'editor'
// area->getName: 'editor-url-redirect',
// activeObject->getInfo() : the document information.
// The urlInfo contains the following properties
// urlInfo: {
// type: 'redirect' // or 'permanentredirect', or 'temporaryredirect' or 'forward'
// url: the starting url
// redirect: the target url
// isEditing: true / false ( if the url is a new one or not )
//}
// Perform the validation here...
callback( true ); // Will tell the editor that the validation has passed.
// callback() or callback( false ) or callback( any falsy value ) will tell the editor that the validation has failed.
}
Editor Extensions
Commands configuration
Méthode Swing allows to add custom commands. Such commands can be launched in different situations, such as external DAM searches, custom Object Panels and widgets. Furthermore, M´thode Swing allows to configure such commands in specific parts of the User Interface (UI) such as, for example, the Toolbar inside the Explorer tab or the Explorer Grid (via Column Catalog).
Prepare the plugin to add commands
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Format of a command
A command is represented by a JSON object which should contain at least the following properties:
// Command options
{
name: "" ,// commandName
methodeContext: [],
isActive: function( ctx ) { /* ... */ },
isEnabled: function( ctx ) { /* ... */ },
action: function( ctx, params, callback ) { /* ... */ },
icon: 'icon-compass',
label: 'My label'
}
name
The unique command name. Please note that the name parameter will be also used for the action label localization. The key toolbar.name will be to be used in order to retrieve a translated string from Swing translation files.
Warning
|
The command name is mandatory. |
methodeContext
The list of applications (JSON Array) where this command should be available, allowed values: swing, desktop (Prime Dashboard), mobile and all.
isActive
The isActive method is used to determine whether a command must be added to the context of reference. That is, for example, whether a custom button should be added to a toolbar.
The isActive method has the Context Object as the only parameters. See Basic structure of the Context Object for further details on the Context Object.
Tip
|
This is the best place to check for particular privileges. |
Warning
|
Each default Swing context calls the isActive method with different parameters. See Swing default contexts to see the different parameters used by the different Swing contexts. |
isEnabled
The isEnabled method is used to determine whether a command must be enabled and disabled according to the current situation. That is, for enable, whether a custom button in a toolbar should be enabled according to the current selection.
The isEnabled method has the Context Object as the only parameters. See Basic structure of the Context Object for further details on the Context Object.
Tip
|
This is the best place to check for the current selection ( selected items, text selection, etc. according to the context) |
Warning
|
Each default Swing context calls the isEnabled method with different parameters. See Swing default contexts to see the different parameters used by the different Swing contexts. |
action( ctx, params, callback )
The action property is a Javascript function which is called when a command is executed.
The parameters are the following:
-
ctx: the Context. See Basic structure of the Context Object for further details on the Context Object.
-
params: a list of params to be passed to the action.
-
callbacks: if available, it is an object containing the success and the error functions.
Warning
|
Every context inside Méthode Swing calls the commands with different values for the params and the callback arguments. See Swing default contexts to see the different parameters used by the different Swing contexts. |
icon
Describes the icon associated with the command.
Tip
|
The icon property is optional. |
label
Describes the label associated with the command.
Tip
|
The label property is optional. |
Register, obtain and execute commands
Commands are, basically, functions that can be called in particular cases. The commands can be associated with specific Swing contexts (such as the Toolbars, or the Grid rows), or can be executed freely from inside the user plugins.
While the basic command format is equal for any case, the command registration is different according to the context of reference. The following paragraphs describe this concept in details.
"Free" command registration and execution
In this case, the user registers a command without associating it with a particular context. For this, all the methods to add, get and execute commands are within the following namespace:
eidosmedia.webclient.commands
Available methods are add, get, exec, defined as follows:
// Add a new command
eidosmedia.webclient.commands.add( command );
// Get the command object
eidosmedia.webclient.commands.get( commandName );
// Execute a command
eidosmedia.webclient.commands.exec( commandName, ... );
add( command )
Adds a command to Méthode Swing. It needs one parameter:
-
command: the command object. See Format of a command for info on the format in use.
Warning
|
It is recommended not to use standard names such as edit, save, etc. because there is the risk to override standard Swing commands. |
Example
eidosmedia.webclient.commands.add({
name: 'myCustomCommand',
icon: 'icon-compass',
label: 'Perform some complex operation...',
isActive: function( ctx ) {
// check privileges...
return true;
},
isEnabled: function( ctx ) {
// check current selected items...
return true;
},
action: function( ctx, params, callbacks ) {
if ( ctx.component.getType() === 'toolbar') {
// perform same difficult operations...
if (callbacks && callbacks.success) {
callbacks.success( /*...*/ );
}
}
}
});
get( commandName )
Return a Javascript Object containing all the properties of the command, as defined in the previous set method.
Example
var cmd = eidosmedia.webclient.commands.get( 'myCustomCommand' );
/*
Now cmd is: {
icon: 'icon-compass',
label: 'Perform some complex operation...',
isActive: function( ctx ) {
// check privileges...
return true;
},
isEnabled: function( ctx ) {
// check current selected items...
return true;
},
action: function( ctx, params, callback ) {
if ( ctx.component.getType() === 'toolbar') {
// perform same difficult operations...
if (callbacks && callbacks.success) {
callbacks.success( /*...*/ );
}
}
}
*/
exec( commandName, … )
It is the method to execute a particular command.
var result = eidosemdia.webclient.commands.exec('myCustomCommand', ctx, params, callbacks );
The only mandatory param is commandName, which is the name of the command to execute. All the other parameters are passed as-is to the command.
Warning
|
As said above, Méthode Swing calls the custom commands with three parameters: ctx, params and callback. The nature of these parameters changes according to which context is using the command. See Swing default contexts to see the different parameters used by the different Swing contexts. |
Tip
|
Of course, if the custom commands are used only within your extensions ( and not by default Swing contexts ), it is possible to use any parameter of choice. |
Sample
/** in a custom widget, for example */
var btn = document.getElementById('myButton');
$(btn).on('click', function() {
eidosmedia.webclient.commands.exec('myCustomCommand', 'all', 'my', 'parameters', 'here', true, [ { everything: 'ok' } ]);
});
Registration of a command to a context
See Swing default contexts for further info on how to register and work with different Swing contexts.
Swing default contexts
Explorer Toolbar
Context Object properties for the Explorer Toolbar
The Object Panel context has the following values:
Parameter | Values | Description |
---|---|---|
area.getType() |
"main" |
|
area.getName() |
"explorer" |
|
component.getType() |
"toolbar" |
|
activeObject.getId() |
String |
Return the ID of the current folder / query opened in the Explorer. |
activeObject.getInfo() |
JSON |
Return the info of the current folder / query opened in the Explorer. |
activeObject.getType() |
JSON |
Return the type of the current folder / query opened in the Explorer. |
activeObject.invalidate() (additional) |
(void) |
Invalidates all the changes and refresh the content of the current folder / query. |
selection |
JSON Array |
Returns an array with the currently selected items in the folder/query. Each item has the same set of methods available. |
Associate commands to the toolbar
It is possible to register the command with the commands.add method ( see add( command ) for futher details ).
Then the commands must be associated to the toolbar as follows:
eidosmedia.webclient.actions.explorer.toolbar.addButton({
action: "COMMAND NAME",
label: "Label",
icon: "Icon"
});
or, it is possible to pass directly the command object to the same function, e.g. :
eidosmedia.webclient.actions.explorer.toolbar.addButton({
name: "cox.resetPriority",
isActive: function( ctx ) { /* ... */ },
isEnabled: function( ctx ) { /* ... */ },
action: function( ctx, params, callbacks ) { /* ... */ },
icon: 'icon-compass',
label: 'My label'
});
Tip
|
The toolbar actions are called without a params and a callbacks parameter. |
Grid Items
These values are valid for any grid. At the moment, only the Explorer grid is managed.
Context Object properties for the Grid Item
The Object Panel context has the following values:
Parameter | Values | Description |
---|---|---|
component.getType() |
"grid-item" |
|
component.getId() |
String |
Not available |
activeObject.getId() |
String |
Return the ID of the current item (grid row). |
activeObject.getInfo() |
JSON |
Return the info of the current item (grid row). |
activeObject.getType() |
JSON |
Return the type of the current item (grid row). |
selection |
JSON Array |
Not available (empty array) |
It is possible to register the command with the commands.add method ( see add( command ) for futher details ).
Then the commands must be associated to the grid item as follows:
eidosmedia.webclient.actions.explorer.grid.addEditor({
action: "COMMAND NAME",
label: "Label",
icon: "Icon"
});
or, it is possible to pass directly the command object to the same function, e.g. :
eidosmedia.webclient.actions.explorer.grid.addEditor({
name: "cox.resetPriority",
isActive: function( ctx ) { /* ... */ },
isEnabled: function( ctx ) { /* ... */ },
action: function( ctx, params, callbacks ) { /* ... */ },
icon: 'icon-compass',
label: 'My label'
});
Object panel
Context Object properties for the ObjectPanel
The Object Panel context has the following values:
Parameter | Values | Description |
---|---|---|
component.getType() |
"objectpanel" |
|
component.getId() |
String |
The id of the ObjectPanel DOM Element ( e.g. '#em-metadata-area' ) |
activeObject.getId() |
String |
Return the ID of the current object |
activeObject.getInfo() |
JSON |
Return the info of the current object |
activeObject.getType() |
JSON |
Return the type of the current object |
selection |
JSON Array |
Not available (empty array) |
Additional methods in the Context Object for Object Panel.
Method | Available in |
---|---|
activeObject.getUniqueMetadataId() |
preFillForm - postFillForm - preSave - postSave - onClose |
activeObject.setReadonly() |
preFillForm - postFillForm - preSave - postSave - onClose |
activeObject.showLoading() |
preFillForm - postFillForm - preSave - postSave - onClose |
activeObject.hideLoading() |
preFillForm - postFillForm - preSave - postSave - onClose |
activeObject.getMetadataXML() |
preFillForm - postFillForm - preSave - validate - postSave - onClose |
activeObject.setMetadataXML() |
preFillForm - onClose |
activeObject.getImage() |
onImageProcessing |
activeObject.setFieldValue() |
postFillForm - preSave |
activeObject.getFieldValue() |
postFillForm - preSave |
activeObject.refreshMetadata() |
postFillForm - postSave - onClose |
activeObject.saveMetadata() |
preFillForm - postFillForm - onClose |
activeObject.refreshPanel() |
onUpdatesAvailable - onEvent |
getUniqueMetadataId()
Return the same unique id used in the HTML panel whenever a -<%=uniqueMetadataId%> has been used to generate a unique Id.
The syntax is the following:
var uniqueId = ctx.activeObject.getUniqueMetadataId(); // e.g "5";
var uniqueId = ctx.activeObject.getUniqueMetadataId(); // e.g "5";
// In this way we ensure that the only the current custom panel is referenced
$('#myCustomPanel-' + uniqueId) // ...
setReadonly()
Creates a readonly layer over the object Panel. The syntax is the following:
ctx.activeObject.setReadonly( [value] );
Value can be true (default) or false.
showLoading(), hideLoading()
Shows or hides a loading element. The syntax is the following:
ctx.activeObject.showLoading( options);
{object} options
- An object containing an optional message to display during the loading process, a color and backgroundColor of the text message.
ctx.activeObject.hideLoading( );
getMetadataXML()
Return the current metadata XML as a document object.
setMetadataXML( metadataXML )
Sets the the new metadata XML ( only in the preFillForm and onClose method ).
getImage()
Returs a Promise resolved with the current active object image raw data
setFieldValue( data-id, value)
Sets programmatically a value to the field having the data-id provided. Value MUST be in the format expected by DTD.
Use always this method to set programmatically a value to be compatible with bulk mode.
getFieldValue( data-id )
Get the current value from the field having data-id. The returned field value is in the format expected by DTD.
Use always this method to get programmatically a value to be compatible with bulk mode.
refreshMetadata()
Refresh the current Metadata.
Warning
|
This will cause a reload of the objectPanel, and consequently a call to "preFillForm" and "postFillFrom" methods. |
refreshPanel()
Refresh the current Object panel.
saveMetadata()
Saves the current Metadata. Before saving, the "preSave" method is called. After saving, the "postSave" method is called. In bulk mode this method saves metadata for all selected objects even if called from a particular activeObject.
Editor extensions
Méthode Swing Text editor can be extended in multiple parts by adding custom buttons and executing custom actions.
Location of the Editor extensions.
Editor extensions consist in a Javascript (*.js) file loaded with Swing.
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Namespaces of the editor extensions
Editor extensions are available under the following namespace:
eidosmedia.webclient.actions.editor
This namespace delves into more sub-namespaces, according to the part of the editor the user want to extend. At the moment, the following namespaces are supported:
eidosmedia.webclient.actions.editor.toolbar // To add buttons and actions in the editor toolbar
eidosmedia.webclient.actions.editor.components // To add buttons and actions in the swing components
The approach to use is the same throughout all the namespaces.
Configure editor actions
Throughout this document, the example will focus on the development of a simple custom command, named custom.PrependText, which will prepend a specific text to the current selection.
To add an editor action, then, it is necessary to follow the steps described below:
1. Add a custom command
The editor extensions follow the same approach of Swing commands.
See the Command configuration paragraph for further details.
Example
eidosmedia.webclient.commands.add({
name: 'custom.PrependText',
isActive: function( ctx ) {
// check privileges...
return true;
},
isEnabled: function( ctx ) {
// check current selected items...
return true;
},
action: function( ctx, params, callbacks ) {
if ( ctx.component.getType() === 'toolbar') {
// perform same difficult operations...
if (callbacks && callbacks.success) {
callbacks.success( /*...*/ );
}
}
}
});
Tip
|
The details of the implementation of the isEnabled and isActive method will be explained later. |
2. Register the commands in the different areas
As a second step, the newly created command must be associated to the specific areas of the editor.
2.a Editor toolbar and custom tabs
To add a button to the Editor toolbar, the following namespace must be used
eidosmedia.webclient.actions.editor.toolbar
The method to be used is addButton(settings). See the following example:
/**
* We now register a new action in the editor toolbar using
* the proper namespace. In this case we call the addButton
* method for the toolbar visible in the editor instance. We
* define a label and an icon for the button and more important
* we tell the button which command has to trigger using the
* action property
*/
eidosmedia.webclient.actions.editor.toolbar.addButton({
action: "custom.PrependText",
label: "Prepend Xml",
icon: 'icon-edit',
tabId: 'custom-tab-id'
});
The addButton method requires a single Javascript object ( settings ) as a parameter. This objects need to have the following properties:
-
action: the name of the previously registered command
-
label: the label associated with the command
-
icon: the icon associated with the command.
Important
|
Buttons can be placed under custom tabs. See Editor custom tabs for more information. |
Important
|
By defining an order property, it is possible to change the order of the buttons in the toolbar (only for the Editor). |
Warning
|
If you need to use the call the same command from different parts of the editor ( e.g. the toolbar and some components ), or you need to differentiate the components for which the command is available, you can ( and should ) verify the origin of the action by checking the Context Object Component Type. This is detailed in the Verify the component type paragraph. |
Editor custom tabs
Swing story editor toolbar is divided in tabs. By default, all the custom buttons are added to a specific "Custom Actions" tab. It is possible, though, to define multiple (2 at maximum) custom tabs and to place the custom buttons accordingly. To add a custom tab, write the following:
/**
* We now register a new tab in the editor toolbar using
* the proper namespace. The tab name must be used in the <tabId> property of the custom button.
*/
eidosmedia.webclient.extensions.editor.tabs.add({
name: 'em-tab-custom',
label: 'Swing custom actions'
});
To add the button to a tab, use the following syntax:
eidosmedia.webclient.actions.editor.toolbar.addButton({
action: "custom.PrependText",
label: "Prepend Xml",
icon: 'icon-edit',
tabId: 'em-tab-custom'
});
Important
|
|
2.b Editor components
To add a button to the Editor components, the following namespace must be used
eidosmedia.webclient.actions.editor.components
The method to be used is addButton(settings). See the following example:
/**
* We now register a new action in the editor component using
* the proper namespace. In this case we call the addButton
* method for the components available in the editor instance. We
* define a label and an icon for the button and more important
* we tell the button which command has to trigger using the
* action property
*/
eidosmedia.webclient.actions.editor.components.addButton({
action: "custom.PrependText",
label: "Prepend Xml",
icon: 'icon-edit',
allowReadOnly: false,
singleItem: true
});
The addButton method requires a single Javascript object ( settings ) as a parameter. This objects need to have the following properties:
-
action: the name of the previously registered command
-
label: the label associated with the command
-
icon: the icon associated with the command.
-
allowReadOnly: if true the button is visible in the component when the story is read only.
-
singleItem: if true the button is visible in a single element of a component with multiple items, for example Collection and Gallery component.
Warning
|
If you need to use the call the same command from different parts of the editor ( e.g. the toolbar and some components ), or you need to differentiate the components for which the command is available, you can ( and should ) verify the origin of the action by checking the Context Object Component Type. This is detailed in the Verify the component type paragraph. |
Warning
|
singleItem attributte is available only for elements in a Collection and Gallery component. In the action method the second paramater contains the selectedItem object. |
2.c Editor components Drop Down menu
It’s possible to add one or more buttons in a drop down menu. In this case the submenu property has to be added to the settings object:
-
submenu: the object containing the buttons to be added in the drop down menu
/**
* We now register a new drop down menu action in the editor component using
* the proper namespace. In this case we call the addButton
* method for the components available in the editor instance. We
* define a label and an icon for the drow down menu and more important
* we set the submenu property that contains the button of the drop down menu
*/
eidosmedia.webclient.actions.editor.components.addButton({
action: "example.customDropDown",
label: "Custom popup",
name: "submenu.customDropDown",
icon: 'icon-copy',
allowReadOnly: false,
submenu: {
videoPreview: {
action: "example.openVideoPreview",
label: "Open Video Preview",
icon: 'fa fa-video-camera'
},
customEdit: {
action: "example.customEditing",
label: "Custom editing",
icon: 'icon-edit',
}
}
});
Implementation of the editor extensions
The editor extensions are powerful because they make use of an editor-related version of the context object. See Basic structure of the Context Object for further details.
As of any command implementation, it is possible to specify the isActive, isEnabled and action methods.
-
isActive method is called in different points according to the editor part it refers to.
-
For the toolbar the method is called after the story is loaded to determine whether a custom action is available.
-
For the components the method is called when a new component is created ( or an existing one is loaded from the story )
-
-
isEnabled method is called in different points according to the editor part it refers to.
-
For the toolbar the method is called whenever the user changes the current selection or cursor position.
-
-
the action is called when the user clicks on the corresponding action button.
Tip
|
All the methods are called with the same Context Object ( ctx ), which is enhanced for the editor and allows to access the current document ( activeDocument ). See Basic structure of the Context Object foo further details. |
Tip
|
Starting from 5.2020.11 version the same Context Object ( ctx ), is enhanced for the editor, ONLY for the editor of story, and allows to access the current document with a new property ( activeDocumentV2 ). In Swing Mobile App, due to Android platform (ONLY for Android), the activeDocument object is null. The activeDocumentV2 provides the same functionality of activeDocument in an asynchronous fashion way. See Basic structure of the Context Object foo further details. |
Warning
|
In the Editor context, activeObj and selection are NOT available. The available methods are:
Example the image component can embed also a video element. In addtion only in teh Editor context the following methods are available for the element info:
|
Important
|
The Editor Context Object is enriched by an additional object, named activeDocument, which contains a subset of methods to access the current document. These methods are described in the Editor API paragraph. |
Important
|
Starting from 5.2020.11 version, the Editor Context Object is enriched by an additional object, named activeDocumentV2, which contains a subset of methods to access, in an asynchronous way, the current document. These methods are described in the Editor API paragraph. |
Editor API
Suggestions for the Editor extensions
Verify the component type
Since the Editor Context object contains a method
ctx.component.getType();
it is possible to use it in the isEnabled and isActive methods to check the kind of component which is calling the action.
// EXCERPT FROM THE COMMAND CODE
isActive: function( ctx ) {
if ( ctx.component.getType() === 'toolbar') {
return true;
}
return false;
},
isEnabled: function( ctx ) {
// Enabling the action for the editable image only.
if ( ctx.component.getType() === ctx.activeDocument.CONSTANTS.BLOCK_IMAGE) {
return true;
}
return false;
},
Tip
|
Checking the component type is mandatory in case of actions added to the Editor components namespace. Otherwise, the action will be available for all components. It’s possible to use some constants defined in the activeDocument: ctx.activeDocument.CONSTANTS.BLOCK_IMAGE ctx.activeDocument.CONSTANTS.BLOCK_VIDEO |
Use of Editor API and extensions in Object Panel
Only for the Object Panel of an opened story, the activeDocument object of the Editor API is available. So, it is possible, from the Object Panel, to call custom actions and manipulate the current document.
It is suggested, though, to verify if the {ctx}.activeDocument is available to show and hide editor-related parts in the Object Panel. See example below:
// From the object panel API
ready: function( ctx ) {
// some other code...
if ( ctx.activeDocument ) {
// We are in the Editor.
$('.custom-editor-metadata-panel').show();
// Use it to manipulate the document
var sel = ctx.activeDocument.getSelection();
// ...
}
}
Starting form 5.2020.11 version only for the Object Panel of an opened story, the activeDocumentV2 object of the Editor API is available. So, it is possible, from the Object Panel, to call custom actions and manipulate the current document.
It is suggested, though, to verify if the {ctx}.activeDocumentV2 is available to show and hide editor-related parts in the Object Panel.
To learn how to extend the Object Panel, see Object panel documentation.
Full example of Editor extension
eidosmedia.webclient.commands.add({
name: "custom.PrependText",
action: function(ctx, params, callback) {
var editorApi = ctx.activeDocument;
// Obtain the current selection
var sel = editorApi.getSelection();
// Supposedly check the current selection ( if it a Content Item, ... )
sel.insertXml('<p>test</p>', 'insertBefore');
},
isActive: function( ctx ) {
// Enables it only for toolbar or Editable Image
var componentType = ctx.component.getType();
if ( componentType === 'toolbar' || componentType === 'editableimage' )
return true;
else
return false;
},
isEnabled: function( ctx ) {
var selection = ctx.activeDocument.getSelection();
var contentItem = sel.getContentItem();
if ( contentItem ) {
return true;
}
return false;
}
});
/**
* We now register a new action in the editor toolbar using
* the proper namespace. In this case we call the addButton
* method for the toolbar visible in the editor instance. We
* define a label and an icon for the button and more important
* we tell the button which command has to trigger using the
* action property
*/
eidosmedia.webclient.actions.editor.toolbar.addButton({
action: "custom.PrependText",
label: "Prepend Xml",
icon: 'icon-edit'
});
eidosmedia.webclient.actions.editor.components.addButton({
action: "custom.PrependText",
label: "Prepend Xml",
icon: 'icon-gear'
});
// Example for custom action for a single element in a Collection or Gallery component
eidosmedia.webclient.commands.add({
name: "example.openVideoPreview",
action: function(ctx, params, callback) {
// params contains the selectedItem
var selectedItem = params.selectedItem;
// checks selectedItem values
},
isActive: function( ctx ) {
// Handle condition activation
return true;
},
isEnabled: function( ctx ) {
// Handle condition enable
return true;
}
});
/**
* We now register a new action in the editor components using
* the proper namespace. We tell the button which command has to trigger using the
* action property
*/
eidosmedia.webclient.actions.editor.components.addButton({
action: "example.openVideoPreview",
label: "Open Video Preview",
icon: 'icon-facetime-video',
singleItem: true
});
Override editor’s default counter
Swing editor comes with a default counter for chars and words. On the one hand, it is possible to specify an additional counter under the Editor configuration ; on the other hand, it is possible to completely override the counter behaviour by defining the following function.
eidosmedia.webclient.editor.counter = function( counterInfo, storyInfo, userInfo ) { /* function here */ }
Method |
|
Parameter |
|
Parameter |
|
Parameter |
|
Returns |
|
So, if the user wants to override the counter behaviour, the eidosmedia.webclient.editor.counter
method provides all the available information. The result of the function MUST be a valid HTML which is placed in the "counter area" of the Editor.
Tip
|
To create a separator, use an empty DIV with the class "em-info-separator" (see examples below). |
Warning
|
If you need to use this features, you’ll probably need to change the Editor > Story > Count configuration to contentItem . See the Story Editor Configuration. |
Full working example
The following example warns the user if the number of characters in a particular content item is reaching ( or above ) the maximum level. It only works with the "contentItem" configuration.
(function() {
eidosmedia.webclient.editor.counter = function( countInfo, storyInfo, userInfo ) {
var charsStyle = '';
var html = '';
var countLimits = {
'headline': 50,
'text': 1500
};
var countXpathLimits = {
'/doc/story/grouphead/headline': 10,
};
var found = false;
if (countInfo.xpath) {
var MAX_CHARS_IN_XPATH = countXpathLimits[ countInfo.xpath ];
found = MAX_CHARS_IN_XPATH != null;
if ( MAX_CHARS_IN_XPATH &&
countInfo.chars > MAX_CHARS_IN_XPATH ) {
charsStyle = 'color: white; font-weight: bold; background-color: red;';
} else if ( MAX_CHARS_IN_XPATH &&
countInfo.chars > (MAX_CHARS_IN_XPATH*0.75) ) {
// We have gone over the 75% of the allowed number of characters
charsStyle = 'color: black; font-weight: bold; background-color: orange;';
}
}
if ( !found && countInfo.contentItemType ) {
var MAX_CHARS_IN_CONTENTITEM = countLimits[ countInfo.contentItemType ];
if ( MAX_CHARS_IN_CONTENTITEM &&
countInfo.chars > MAX_CHARS_IN_CONTENTITEM ) {
charsStyle = 'color: white; font-weight: bold; background-color: red;';
} else if ( MAX_CHARS_IN_CONTENTITEM &&
countInfo.chars > (MAX_CHARS_IN_CONTENTITEM*0.75) ) {
// We have gone over the 75% of the allowed number of characters
charsStyle = 'color: black; font-weight: bold; background-color: orange;';
}
}
html += '<span class="em-info-container" style="' + charsStyle +
'"><b>Chars:</b> <span id="chars_counter">' + (countInfo.chars || 0) +
'</span></span>';
html += '<span class="em-info-container" id="words_counter_box">' +
'<b>Words:</b> <span id="words_counter">' + (countInfo.words || 0) +
'</span></span>';
if ( countInfo.customValue ) {
html += '<span class="em-info-container"><b id="custom_counter_label">' +
countInfo.customLabel + '</b><span id="custom_counter">' +
countInfo.customValue + '</span></span>';
}
return html;
}
})();
Loaded document callback action
It is possible to register an action that would be called when the Swing editor has finished loading the current document. This action will be provided with the context object for the editor extensions and will be able to access the current document Editor API (activeDocument) and activeObject.
Example
(function () {
// Register the after load callback
eidosmedia.webclient.extensions.editor.afterLoad.register(function (ctx) {
var team = ctx.getCurrentUserInfo().team;
// Access the current loaded document
var node = ctx.activeDocument.getNode({ xpath: "/doc/story/summary/p" });
node.replaceTextContent("Team: " + team);
});
})();
General information on the Editor API
Editor API allows the user to perform different operations on the currently opened document. They are available within the Context Object, when the user is editing a Story.
Warning
|
Editor API are to be considered as a feature in progress. Changes and additions may be made without warning. |
Tip
|
In the source code, we will refer to the Context Object as a generic "ctx" object. |
activeDocument
The activeDocument is the entry point of the Editor API. It contains a set of different methods to analyze and manage the currently opened document.
Methods of the activeDocument object
getXmlContent
Returns the complete XML content of the document.
It can be called as
ctx.activeDocument.getXmlContent();
Method |
|
Parameter |
None |
Returns |
|
Example
// Obtains the XML of the document.
var xml = ctx.activeDocument.getXmlContent();
// For example, we can parse the XML with jQuery and use it somehow.
var parsedXML = $.parseXML( xml );
// ...
getTextContent
Returns the complete text content of the document.
It can be called as
ctx.activeDocument.getTextContent(options);
Method |
|
Parameter |
Optional
|
Returns |
|
Example
// Obtains the text content of the document.
var options = {};
// Uncomment this line if you want to include witespace nodes
options.includeWhitespaceNodes = true;
var text = ctx.activeDocument.getTextContent(options);
// ...
getMetadata
Returns the complete Metadata of the document as a string.
It can be called as
ctx.activeDocument.getMetadata( callbacks );
Method |
|
Parameter |
|
Returns |
|
Warning
|
This call is asynchronous. The Metadata string is available only as the parameter of the success callback. |
Example
// Obtains the Metadata of the document
ctx.activeDocument.getMetadata({
success: function( metadata ) {
// Do something with this...
},
error: function( err ) {
// For example.
ctx.showError( err.message );
}
});
getSelection
Returns the current Selection in the active document.
Tip
|
The current selection is an object of type Selection. See Selection object for further information on available methods. |
It can be called as
ctx.activeDocument.getSelection();
Method |
|
Parameter |
None |
Returns |
|
Example
// Obtains the current selection.
var sel = ctx.activeDocument.getSelection();
// sel is now a Selection object.
// For example, we can verify that the current selection is a ContentItem
var selNode = sel.getNode();
if ( selNode.nodeType === ctx.activeDocument.CONSTANTS.CONTENTITEM_TYPE ) {
// Perform a specific action...
}
insertXML
Insert an XML in a specified part of the document.
It can be called as
ctx.activeDocument.insertXML(xml, xpathOptions, insertOptions);
Method |
|
Parameter |
e.g. |
Parameter |
See example below. |
Parameter |
Otherwise, it is possible to directly pass the insertType as a string ( |
Returns |
|
Warning
|
At the moment, if the specified xpath in the xpathOptions corresponds to more than one xPath, only the first is taken. |
// Prepares the xml.
var xml = '<p>Prepend me</p>';
ctx.activeDocument.insertXml( xml, {
xpath: 'doc/story/text/superbyline',
criteria: {
[
param: 'xsm-preserve',
condition: 'equal',
value: 'true'
]
} },
'prepend' );
// the xml will be inserted only in the first superbyline tag that satisfy xpath and the additional (optional) criteria
// Prepares the xml.
var xml = '<h1><?EM-dummyText lorem ipsum?></h1>';
ctx.activeDocument.insertXml( xml, {xpath: 'cursorPosition'});
// the xml will be inserted at the cursor position, replacing the current selection if not collapsed.
getDocumentInfo
Returns a subset of information on the current document. The information includes the following information : channel, workfolder, issueDate, templateName, language.
It can be called as
ctx.activeDocument.getDocumentInfo();
Method |
|
Parameter |
None |
Returns |
|
Example
// Obtains the document information.
var documentInfo = ctx.activeDocument.getDocumentInfo();
/*
documentInfo is now:
{
"id": "id",
"readonly": true,
"channel": "CHANNEL",
"workfolder": "WORKFOLDER",
"issueDate": "ISSUE DATE",
"templateName": "TEMPLATE NAME",
"language": "en/uk"
}
*/
if ( documentInfo.channel === 'Globe-Web' ) {
// ... do something, for example it can remove a specific custom button.
}
isReadonly
Returns the readonly status of the story
It can be called as
ctx.activeDocument.isReadonly();
Method |
|
Parameter |
None |
Returns |
|
Example
// Obtains the document information.
var isReadonly = ctx.activeDocument.isReadonly();
saveDocument
Execute the save of the current document.
It can be called as
ctx.activeDocument.saveDocument();
Method |
|
Parameter |
Optional {Function} callback - A function invoked if the the document is successfully saved |
Warning
|
If the document is not dirty, the save is not executed, but the callback, if defined, is always invoked. |
Example
// Save the current document.
ctx.activeDocument.saveDocument();
getNode
Returns a specific node, as a DocumentNode object, upon the information contained in the XPath
It can be called as
ctx.activeDocument.getNode(xpathOptions);
Method |
|
Parameter |
|
Return |
|
Warning
|
At the moment, if the specified xpath in the xpathOptions corresponds to more than one node, only the first is taken. |
Example
// prepare the xpath options
var xpathOptions = {
xpath: 'doc/story/text',
criteria: {
[ param: 'channel',
condition: 'equal',
value: 'Globe-Print'
]
}
};
// Obtains the node.
var node = ctx.activeDocument.getNode(xpathOptions);
// Perform actions on the found node
// ...
if (node) {
...
}
insertExternalUrl
Insert an external URL in the document, upon the information contained in the object to insert and in the provided options
It can be called as
ctx.activeDocument.insertExternalUrl(item, insertOptions);
Method |
|
Parameter |
|
Parameter |
|
Return |
|
Example
// prepare the object to insert
var item = {
'url': 'https://images-assets.nasa.gov/image/GSFC_20171208_Archive_e001240/GSFC_20171208_Archive_e001240~orig.jpg',
'type': 'web::image'
};
// Perform the insert.
ctx.activeDocument.insertExternalUrl(item, {});
insertObject
Insert a list of Methode Object in the document, upon the information contained in the reference object to insert and in the provided insertOptions
It can be called as
ctx.activeDocument.insertObject(reference, insertOptions);
Method |
|
Parameter |
|
Parameter |
|
Return |
|
Example
// prepare the object to insert
// Two image objects will be inserted using the paths
const reference = {
full: false,
referenceListIds: ['/Globe/Images/Foreign/11.obama_family.jpeg', '/Globe/Images/Foreign/1420087334.jpg'],
withPath: true
}
// Example One
const insertOptionsOne = {
insertiontype: "insert"
};
// Perform the insert.
ctx.activeDocument.insertObject(reference, insertOptionsOne);
// Example Two
const insertOptionsTwo = {
insertiontype: "insert",
templateInfo: {name: "", type: eomeditor.publicapi.TEMPLATE_TYPE.IMAGE}
};
// Perform the insert.
ctx.activeDocument.insertObject(reference, insertOptionsTwo);
// Example Three
const insertOptionsThree = {
insertiontype: "insert",
templateInfo: {name: "image web square", type: eomeditor.publicapi.TEMPLATE_TYPE.IMAGE}
};
// Perform the insert.
ctx.activeDocument.insertObject(reference, insertOptionsThree);
setDocumentToBeRefreshed
Some events in Swing are not handled. This API could be useful when some actions are fired and they change the document server side. This way, it’s possible to warn the user that the document should be refresh.
It can be called as
ctx.activeDocument.setDocumentToBeRefreshed(options);
Method |
|
Parameter |
|
Return |
|
Example
action: function(ctx, params, callback) {
var editorApi = ctx.activeDocument;
editorApi.setDocumentToBeRefreshed();
}
switchToChannel(channel)
Switch the document to the specified channel
It can be called as
ctx.activeDocument.getCollectionSelectedItems(attrOptions)
Method |
|
Parameter |
Required |
// Switch to channel
ctx.activeDocument.switchToChannel(channel);
Constants of the activeDocument object
The activeDocument object comes with a set of constants to simplify the management of the return values of the different methods.
The constants are available under
activeDocument.CONSTANTS
Currently the following constants are visible:
ctx.activeDocument.CONSTANTS = {
DUMMY_TYPE: 'DummyText', // Document Node type
CONTENTITEM_TYPE: 'ContentItem', // Document Node type
CONTENTBLOCK_TYPE: 'ContentBlock', // Document Node type
CONTENTNODE_TYPE: 'ContentNode', // Document Node type,
BLOCK_IMAGE: 'image', // ContentBlock of type Image
BLOCK_VIDEO: 'video', // ContentBlock of type Video
};
activeDocumentV2
The activeDocumentV2 is an entry point of the Editor API starting form version 5.2020.11. It contains a set of different methods to analyze and manage the currently opened document in an asynchronous way that are cross platform compatible (Swing, Swing Mobile, Prime). Starting from the version 5.2020.11, we reccomend to use activeDocumentV2 and evaluating the migration for existing extensions.
Methods of the activeDocumentV2 object
getXmlContent
Returns the complete XML content of the document or a part of it based on the options parameter.
It can be called as
ctx.activeDocumentV2.getXmlContent(options);
Method |
|
Parameter |
If options is not specied or if it’s an empty object the xml of the entire docment will be returned. |
Returns |
|
Example
// Obtains the XML of the document.
ctx.activeDocumentV2.getXmlContent({}).then(result => {
console.log(`V2 async document result: ${result}`);
}).catch(error => {
console.log(`V2 async document error: ${error}`);
});
// Obtains the XML of the current selection
ctx.activeDocumentV2.getXmlContent({useSelection: true}).then(result => {
console.log(`V2 async result selection: ${result}`);
}).catch(error => {
console.log(`V2 async error selection: ${error}`);
});
// Obtains the XML of a specific node
var xpathOptions = {
'xpath': 'doc/story/text'
};
ctx.activeDocumentV2.getXmlContent({xpathOptions}).then(result => {
console.log(`V2 async xpath result: ${result}`);
}).catch(error => {
console.log(`V2 async xpath error: ${error}`);
});
// ...
getTextContent
Returns the complete text content of the document.
It can be called as
ctx.activeDocumentV2.getTextContent();
Method |
|
Returns |
|
Example
// Obtains the text of the document.
ctx.activeDocumentV2.getTextContent().then(result => {
console.log(`V2 async document result: ${result}`);
}).catch(error => {
console.log(`V2 async document error: ${error}`);
});
// ...
replaceXmlContent
Replaces the XML content of a node.
It can be called as
ctx.activeDocumentV2.replaceXmlContent(options);
Method |
|
Parameter |
|
Return |
|
// prepare the xpath options
var xpathOptions = {
xpath: 'doc/story/summary',
criteria: {
[
param: 'channel',
condition: 'equal',
value: 'Globe-Print'
]
}
};
// REPLACE XML content
ctx.activeDocumentV2.getXmlContent({xpathOptions}).then( content => {
var newContent = '<summary id="U26664270086oOb"><p>New summary content</p></summary>';
ctx.activeDocumentV2.replaceXmlContent({newContent, xpathOptions}).then(result => {
console.log('content replaced')
});
})
...
//
saveDocument
Execute the save of the current document.
It can be called as
ctx.activeDocumentV2.saveDocument();
Method |
|
Return |
|
Warning
|
If the document is not dirty, the save is not executed, but the promise is always resolved. |
Example
// Save the current document.
ctx.activeDocumentV2.saveDocument().then(result => {
console.log(`save operation successfully excuted`);
}).catch(error => {
console.log(`an error occurred saving the document`);
});
insertXmlContent
Insert an XML in a specified part of the document..
It can be called as
ctx.activeDocumentV2.insertXmlContent(options);
Method |
|
Parameter |
|
Return |
|
var xpathOptions = {
xpath: 'cursorPosition'
};
var xmlContent = '<h1><?EM-dummyText lorem ipsum?></h1>';
activeDocumentV2.insertXmlContent({xmlContent, xpathOptions}).then(result => {
console.log('content has been inserted');
}).catch(error => {
console.log('content has not been inserted');
});
...
//
Selection object
The Selection Object allows to manipulate the selection. It contains a set of properties and methods described below.
Methods
getNode
Returns the current selected node, as a DocumentNode object.
It can be called as
{SelectionObject}.getNode();
Method |
|
Parameter |
Optional - Set options.getWrappedSection = true if it’s needed to get the section wrapped node |
Return |
|
// Obtains the document selection
var sel = ctx.activeDocument.getSelection();
var selectedNode = sel.getNode();
// Perform actions on the selected node
// ...
getXmlContent
Returns the XML of the current Selection.
It can be called as
{SelectionObject}.getXmlContent();
Method |
|
Parameter |
None |
Return |
|
// Obtains the document selection
var sel = ctx.activeDocument.getSelection();
var selectedXml = sel.getXmlContent();
// Perform actions on the selected node
// ...
Tip
|
Calling |
insertXml
Insert an XML in a specified part of the current selection or replaces the current selection with the new XML.
It can be called as
{SelectionObject}.insertXML(xml, insertOptions);
Method |
|
Parameter |
e.g. |
Parameter |
Otherwise, it is possible to directly pass the insertType as a string ( |
Returns |
|
// Obtains the document information.
var xml = '<p>Prepend me</p>';
var sel = ctx.activeDocument.getSelection();
sel.insertXml( xml, 'prepend' );
prepend, append
Insert an XML in a specified part of the current selection. They are shortcuts method for insertXml.
It can be called as
{SelectionObject}.prepend(xml);
{SelectionObject}.append(xml);
See insertXml for further details.
getTextContent
Returns the text content of the current Selection.
It can be called as
{SelectionObject}.getTextContent();
Method |
|
Parameter |
Optional
|
Return |
|
// Obtains the document selection
var sel = ctx.activeDocument.getSelection();
var options = {};
// Uncomment this line if you want to include witespace nodes
// options.includeWhitespaceNodes = true;
var text = sel.getTextContent(options);
// ...
Tip
|
Calling |
DocumentNode interface
It is the lowest-level object available for manipulating the Active Document. It represents a node within the document. It contains different methods and properties to interact with the node.
Tip
|
The DocumentNode object is NOT a DOM node, so operation as $(<DocumentNode>) will not work. |
Properties
nodeType
Return the node type. Can be one of the following:
-
ContentItem
-
ContentNode
-
ContentBlock
-
DummyText
Tip
|
Verify the value of this property against the Constants of the activeDocument object to perform the best check. |
Tip
|
Each Document Node type has specific methods. See Types for details on each document node. |
var sel = ctx.activeDocument.getSelection();
var selectedNode = sel.getNode();
if ( selectedNode.nodeType === ctx.activeDocument.CONSTANTS.DUMMY_TYPE ) {
// It is a dummy text...
sel.append('<p>New text here</p>');
}
contentItem
Returns the contentItem in which the element is contained. It can be one of two values:
-
null
, if the element is not part of any contentItem, or it is a contentItem itself. -
{DocumentNode} ContentItem
the document node of type 'ContentItem'. See ContentItem for further details.
Methods
getXmlContent
Returns the XML of the node.
It can be called as
{DocumentNode}.getXmlContent();
Method |
|
Parameter |
None |
Return |
|
// prepare the xpath options
var xpathOptions = {
xpath: 'doc/story/text',
criteria: {
[
param: 'channel',
condition: 'equal',
value: 'Globe-Print'
]
}
};
// Obtains the node.
var node = ctx.activeDocument.getNode(xpathOptions);
// Perform actions on the found node
// ...
if (node) {
var xmlContent = node.getXmlContent();
}
replaceXmlContent
Replaces the XML content of the current node.
It can be called as
{DocumentNode}.replaceXmlContent();
Method |
|
Parameter |
|
Return |
|
// prepare the xpath options
var xpathOptions = {
xpath: 'doc/story/summary',
criteria: {
[
param: 'channel',
condition: 'equal',
value: 'Globe-Print'
]
}
};
// Obtains the node.
var node = ctx.activeDocument.getNode(xpathOptions);
// Perform actions on the found node
// ...
if (node) {
var repxml = '<summary id="U26664270086oOb"><p>New summary content</p></summary>';
node.replaceXmlContent(repxml);
}
getTextContent
Returns the text content of the node.
It can be called as
{DocumentNode}.getTextContent();
Method |
|
Parameter |
Optional
|
Return |
|
// prepare the xpath options
var xpathOptions = {
xpath: 'doc/story/text',
criteria: {
[
param: 'channel',
condition: 'equal',
value: 'Globe-Print'
]
}
};
// Obtains the node.
var node = ctx.activeDocument.getNode(xpathOptions);
// Perform actions on the found node
// ...
if (node) {
var options = {};
// Uncomment this line if you want to include witespace nodes
// options.includeWhitespaceNodes = true;
var text = node.getTextContent(options);
// ....
}
replaceTextContent
Replace the text of the node with another text.
It can be called as
{DocumentNode}.replaceTextContent(text);
Method |
|
Parameter |
|
Parameter |
|
Returns |
|
Warning
|
Right now to execute the replace the API use the information in the current selection. |
// Obtains the current selection.
var sel = ctx.activeDocument.getSelection();
var selectedNode = sel.getNode();
// Replace the text of the current node with simple text
selectedNode.replaceTextContent( 'Simple text' );
// Replace the text of the current node with an xml format
selectedNode.replaceTextContent('<a href="http://www.eidosmedia.com" title="Eidosmedia">Eidosmedia</a>', {'format': 'xml'});
getContentInfo
Returns an object that contains a set of different methods to analyze and manage the current node.
Warning
|
This method is valid only for content nodes that refers to Methode Content: Images, External content items. |
API functions to get and set system attributes and metadata of an image linked to a story
It can be called as
{DocumentNode}.getContentInfo();
Method |
|
Parameter |
None |
Return |
|
// Obtains the current selection.
var sel = ctx.activeDocument.getSelection();
var selectedNode = sel.getNode();
// Perform actions on the found node
// ...
if (selectedNode) {
var ctx = selectedNode.getContentInfo();
var id = ctx.getId();
var type = ctx.getType();
var sysAttributes = ctx.getSysAttributes();
var usageTickets = ctx.getUsageTickets();
}
getAttributes
Get node attributes.
It can be called as
{DocumentNode}.getAttributes();
Method |
|
Parameter |
None |
Return |
|
// Obtains the current selection.
var sel = ctx.activeDocument.getSelection();
var selectedNode = sel.getNode();
// Perform actions on the found node
if (selectedNode) {
var attributes = selectedNode.getAttributes();
// ...
}
setAttributes
Set attributes to a node.
It can be called as
{DocumentNode}.setAttributes();
Method |
|
Parameter |
|
Return |
|
Warning
|
Don’t use this API to set the channel attribute. |
// prepare the xpath options
var xpathOptions = {
xpath: 'doc/story/summary',
criteria: {
[
param: 'channel',
condition: 'equal',
value: 'Globe-Print'
]
}
};
// Obtains the node by x path.
var node = ctx.activeDocument.getNode(xpathOptions);
// To obtain the node by selection uncomment the following lines
// var sel = editorApi.getSelection();
// var node = sel.getNode();
var attrOptions = {};
var attributes = [{'name': 'testattr', 'value': 'testvalue'}];
attrOptions.attributes = attributes;
// Perform actions on the found node
// ...
if (node) {
node.setAttributes(attrOptions);
}
setExternalReference
Set a refence of a Methode object to a node.
It can be called as
{DocumentNode}.setExternalReference();
Method |
|
Parameter |
Required |
Parameter |
Optional
|
Return |
|
Warning
|
cover, hardcrop, tmx and xtransform settings are used inserting only images or graphics |
var editorApi = ctx.activeDocument;
var sel = editorApi.getSelection();
var node = sel.getNode();
var reference = path o loid of the objects to insert
const settings = {
cover: true
hardCrop: false
tmx: null
xtransform: null
}
node.setExternalReference( reference, settings );
setChannels
Set channels to a node.
It can be called as
{DocumentNode}.setChannels();
Method |
|
Parameter |
|
Return |
|
// prepare the xpath options
var xpathOptions = {
xpath: 'doc/story/summary',
criteria: {
[
param: 'highlight',
condition: 'equal',
value: 'yes'
]
}
};
// Obtains the node by x path.
var node = ctx.activeDocument.getNode(xpathOptions);
// To obtain the node by selection uncomment the following lines
// var sel = editorApi.getSelection();
// var node = sel.getNode();
var channels = ['Globe-Web'];
// Perform actions on the found node
// ...
if (node) {
node.setChannels(channels);
}
Types
There are four different DocumentNode
types.
ContentItem
Its nodeType can be checked against ctx.activeDocument.CONSTANTS.CONTENTITEM_TYPE
.
It has some specific methods:
duplicate
Duplicates a contentItem.
It can be called as
{ContentItem}.duplicate(channel);
Method |
|
Parameter |
e.g. |
Returns |
|
// Obtains the current selection.
var sel = ctx.activeDocument.getSelection();
var selectedNode = sel.getNode();
if ( selectedNode.nodeType === ctx.activeDocument.CONSTANTS.CONTENTITEM_TYPE ) {
// it is a ContentItem node. Duplicate itself.
selectedNode.duplicate( 'Globe-Web,Globe-Print' );
} else {
// Duplicates the container ContentItem.
selectedNode.contentItem.duplicate( 'Globe-Web,Globe-Print' );
}
duplicateContent
Copy the content of the ContentItem node into another node.
It can be called as
{ContentItem}.duplicateContent(xpathOptions);
Method |
|
Parameter |
See example below. |
Returns |
|
Warning
|
At the moment, if the specified xpath in the xpathOptions corresponds to more than one node, only the first is taken. |
// Obtains the current selection.
var sel = ctx.activeDocument.getSelection();
var selectedNode = sel.getNode();
var xpathOptions = {
xpath: 'doc/story/text',
criteria: {
[
param: 'xsm-preserve',
condition: 'equal',
value: 'true'
]
}
};
if ( selectedNode.nodeType === ctx.activeDocument.CONSTANTS.CONTENTITEM_TYPE ) {
// it is a ContentItem node. Duplicate its own content.
selectedNode.duplicateContent( xpathOptions );
} else {
// Duplicates the content of the container ContentItem.
selectedNode.contentItem.duplicateContent( xpathOptions );
}
ContentNode
Its nodeType can be checked against ctx.activeDocument.CONSTANTS.CONTENTNODE_TYPE
.
It has no specific methods at the moment.
ContentBlock
Its nodeType can be checked against ctx.activeDocument.CONSTANTS.CONTENTBLOCK_TYPE
.
Its blockType can be checked against ctx.activeDocument.CONSTANTS.BLOCK_*
.
Methods common to all the ContentBlocks
Returns the XML of the current node.
It can be called as
{ContentBlock}.getXmlContent();
Method |
|
Parameter |
None |
Return |
|
// Obtains the document selection
var sel = ctx.activeDocument.getSelection();
var selectedNode = self.getNode();
if ( selectedNode.nodeType === ctx.activeDocument.CONSTANTS.CONTENTITEM_TYPE ) {
var xml = selectedNode.getXmlContent();
// ...
}
Replaces the XML content of the current node.
It can be called as
{ContentBlock}.replaceXmlContent();
Method |
|
Parameter |
|
Return |
|
Warning
|
If the specified xml doesn’t contain a special element an error occurred. A block content can be replaced only with another block content. Right now we can replace only imageElement, videoElement and objectElement |
// Obtains the document selection
var sel = ctx.activeDocument.getSelection();
var selectedNode = self.getNode();
if ( selectedNode.nodeType === ctx.activeDocument.CONSTANTS.CONTENTBLOCK_TYPE ) {
var xml = '<photo-web><fw-photo width="200" height="200"></fw-photo>' +
'<photo-caption channel="Globe-Web"><?EM-dummyText Insert caption first here?><p><?EM-dummyText Insert caption here?></p></photo-caption></photo-web>';
var result = selectedNode.replaceXmlContent(xml);
// ...
}
Image Block
It represents an Image Block. Its blockType can be checked against ctx.activeDocument.CONSTANTS.BLOCK_IMAGE
.
Copies the image into other image elements, maintaining the crop and the transformation information.
It can be called as
{ContentBlock}.copyImage(xpathOptions, settings)
Method |
|
Parameter |
See example below. |
Parameter |
|
Returns |
|
Warning
|
At the moment, if the specified xpath in the xpathOptions corresponds to more than one xPath, only the first is taken. |
// Obtains the current selection
var sel = ctx.activeDocument.getSelection();
var selNode = sel.getNode();
// Check if it is an image block
if ( selNode.blockType === ctx.activeDocument.CONSTANTS.BLOCK_IMAGE ) {
var xpathOptions = {
'xpath': 'doc/story/text/photo-web/fw-photo',
'criteria': [
{'param': 'eomattr',
'condition': 'equal',
'value': 'true'}
]
};
selNode.copyImage(xpathOptions, { 'cover': true, 'hardCrop': false, 'copy': true });
}
Change the alignment of a block component.
It can be called as
{ContentBlock}.changeAlignment(align, settings)
Method |
|
Parameter |
Required |
Parameter |
Optional See example below. |
// Obtains the current selection
var sel = ctx.activeDocument.getSelection();
var selNode = sel.getNode();
// Check if it is an image block
if ( selNode.blockType === ctx.activeDocument.CONSTANTS.BLOCK_IMAGE ) {
selNode.changeAlignment('center');
}
Change width and height of a block.
It can be called as
{ContentBlock}.changeBlockDimensions(xpathOptions, settings)
Method |
|
Parameter |
Required |
Parameter |
Optional See example below. |
// Obtains the current selection
var sel = ctx.activeDocument.getSelection();
var selNode = sel.getNode();
// Check if it is an image block
if ( selNode.blockType === ctx.activeDocument.CONSTANTS.BLOCK_IMAGE ) {
var dimensions = {'width': 300, 'height': 300};
selNode.changeBlockDimensions(dimensions);
}
Video Block
It has no specific methods at the moment.
Collection Block
It represents a Collection Block. It can be of three types: insert, embed or link. Its blockType can be checked against ctx.activeDocument.CONSTANTS.BLOCK_COLLECTION_INSERT
, ctx.activeDocument.CONSTANTS.BLOCK_COLLECTION_EMBED
, ctx.activeDocument.CONSTANTS.BLOCK_COLLECTION_LINK
.
Set attributes to an item of a collection .
It can be called as
{ContentBlock}.setItemAttributes(attrOptions)
Method |
|
Parameter |
|
Returns |
|
Warning
|
At least selected or index must be specified, otherwise the attributes will be not applied. |
// Obtains the current selection
var sel = ctx.activeDocument.getSelection();
var selNode = sel.getNode();
// Check if it is a collection block
if ( selNode.blockType === ctx.activeDocument.CONSTANTS.BLOCK_COLLECTION_INSERT ||
selNode.blockType === ctx.activeDocument.CONSTANTS.BLOCK_COLLECTION_EMBED ||
selNode.blockType === ctx.activeDocument.CONSTANTS.BLOCK_COLLECTION_LINK) {
var options = {};
var attributes = [{'name': 'eomtest', 'value': 'test'}, {'name': 'class', 'value': 'testclass'}];
options.attributes = attributes;
options.selected = true; // the attributes will be applied to the selected item
selNode.setItemAttributes(options);
}
Get the selected items of a collection .
It can be called as
{ContentBlock}.getCollectionSelectedItems(attrOptions)
Method |
|
Parameter |
|
Returns |
|
// Obtains the current selection
var sel = ctx.activeDocument.getSelection();
var selNode = sel.getNode();
// Check if it is a collection block
if ( selNode.blockType === ctx.activeDocument.CONSTANTS.BLOCK_COLLECTION_INSERT ||
selNode.blockType === ctx.activeDocument.CONSTANTS.BLOCK_COLLECTION_EMBED ||
selNode.blockType === ctx.activeDocument.CONSTANTS.BLOCK_COLLECTION_LINK) {
var options = {};
// Uncomment this lines if you want to get items with a specific attribute value
/* var attributes = [{'name': 'lead', 'value': 'test'}];
options.attributes = attributes; */
var selectedItems = selNode.getCollectionSelectedItems(options);
}
DummyText
Its nodeType can be checked against ctx.activeDocument.CONSTANTS.DUMMY_TYPE
.
It has no specific methods at the moment.
From activeDocument to activeDocumentV2
Follows some examples to compare the use of activeDocument and activeDocumentV2 to perform the same operation.
getXmlContent
Example
// ***** activeDocument ******
// Obtains the current selection.
var sel = ctx.activeDocument.getSelection();
// get the node
var selNode = sel.getNode();
var xmlContent = node.getXmlContent();
// ***** activeDocumentV2 ******
// Obtains the XML of the current selection
ctx.activeDocumentV2.getXmlContent({useSelection: true}).then(result => {
console.log(`V2 async result selection: ${result}`);
}).catch(error => {
console.log(`V2 async error selection: ${error}`);
});
// ...
getTextContent
Example
// ***** activeDocument ******
// Obtains the text
var textContent = ctx.activeDocument.getTextContent();
// ***** activeDocumentV2 ******
// Obtains the XML of the current selection
ctx.activeDocumentV2.getTextContent().then(result => {
console.log(`V2 async result selection: ${result}`);
}).catch(error => {
console.log(`V2 async error selection: ${error}`);
});
// ...
replaceXmlContent
Example
// ***** activeDocument ******
// prepare the xpath options
var xpathOptions = {
xpath: 'doc/story/summary',
criteria: {
[
param: 'channel',
condition: 'equal',
value: 'Globe-Print'
]
}
};
// Obtains the node.
var node = ctx.activeDocument.getNode(xpathOptions);
// Perform actions on the found node
// ...
if (node) {
var repxml = '<summary id="U26664270086oOb"><p>New summary content</p></summary>';
node.replaceXmlContent(repxml);
}
// ***** activeDocumentV2 ******
// prepare the xpath options
var xpathOptions = {
xpath: 'doc/story/summary',
criteria: {
[
param: 'channel',
condition: 'equal',
value: 'Globe-Print'
]
}
};
// REPLACE XML content
ctx.activeDocumentV2.getXmlContent({xpathOptions}).then( content => {
var newContent = '<summary id="U26664270086oOb"><p>New summary content</p></summary>';
ctx.activeDocumentV2.replaceXmlContent({newContent, xpathOptions}).then(result => {
console.log('content replaced')
});
})
// ...
saveDocument
Example
// ***** activeDocument ******
ctx.activeDocument.saveDocument();
// ***** activeDocumentV2 ******
// Save the current document.
ctx.activeDocumentV2.saveDocument().then(result => {
console.log(`save operation successfully excuted`);
}).catch(error => {
console.log(`an error occurred saving the document`);
});
// ...
insertXmlContent
Example
// ***** activeDocument ******
var newXmlContent = '<h1><?EM-dummyText lorem ipsum?></h1>';
var retValue = ctx.activeDocument.insertXml(newXmlContent, {xpath: 'cursorPosition'});
// ***** activeDocumentV2 ******
var xpathOptions = {
xpath: 'cursorPosition'
};
var xmlContent = '<h1><?EM-dummyText lorem ipsum?></h1>';
activeDocumentV2.insertXmlContent({xmlContent, xpathOptions}).then(result => {
console.log(`content has not been inserted`);
}).catch(error => {
console.log(`content has not been inserted ${error}`);
});
// ...
General information on the GalleryEditor API
GalleryEditor API allows the user to perform different operations on the currently opened document. They are available within the Context Object, when the user is editing a Gallery.
Warning
|
GalleryEditor API are to be considered as a feature in progress. Changes and additions may be made without warning. |
Tip
|
In the source code, we will refer to the Context Object as a generic "ctx" object. |
activeDocument
The activeDocument is the entry point of the GalleryEditor API. It contains a set of different methods to analyze the currently opened document.
Methods of the activeDocument object
getXmlContent
Returns the complete XML content of the document.
It can be called as
ctx.activeDocument.getXmlContent();
Method |
|
Parameter |
None |
Returns |
|
Example
// Obtains the XML of the document.
var xml = ctx.activeDocument.getXmlContent();
// For example, we can parse the XML with jQuery and use it somehow.
var parsedXML = $.parseXML( xml );
// ...
getObjectsData
Returns an array containing the list of the data of each object present in the active document.
It can be called as
ctx.activeDocument.getObjectsData();
Method |
|
Parameter |
None |
Returns |
|
Warning
|
The objects contained in the array are intended as "read only" objects. Any change made on them will not be reflected in the active document. |
Example
// Obtains the current selection.
var objectsData = ctx.activeDocument.getObjectsData();
// objectsData is now an array of objects.
Here below an extract of the data contained in each returned object:
{
"id": "199$1.0.624088073",
"type": "Image",
"name": "Official_portrait_of_Barack_Obama-U47037702204ISU-266x200@Globe-Web.jpg",
"description": "",
"owner": "user",
"creator": "user",
"created": 1457105152,
"last_modifier": "user",
"size": 125008,
"system_attributes": {
"workfolder": "",
"template": "",
"templateName": "",
"summary": "",
"wordCount": "",
"sugCategory": "",
"channel": "",
"title": "...",
"storyType": "",
"productInfo": {
"name": "",
"issueDate": ""
},
"imageInfo": {
"width": 266,
"height": 200,
"ptWidth": 63.84000015258789,
"ptHeight": 48,
"colorType": "RGB",
"processTypes": ["resample"]
},
"priority": ""
},
"system_attributes_xml": "<props><process><type>resample</type></process><title>...</title><summary/><imageInfo>\n<width>266</width>\n<height>200</height>\n<ptWidth>63.84</ptWidth>\n<ptHeight>48.0</ptHeight>\n<xDim>22.52</xDim>\n<yDim>16.93</yDim>\n<dim>2.252cm x 1.693cm</dim>\n<xres>300.0</xres>\n<yres>300.0</yres>\n<colorType>RGB</colorType>\n<fileType>PNG</fileType>\n</imageInfo></props>",
"usage_ticket": "<?xml version='1.0' encoding='UTF-8'?><tl></tl>"
}
isCroppedImage
Return a boolean value to check if the image is hard cropped.
It can be called as
ctx.activeDocument.isCroppedImage(loid);
Method |
|
Parameter |
|
Returns |
|
// Obtain the cropped information.
var isCropped = ctx.activeDocument.isCroppedImage(loid);
//check the isCropped variable
saveDocument
Execute the save of the current document.
It can be called as
ctx.activeDocument.saveDocument();
Method |
|
Parameter |
Optional {Function} callback - A function invoked if the the document is successfully saved |
Warning
|
If the document is not dirty, the save is not executed, but the callback, if defined, is always invoked. |
Dwp Editor extensions
Méthode Swing DWP editor can be extended in multiple parts by adding custom buttons and executing custom actions, or configuring custom templates to render DWP linked objects.
Location of the DWP Editor extensions.
DWP Editor extensions consist in a Javascript (*.js) file loaded with Swing.
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Namespaces of the DWP editor extensions
DWP Editor extensions are available under the following namespace:
eidosmedia.webclient.actions.dwpeditor
Configure actions
Throughout this document, the example will focus on the development of a simple custom command, named custom.EditDwplink, which will edit a dwp link custom properties.
To add an action, then, it is necessary to follow the steps described below:
1. Add a custom command
The editor extensions follow the same approach of Swing commands.
See the Command configuration paragraph for further details.
Example
eidosmedia.webclient.commands.add({
name: 'change.dwpLink',
isActive: function( ctx ) {
return true;
},
isEnabled: function( ctx ) {
return true;
},
action: function( ctx, params, callbacks ) {
if (callbacks && callbacks.success) {
callbacks.success( /*...*/ );
}
}
});
Tip
|
The details of the implementation of the isEnabled and isActive method will be explained later. |
2. Associated the commands to item toolbar
As a second step, the newly created command must be associated to the item toolbar. To add a button to the item toolbar, the following namespace must be used
eidosmedia.webclient.actions.dwpeditor
The method to be used is addButton(settings). See the following example:
/**
* We now register a new action in the item toolbar using
* the proper namespace. In this case we call the addButton
* method, we define a label and an icon for the button and more important
* we tell the button which command has to trigger using the
* action property
*/
eidosmedia.webclient.actions.dwpeditor.addButton({
action: "change.dwpLink",
label: "Chane Dwp Link",
icon: 'icon-globe'
});
The addButton method requires a single Javascript object ( settings ) as a parameter. This objects need to have the following properties:
-
action: the name of the previously registered command
-
label: the label associated with the command
-
icon: the icon associated with the command.
Implementation of the DWP editor extensions
The editor extensions are powerful because they make use of an editor-related version of the context object. See Basic structure of the Context Object for further details.
As of any command implementation, it is possible to specify the isActive, isEnabled and action methods.
-
isActive method is called in different points according to the editor part it refers to.
-
For the toolbar the method is called after the story is loaded to determine whether a custom action is available.
-
For the components the method is called when a new component is created ( or an existing one is loaded from the story )
-
-
isEnabled method is called in different points according to the editor part it refers to.
-
For the toolbar the method is called whenever the user changes the current selection or cursor position.
-
-
the action is called when the user clicks on the corresponding action button.
Tip
|
All the methods are called with the same Context Object ( ctx ), which is enhanced for the editor and allows to access the active object ( activeObject ). See Basic structure of the Context Object for further details. |
Warning
|
In the Editor context, activeDocument and selection are NOT available. |
Important
|
The Dwp Editor Context Object activeObject contains a subset of methods to access the current dwp link information. These methods are described in the Editor API paragraph. |
Dwp Editor API
getLink
Returns dwp link information.
It can be called as
ctx.activeObject.getLink();
Method |
|
Parameter |
None |
Returns |
|
Example
var info = ctx.activeObject.getLink();
// info is now:
{
"name": "230-Short updates.dwc",
"id": "1.0.36956807",
"type": "EOM::WebContainer",
"modified": {
"type": "DATE",
"format": "YYYYMMDDHHmmss",
"value": "20160323133940"
},
"last_modifier": "Dario",
"locked": {
"type": "DATE",
"format": "YYYYMMDDHHmmss",
"value": "20160323133940"
},
"locker": "",
"webType": "dwc-4stories-230",
"styleSheet": "List",
"templates": [
"Grid",
"List",
"230-4rows1col"
],
"status_info": {
"name": "",
"identifier": "",
"comment": ""
},
"system_attributes": {
"workfolder": "/Globe/Politics",
"template": "",
"templateName": "/SysConfig/Globe/Web/DwcTemplates/public/230/230-4rows1col.dwc",
"summary": "",
"wordCount": "",
"sugCategory": "",
"channel": "Globe-Web",
"storyType": "",
"productInfo": {
"name": "Globe-Web",
"issueDate": "20111005"
},
"priority": ""
},
"system_attributes_xml": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<props><productInfo><name>Globe-Web</name>\r\n<issueDate>20111005</issueDate>\r\n</productInfo>\r\n<workFolder>/Globe/Politics</workFolder>\r\n<templateName>/SysConfig/Globe/Web/DwcTemplates/public/230/230-4rows1col.dwc</templateName>\r\n</props>\r\n",
"channel": "Globe-Web",
"pstate": {
"uuid": "f8c9bd50-ee54-11e0-b51c-542d5e32b6d1",
"suid": "",
"loid": "1.0.36956807",
"retention_time": 0,
"ucount": 44
},
"position": 1
}
getTemplates
Returns the list of dwp link available templates.
It can be called as
ctx.activeObject.getTemplates();
Method |
|
Parameter |
None |
Returns |
|
Example
var templates = ctx.activeObject.getTemplates();
// templates is now:
[{
"value":"Grid",
"selected":false
},{
"value":"List",
"selected":true
}, {
"value":"230-4rows1col"
,"selected": false
}]
getCustomProperties
Returns the list of dwp link custom properties.
It can be called as
ctx.activeObject.getCustomProperties();
Method |
|
Parameter |
None |
Returns |
|
Example
var properties = ctx.activeObject.getCustomProperties();
// properties is now:
[{
"key": "customTitle",
"value": "Alternate title"
}, {
"key": "customDisplayLink",
"value": "yes"
}, {
"key": "customMaxResults",
"value": "10"
}, {
"key": "customTitleColor",
"value": "gray"
}]
setCustomProperties
Set the list of dwp link custom properties.
It can be called as
ctx.activeObject.setCustomProperties(properties);
Method |
|
Parameter |
|
Returns |
None |
Example
var properties = [{
"key": "customTitle",
"value": "Alternate title"
}, {
"key": "customDisplayLink",
"value": "yes"
}, {
"key": "customMaxResults",
"value": "10"
}, {
"key": "customTitleColor",
"value": "gray"
}];
ctx.activeObject.setCustomProperties(properties);
Custom DWP linked item templates
Méthode Swing DWP editor uses HTML templates to render linked objects. It is possible to configure custom templates to be used based on linked item type.
Editor configuration
In DWP editor configuration can be specified which HTML template should be used to render a specific item linked type.
<WebClientConfiguration>
...
<editor>
...
<webpage>
...
<linkedItemTemplates>
<linkedItemTemplate>
<type>EOM::CompoundStory</type>
<template>dwp-story-template.html</template>
</linkedItemTemplate>
<linkedItemTemplate>
<type>EOM::WebContainer</type>
<template>dwp-dwc-template.html</template>
</linkedItemTemplate>
</linkedItemTemplates>
</webpage>
</editor>
<WebClientConfiguration>
Configured template files will be retrieved from
{SWING-APP}/config/templates/dwp/{TEMPLATE-NAME}
and can be configured outside {SWING-APP}, see the paragraph How to configure DWP linked item templates in external folder.
Templating system
Underscore.JS templating system is used to define templates.
The template is rendered with a main object item, which contains all the information about the item.
// item:
{
name: 'ART-stories_block.dwc',
id: '1.0.895409210',
databaseId: '41',
type: 'EOM::WebContainer',
modified: 1524043188,
last_modifier: 'john.doe',
locked: 1542709437,
// empty string if the item is not locked, username of the locker otherwise
locker: '',
webType: 'dwc-element-4row3cols',
styleSheet: null,
// stylesheet configured for the zone and applied as default
defaultStylesheet: 'first',
// selected template
template: 'stories_block',
// available templates
templates: [
{
name: 'stories_block',
path:
'/SysConfig/Globe/WebV2/DwcTemplates/public/1060/stories_block.dwc'
},
{
name: 'one_story_2_heads',
path:
'/SysConfig/Globe/WebV2/DwcTemplates/public/1060/one_story_2_heads.dwc'
}
],
status_info: {
name: '',
identifier: ''
},
// thumbnail preview if available, null otherwise
preview: null,
channel: 'Globe-Web',
owner: 'john.doe',
creator: 'john.doe',
created: 1500474152,
size: 243,
path: '/Globe/WebV2/Web Components/Art/ART-stories_block(1).dwc',
issueDate: '20150903',
system_attributes_xml: 'system attributes XML string',
system_attributes_json: {
// system attributes as json object
},
usage_ticket: 'usage ticket XML string',
usage_ticket_json: {
// usage ticket as json object
},
attributes: 'attributes XML string',
attributes_json: {
// attributes as json object
},
virtual_attributes: 'virtual attributes XML string',
virtual_attributes_json: {
// attributes as json object
},
summary: '',
dwc: {
struct: {
// dwc container structure as json object, see next section
},
links: {
// dwc linked items, see next section
}
},
// Icon class for type
iconType: 'emui-icon-dwp',
// Display label for type
labelType: 'Web Container'
}
DWC
If a linked item is also a container, e.g. a DWC, the object passed to the template will also have a dwc field, containing information about container structure and linked items.
{
// ...
dwc: {
struct: {
type: 'container',
path: 'root',
pageTemplate: 'stories_block',
depth: 0,
slots: 12,
rowspan: 1,
id: '41$1.0.895409210',
channel: 'Globe-Web',
webType: 'dwc-element-4row3cols',
rows: [
{
dimension: 1,
boxesCount: 3,
boxes: [
{
type: 'zone',
path: 'root[r0]-zone0',
depth: 1,
slots: 5,
rowspan: 1,
sequence: 1,
maxItems: 4,
styleSheet: '2col-photo-homepage',
name: 'box',
zoneIndex: 1
}
// ...
]
}
],
dimension: 1
},
links: {
box: [
{
depth: 0,
slots: 0,
rowspan: 0,
sequence: 1,
maxItems: 1,
styleSheet: '1col-photo-tight-homepage',
links: [
{
id: '1.0.740572086',
name: 'Story 1',
databaseId: '41',
channel: 'Globe-Web',
webType: 'story',
position: 1,
type: 'EOM::CompoundStory',
modified: 1522759672,
last_modifier: 'john.doe',
locked: 1524465039,
locker: '',
status_info: {
name: 'NewsFlow/Editing',
identifier: 'RGB(255,0,0)'
},
system_attributes_json: {
// system attributes as json object
}
}
],
zoneIndex: 0
}
// ...
]
}
}
}
Following, a very simple example of a custom template for DWC objects:
<%
function writeLink(link) {
%>
<div><%=link.name%></div>
<%
// ...
}
function writeRow(row) {
%>
<div>DWC row</div>
<ul>
<%
_.each(row.boxes, function(box) {
if (box.type === 'zone' || box.type === 'container') {
%><li>
<div>BOX</div>
<%
var seqObj = _.findWhere(
item.dwc.links[box.name],
{ sequence: parseInt(box.sequence) }
);
_.each(seqObj && seqObj.links, writeLink);
%>
</li><%
}
});
%>
</ul>
<%
}
%>
<div>
<h1>DWC</h1>
<p>Name <%=item.name%></p>
<%
_.each(item.dwc.struct.rows, writeRow);
%>
</div>
How to configure DWP linked item templates in external folder
Custom DWP linked item templates may be made available to Swing application by defining one or more nested components in Swing web context in server.xml. (for further details on Tomcat 9.x Resources configuration, please refer to Resources configuration).
<Context docBase="com.eidosmedia.webclient.web-app"
path="/swing" reloadable="false">
<Resources className="org.apache.catalina.webresources.StandardRoot">
<PreResources
className="org.apache.catalina.webresources.DirResourceSet"
base="/methode/meth01/extension/dwp-templates" readOnly="true"
webAppMount="/config/templates/dwp" />
</Resources>
</Context>
Custom editor panels
With Méthode Swing it’s possible to add custom lateral panels to the Editor. The behaviour and the registration is similar to the Object Panel extension, and allows the user to interact with the Editor and the opened document through the use of the Editor Apis.
Registration of a custom panel
To register a new custom panel, use the following namespace
eidosmedia.webclient.extensions.binder
and its function
add( name, options )
Method |
|
Parameter |
Required |
Returns |
|
The following is a very simple of a working custom panel.
eidosmedia.webclient.extensions.binder.add( "city-panel", {
label: "City info",
icon: 'fa fa-building-o',
template: 'city-panel.html',
isActive: function(ctx) {
return true;
},
headerButtons: [{ name: 'refresh', icon: 'icon-refresh', title: 'toolbar.refresh' }],
init: function(ctx, $container, panelMethods) {
// Load external sources...
},
ready: function(ctx, $container, panelMethods) {
alert("No man is an island, / Entire of itself. / Each is a piece of the continent, / A part of the main. ... / For whom the bell tolls, / It tolls for thee.");
},
closeOnHide: true,
refreshOnShow: true,
callReadyOnChangeItem: false,
/**
* Method called whenever the user clicks on the refresh button.
*/
onRefresh: function(ctx, $container, panelMethods) {
console.error('Clicked on refresh');
},
onClose: function(ctx, $container, panelMethods) {
alert("Don't leave me, please!");
},
/**
* Method called whenever the user changes selection. Available only inside
* the story editor.
*/
onChangedPath : function(ctx, $container, panelMethods, pathInfo) {
console.log(pathInfo);
}
});
Properties and methods of the custom panel
The following paragraphs describe each of the available properties or methods for the custom panel.
label
[Mandatory] {String} label
defines the label visible on the top of the panel when it is selected.
Example
{
// ...
label: "For whom the bell tolls",
// ...
}
icon
[Optional] {String} icon
defines the icon of the custom panels. All the most recent Font Awesome icons are available.
Example
{
// ...
icon: "fa fa-bell",
// ...
}
template
[Mandatory] {String} template
defines the path of the custom panel HTML template. The templates must be put under the following folder:
{SWING-APP}/config/templates/panels/
Tip
|
Swing supports Tomcat 9.x, so custom panels can be configured outside {SWING-APP}. See the paragraph How to configure custom panels in external folder for some tips in how to take advantage of this configuration option. |
Caution
|
the path specified in the template option is relative to the /panels/ folder. |
Example
{
// ...
template: 'bell.html',
// ...
}
offlineAvailable
[Optional] {Boolean} offlineAvailable
determines whether the custom panel is visible or not when the application is offline.
Example
{
// ...
offlineAvailable: true,
// ...
}
localStoryAvailable
[Optional] {Boolean} localStoryAvailable
determines whether the custom panel is visible or not when editing a local story.
Example
{
// ...
localStoryAvailable: true,
// ...
}
isActive( ctx )
[Optional] {Function} isActive
determines whether the custom panel is visible or not. If not specified, the panel is always visible. This function must return a valid Boolean
value to be used. The isActive method has the usual ctx parameter available.
Example
{
// ...
isActive: function( ctx ) {
return ctx.activeObject.getType() === 'EOM::Story';
},
// ...
}
init( ctx, $container )
[Optional] {Function} init
is called as soon as the panel is initialized, after the isActive method has passed. It has the following parameters:
Name | Description |
---|---|
|
The usual Context Object |
|
The jQuery reference to the container node. |
Caution
|
The init method is called before the template has been loaded, so the $container content is actually empty. Do not use it to add event listeners to DOM objects. |
Example
{
// ...
init: function( ctx, $container ) {
// For example, load external sources...
},
// ...
}
ready( ctx, $container )
[Optional] {Function} ready
is called after the panel has been initialized and the template loaded. It has the following parameters:
Name | Description |
---|---|
|
The usual Context Object |
|
The jQuery reference to the container node. |
|
A small set of common methods to be used inside the panel. The only available method is setMessage( message, icon, element ). |
Tip
|
This is the best place to add event listeners to DOM object and to actually implement the whole panel’s logic. |
Example
{
// ...
ready: function( ctx, $container, panelMethods ) {
var _ctx = ctx; // Remember to save the instance, otherwise inside the event it will not work
$container.off('click', '.my-save-button').on('click', '.my-save-button', function() {
_ctx.activeDocument.saveDocument();
});
},
// ...
}
refreshOnShow
[Optional] If set to true, the custom panel will refresh ( and call all the subsequent methods, e.g. ready (not _init) ), any time the custom panel tab is selected by the user ( except for the first time ).
closeOnHide
[Optional] If set to true, the onClose method, if available, will be called any time the custom tab loses focus ( another tab is opened ).
callReadyOnChangeItem
[Optional] If set to true, the custom panel will call the ready method, any time the item selection changes.
onClose
[Optional] Method called when the custom panel is closed. This happens when a document is closed, when a different element is selected, or when the custom tab is hidden ( in case of closeOnHide set to true).
The syntax is the following:
onClose( ctx );
Method |
|
Parameter |
|
Returns |
|
onApplicationStatusChange
[Optional] Method called when the application status change from online to offline or vice versa (triggered only when using the offline functionality).
The syntax is the following:
onApplicationStatusChange(ctx, $container, panelMethods, status);
Method |
|
Parameter |
|
|
The jQuery reference to the container node. |
|
A small set of common methods to be used inside the panel. The only available method is setMessage( message, icon, element ). |
Parameter |
|
Returns |
|
Example
// options object...
{
onApplicationStatusChange: function( ctx, $container, panelMethods, status ) {
// For example, we can check the application status
if (status.isOnline) {
....
}
}
}
onMessage
[Optional] Method called when the application status change from online to offline or vice versa (triggered only when using the offline functionality).
The syntax is the following:
onMessage(ctx, $container, panelMethods, key, message);
Method |
|
Parameter |
|
|
The jQuery reference to the container node. |
|
A small set of common methods to be used inside the panel. The only available method is setMessage( message, icon, element ). |
|
A string that represents the event notification form the editor instance. For example it can be refreshcurrentitem, when changing between one channel copy and another . |
Parameter |
|
Returns |
|
Example
// options object...
{
onMessage(ctx, $container, panelMethods, key, message) {
if ('key' === 'refreshcurrentitem') {
console.log('message contains all the information about the current editing story');
}
}
}
How to configure custom panels in external folder
Additional objects may be made available to Swing application by defining one or more nested components in Swing web context in server.xml. (for further details on Tomcat 9.x Resources configuration, please refer to Resources configuration).
This is an example of the external custom panels configuration.
<Context docBase="com.eidosmedia.webclient.web-app"
path="/swing" reloadable="false">
<Resources
className="org.apache.catalina.webresources.StandardRoot">
<PreResources
className="org.apache.catalina.webresources.DirResourceSet"
base="/methode/meth01/extension/custompanels" readOnly="true"
webAppMount="/config/templates/panels" />
</Resources>
</Context>
Custom insertinfo panels
With Méthode Swing it’s possible to add custom insertinfos to the Editor. The behaviour and the registration is similar to the Object Panel extension.
Registration of a custom insertinfo template
To register a new custom insertinfo template, use the following namespace
eidosmedia.webclient.insertinfo
and its function
add( options )
Method |
|
Parameter |
Required |
Returns |
|
The following is a very simple of a working custom insertinfo template.
(function() {
eidosmedia.webclient.insertinfo.add({
/**
* name of the custom insertinfo implementation
*/
name: "CustomInsertInfo",
/**
* path of the html template relative to the insertinfo folder
*/
template: "customInsertInfo.html",
/**
* An array of insertinfo template configured in the DTX which the custom implementation will be connected.
*/
dtxTemplateName: ['Custom Image Size', 'Custom width-height'],
/**
*
* @param ctx: The usual Context Object. See <<ctx>> for further details. It could be empty
* if only placeholder is inserted.
* @param htmlTemplate: a String containing the html of
* the configured template
*
* @return a jQuery object with the html to show to the user
*/
init: function(ctx, htmlTemplate){
/*
* Elaborate the html and return the
* html to show to the user
*
*/
return $(htmlTemplate);
},
/**
*
* @param ctx: The usual Context Object. See <<ctx>> for further details. It could be empty
* if only placeholder is inserted.
* @param $html: the jQuery representation of the html
* edited by the user
*
* @return an object with key values pairs:
* {
* "uVariable" : "value",
* "uVariable2" : "value2"
* }
*/
getValues: function(ctx, $html){
/**
* Elaborate $html object
**/
var width = $html.find('#custom_width').val();
var height = $html.find('#custom_height').val();
result = {
"uWidth" : width,
"uHeight" : height
}
return result;
}
});
})();
Properties and methods of the custom insertinfo
The following paragraphs describe each of the available properties or methods for the custom insertinfo.
name
[Mandatory] {String} name
defines the name of the custom inserinfo.
{
// ...
name: 'CustomInsertInfo',
// ...
}
dtxTemplateName
[Mandatory] {Array,String} dtxTemplateName
An array of insertinfo template configured in the DTX which the custom implementation will be connected.
Tip
|
String type is still supported only for backward compatibility. |
Example
{
// ...
dtxTemplateName: ['Custom image size', 'Custom width height'],
// ...
}
DTX configuration:
{
<template name="Custom image size" element="fg-photo" mode="inline">
<photo-group>
<fg-photo width="{uWidth}" height="{uHeight}"></fg-photo>
<photo-caption>
<p xpAttributesSource="/*/iptc/caption/text()">
<source xpAttributesSource="/*/iptc/source/text()"><?EM-dummyText Insert caption source?></source>
<?EM-dummyText Insert caption here?>
</p>
<foto-links></foto-links>
</photo-caption>
</photo-group>
</template>
<template name="Custom width height" element="fg-photo" mode="inline">
<photo-group>
<fg-photo width="{uWidth}" height="{uHeight}"></fg-photo>
<photo-caption>
<p xpAttributesSource="/*/iptc/caption/text()">
<source xpAttributesSource="/*/iptc/source/text()"><?EM-dummyText Insert caption source?></source>
<?EM-dummyText Insert caption here?>
</p>
<foto-links></foto-links>
</photo-caption>
</photo-group>
</template>
}
Tip
|
dtxTemplateName can contain the value of the attribute customInsertInfo of the link element of type insert. In this case the custom implementation will be connected to all the tempplate configured. |
{
<insertInfo type="Image" channel="Globe-Web" container="EOM::CompoundStory,EOM::MediaGallery">
<link name="Insert" type="insert" customInsertInfo="customLinkInsert">
<template name="Custom Image One" element="fg-photo" mode="inline">
<photo-group>
<fg-photo width="{uWidth}" height="{uHeight}"></fg-photo>
<photo-caption>
<p xpAttributesSource="/*/iptc/caption/text()">
<source xpAttributesSource="/*/iptc/source/text()"><?EM-dummyText Insert caption source?></source>
<?EM-dummyText Insert caption here?>
</p>
<foto-links></foto-links>
</photo-caption>
</photo-group>
</template>
<template name="Custom Image Two" element="fg-photo" mode="inline">
<photo-group>
<fg-photo width="{uWidth}" height="{uHeight}"></fg-photo>
<photo-caption>
<p xpAttributesSource="/*/iptc/caption/text()">
<source xpAttributesSource="/*/iptc/source/text()"><?EM-dummyText Insert caption source?></source>
<?EM-dummyText Insert caption here?>
</p>
<foto-links></foto-links>
</photo-caption>
</photo-group>
</template
</link>
</insertInfo>
}
Caution
|
all the variables have to be wrapped with brackets (e.g. {uWidth}). |
template
[Mandatory] {String} template
defines the path of the custom panel HTML template. The templates must be put under the following folder:
{SWING-APP}/config/templates/insertinfo/
Tip
|
Swing supports Tomcat 9.x, so custom panels can be configured outside {SWING-APP}. See the paragraph How to configure custom insertinfo in external folder for some tips in how to take advantage of this configuration option. |
Caution
|
the path specified in the template option is relative to the /insertinfo/ folder. |
Example
{
// ...
template: 'customInsertInfo.html',
// ...
}
init( ctx, htmlTemplate )
[Mandatory] {Function} init
is called as soon as the panel is initialized. This function must return a valid jQuery
object to be used.
Name | Description |
---|---|
|
The usual Context Object. See Basic structure of the Context Object for further details. It could be empty if only placeholder is inserted. |
|
htmlTemplate: a String containing the html of the configured template |
Returns |
|
Example
{
// ...
init: function( ctx, html ) {
// Elaborate the html document an return a jQuery html object
var $html = $(html);
return $html;
},
// ...
}
getValues( params, $html )
[Mandatory] {Function} getValues
is called when the user applies the insertinfo. This function must return a valid Object
containing all the variables present in the template.
Name | Description |
---|---|
|
The usual Context Object. See Basic structure of the Context Object for further details. It could be empty if only placeholder is inserted. |
|
The jQuery representation of the html edited by the user. |
Returns |
|
Example
{
// ...
getValues: function( ctx, $html ) {
/*
* Elaborate $html object
*/
var width = $html.find('#custom_width').val();
var height = $html.find('#custom_height').val();
result = {
"uWidth" : width,
"uHeight" : height
}
return result;
},
// ...
}
How to configure custom insertinfo in external folder
Additional objects may be made available to Swing application by defining one or more nested components in Swing web context in server.xml. (for further details on Tomcat 9.x Resources configuration, please refer to Resources configuration).
This is an example of the external custom insertinfo configuration.
<Context docBase="com.eidosmedia.webclient.web-app"
path="/swing" reloadable="false">
<Resources
className="org.apache.catalina.webresources.StandardRoot">
<PreResources
className="org.apache.catalina.webresources.DirResourceSet"
base="/methode/meth01/extension/insertinfo" readOnly="true"
webAppMount="/config/templates/insertinfo" />
</Resources>
</Context>
Channel copy
With Méthode Swing it’s possible to add custom manipulation to the content of a channel copy after his creation.
Registration of a custom manipulation
To register a custom manipulation, use the following namespace
eidosmedia.webclient.extensions.channelCopy
and its function
register( options )
Method |
|
Parameter |
Required |
Returns |
|
The following is a very simple registration for a custom manipulation.
(function() {
eidosmedia.webclient.extensions.channelCopy.register(function( data, callback ) {
// Save the current content of the channel copy
var xmlElaborated = data.xmlContent;
try {
/**
* Save the current content of the channel copy. This variable will be used to make some changes to the current content
*/
var xmlContent = data.xmlContent;
/**
* Save information about the current channel copy. For example the channel name
*/
var copyInfo = data;
/**
* Perform some simple manipulation. In our case add only a new attribute
*/
var xml = $.parseXML(xmlContent);
var $xml = $(xml);
var $doc = $xml.find('doc');
$doc.attr('newattr', 'newvalue');
/**
* Serialize the new xml content
*/
var serializer = new XMLSerializer();
var preValue = xmlElaborated.slice(0, xmlElaborated.indexOf('<doc'));
var result = serializer.serializeToString($doc[0]);
/**
* Save the new xml content
*/
xmlElaborated = preValue + result;
/**
* notify a callback if specified
*/
if (callback) {
callback(xmlElaborated);
}
} catch (ex) {
console.log("Channel copy custom manipulation exception caught", ex);
if (callback) {
callback(xmlElaborated);
}
}
});
})();
Note
|
The function must be have two parameters. The first one contains info about xml content and the channel object info. The second one it’s a callback that must be invoked after the custom manipulation. Wrap all the custom manipulation with a try…catch block otherwise the normal process of the channel copy creation will be not performed. After the custom manipulation the system will perform a validation check of the new content. If the check goes wrong the channel copy will be created with the original content and the user will be notified |
Dashboard
Widget Creation - Méthode Swing
Méthode Swing dashboards are extensible with custom widgets.
This document will introduce the use of Méthode Swing SDK for creating and testing the widgets, as well as describe the correct widget structure and provide a complete example of a custom widget creation.
Widget structure
All the widgets are put inside the following path:
{SWING-APP}/app/widgets/{WIDGET-NAME}
Widgets can be configured outside {SWING-APP}. See the paragraph How to configure widgets in external folder for some tips in how to take advantage of this new configuration option.
As you can see, all the widget provided by Méthode Swing are included in this folder.
Each widget folder must contain the following files:
File name | Description |
---|---|
{WIDGET-NAME} .js |
The JavaScript file defines the widget’s behaviour. |
{WIDGET-NAME} .html |
The file represents the visual template of the widget. |
{WIDGET-NAME} .less |
LESS is a CSS-like language. This file changes the aesthetic appearance of the widget. It is not mandatory. |
Caution
|
It is necessary that the file all have the same name of the folder. It is recommended, although not mandatory, to use lower case characters and, in general, to avoid "unusual" characters. |
Tip
|
DEBUG MODE: by default, all widgets are aggregated into a single widgets.js file at the Tomcat startup. When creating a widget, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that widget will be loaded on every refresh of the page. Note: in debug mode, the widgets are loaded separately and asynchronously; this may occur in a widget not loaded correctly. In this case, simply change tab (e.g. move to "My Area") and back to the Dashboard to have the widget loaded correctly. |
JS file
The widget’s Javascript file should be written as follows:
/*
* Todo List Widget. Used to demonstrate the creation of a custom widget
*/
eidosmedia.webclient.dashboard.widgets.define( {WIDGET-NAME}, function() {
var settings = {
title: 'SOME TITLE',
icon: 'icon-gear'
// Default settings...
};
function onResize() {
// Method called on the windows resize.
};
function loadData() {
// Method called on the widget loading. Used to retrieve the user's data.
};
function updateData() {
// Used to update the widget's template.
};
return {
settings: settings,
onResize: onResize,
loadData: loadData,
updateData: updateData
};
});
Basically, is the widget should call the
eidosmedia.webclient.dashboard.widgets.define
function, with the following parameters:
-
{WIDGET-NAME} : the same name used everywhere else in the widget folder.
-
a function which returns a JavaScript object with a set of mandatory methods as described in the following paragraph.
Each widget has a set of default settings, which can be specified under the settings property of the widget.
When the Dashboard is displayed, the widgets specified in the configuration are initialized. The chain of events continues as follows:
-
First, the dashboard renders the HTML template with status = "init". ( See HTML file for details on how the template is called )
-
Second, the dashboard calls the widget’s loadData (required) method which should load the widget’s data. ( See loadData for details on how the method is called )
-
Within the widget loadData method, the widget should call either the dashboard updateBaseData method ( See updateBaseData for further details ), to let the dashboard know that the loading has finished.
Optionally, it is possible to specify the behaviour when the window is resized. (For example, it can be used to retrive the number of visible objects and change the widget’s rendering accordingly).
See onResize for further details on how to manage the resize.
Required methods for the widget
loadData
loadData is the method called by the Dashboard in order to load the Widget data. It must be declared as follows:
loadData: function( settings, ctx ) { ...
The function is called with one parameter:
-
settings - contains the settings specified in the widget configuration. It is a Javascript object.
-
ctx - the Swing context object. See Context object documentation.
Tip
|
If you specified the settings property in the widget declaration, you can be sure that at least those settings are available. If the user specifies customs settings in Swing configuration, the properties with the same name are overridden by the user configuration. |
Important
|
Within the loadData function, the Javascript context (also known as the this object) is the widgetContext object ( see widgetContext: list of available methods within the widget to know the complete list of methods available ). |
Important
|
It is mandatory that the widget calls the updateBaseData method of the widgetContext object (the this object), otherwise the dashboard as no way of knowing that the widget has finished loading. See updateBaseData for further details. In general, the method updateBaseData must be called with two parameters:
|
This is an example of the TODOLIST widget loadData function.
function loadData( settings, ctx ) {
var widgetContext = this; // save the widget variable.
// Get the user todo list
try {
/* getUserData is one of the available methods,
see the proper documentation below for further details */
widgetContext.getUserData( 'todolist',{
success: function( data ) {
// Process List items.
/* NOTE: IT IS NECESSARY TO CALL THE FOLLOWING METHOD TO LET THE DASHBOARD
KNOW THAT THE WIDGET HAS COMPLETED THE DATA LOADING. */
widgetContext.updateBaseData( settings, data );
},
error: function(xhr, textStatus, errorThrown) {
// Process the error response and show the Widget Error
var error = widgetContext.processErrorResponse(xhr, textStatus, errorThrown);
widgetContext.showError(error);
}
});
} catch (ex) {
widgetContext.showError( { message: ex.message } );
}
};
Optional methods for the widget
updateData
updateData is the method called by the Dashboard after the widget has been loaded. It is generally used to add listeners for events, button clicks, and anything related.
Caution
|
Do not confuse updateData (the widget method) with updateBaseData (the widgetContext method). The widgetContext.updateBaseData() checks if the widget updateData method is available and calls it. |
updateData: function( settings, items, ctx ) { ...
The function is called with some parameters:
-
settings - contains the settings specified in the widget configuration. It is a Javascript object.
-
data - the loaded data. It can be whatever you prefer (an array or JSON object). The data is passed to the widget without further elaboration.
-
ctx - the Swing context object. See Context object documentation.
Important
|
Within the updateData function, the Javascript context (also known as the this object) is the widgetContext object ( see widgetContext: list of available methods within the widget to know the complete list of methods available ). |
This is an example of the updateData function.
function updateData( settings, data, ctx ) {
var widgetContext = this; // save the widget variable.
// add Listeners to the object.
var $widget = widgetContext.getWidgetContainer(); //Obtains the jQuery reference to the widget.
$widget.find('#saveSomething').off('click').on('click', function() {
// do some elaboration of the data...
alert('you clicked me');
});
};
onResize
onResize is the method called by the Dashboard whenever the Browser window is resized. It can be used, for example, to change the number of rows shown.
onResize: function( ) { ...
The method is called without parameters.
Important
|
Within the onResize function, the Javascript context (also known as the this object) is the widgetContext object ( see widgetContext: list of available methods within the widget to know the complete list of methods available ). |
This is an example of the diggfeeds widget onResize function.
function onResize() {
var widgetContext = this;
var ROW_PIXEL_HEIGHT = 65;
var HEADER_PIXEL_HEIGHT = 30;
var calcElements = function() {
var widgetHeight = widgetContext.getHeight();
var totalEl = Math.floor( (widgetHeight - HEADER_PIXEL_HEIGHT) / ROW_PIXEL_HEIGHT);
return totalEl;
};
var totalRow = widgetContext.settings.count;
var totalNewEl = calcElements.call(this);
if ( totalNewEl === totalRow ){
return;
} else {
// New quantity of items.
// Refresh the widget with new items.
this.settings.count = totalNewEl;
loadData.call( widgetContext, widgetContext.settings );
}
};
widgetContext: list of available methods within the widget
The widgetContext object is very important and represents the context ( the this object ) with which the loadData, updateData and onResize methods are called.
It provides a set of common methods which can ( and should ) be used within the widget.
The most important is updateBaseData, which must be called within the widget loadData method as widely described before.
Important
|
Any of these methods can be accessed with the keyword this within the threed common methods ( loadData, updateData and onResize ). It is recommended to save the reference into a variable, to be used within the callback functions. For example: var widgetContext = this; // .... widgetContext.updateBaseData( settings, data ); |
updateBaseData
The method must be called within the loadData method, to let the dashboard know that the widget has finished loading data. It must be called as follows:
widgetContext.updateBaseData( settings, data );
-
settings are the widget’s settings ( provided within the loadData method ), or any setting that you want to pass to the widget.
-
data is the loaded information to be passed to the widget.
Caution
|
This internal method automatically calls the widget updateData method with the same settings, as described above. |
getHeight
Returns the current widget height. Useful in obtaining the widget dimensions for the onResize method.
function onResize() {
var widgetHeight = this.getHeight();
// Some elaboration...
}
getWidth
Returns the current widget width. Useful in obtaining the widget dimensions for the onResize method.
function onResize() {
var widgetWidth = this.getWidth();
// Some elaboration...
}
getWidgetIcon
Returns the current widget icon as specified in the settings. It is often used inside the widget HTML template, as follows.
Tip
|
The result of this.getWidgetIcon() and of this.settings.icon are the same. |
<h1>
<%=settings.title%>
<i class="<%=(widget.getWidgetIcon() || settings.icon)%>"></i>
</h1>
getIcon
getIcon returns the configured icon according to the type.
It is called as follows:
this.getIcon( type );
It returns a string containing the corresponding icon.
var icon = this.getIcon( 'EOM::Story' ); // Returns 'emui-icon-file-text';
// Some elaboration...
addDummy
addDummy fills an array with empty elements.
It is called as follows:
addDummy(data, max)
-
data is the array of items
-
max is the array length.
// data has 30 elements.
this.addDummy( data, 50 );
/**
* Now data has 50 elements. From Index 30 to index 49, the element is
* { empty: true }
*/
execute
execute executes specific supported actions.
Supported actions are:
-
newcontent : opens the "New Content" dialog
-
newmessage : opens the "New Message" dialog
-
newstory : creates a new story document with the default configuration
-
newgallery : creates a new gallery document with the default configuration
It is called as follows:
execute( action, options )
The method does not return anything.
// Open the "new content" dialog.
this.execute( "newcontent" );
getWidgetContainer
The method returns the jQuery reference to the current widget’s container
Tip
|
Use this method to quickly look for DOM elements of your widget. |
var $container = this.getWidgetContainer();
// Search all anchors inside the widget...
var $links = $container.find('a');
getCurrentUser
The method returns a JSON object with the logged user’s properties. See the example to see the returned properties.
var currentUser = this.getCurrentUser();
/** Returns
{
"picture": "/WebClient/user/avatar/user_name?token=1fb301ce-1dc3-4f78-9e2c-0b9c2750ff1b",
"name": "user_name",
"description": "Eidosmedia top class R&D",
"config_folder": "eomfs:/Configurations/Profiles/user_name/Config",
"id": "1.0.417997841",
"fullName": "Ted Mosby",
"team": "Globe_Web",
"phoneNumber": "456",
"mobileNumber": "123",
"twitter": "user_name",
"facebook": "john.doe@r.com",
"role": "Reporter",
"homeEmail": "john.doe.home@r.com",
"businessEmail": "john.doe@r.com2",
"statusMessage": "Status msgsdsadsadas",
"workDir": "workfolder:///Globe/Sport",
"location": "Roma",
"profileDir": "eomfs:/Configurations/Profiles/user_name",
"lastLoggedOn": 1423501287,
"initials": "AP",
"signature": "John",
"system_attributes": "SYSTEM ATTRIBUTES",
"metadata": "",
"homePath": "/Users/user_name",
"admin": true,
"groups": [
{
"name": "Administrators",
"description": "",
"config_folder": "eomfs:/Configurations/Profiles/Administrators/Config",
"profile_folder": "eomfs:/Configurations/Profiles/Administrators",
"categories": [
"EOM::Group",
"EOM::Configuration",
"EOM::Privileges"
],
"isConfiguration": true
}
],
"calendars": [
{
"color": "#0C96D7",
"id": "U00033812843qQO",
"name": "World Cup 2014",
"url": "https://www.google.com/calendar/ical/qlbi1b0rp50vb07rmssnebq694%40group.calendar.google.com/public/basic.ics",
"icon": "icon-bookmark",
"private": false
}
],
"status": "available",
"teams": [
"Globe_Team",
"Globe_Web"
]
}
**/
getUserLocation
Returns the Backbone Model of the user location.
var userLocation = this.getUserLocation();
var latitude = userLocation.get('latitude'); // longitude...
getCurrentLocation
Returns, in a callback, the current location obtained with the browser geolocation API and with Google Maps API.
this.getCurrentLocation( function(location) {
// Do something with location...
// It is an object
/*
{
"latitude": 45.3231,
"longitude": 9.1321
}
*/
});
getConfiguration
Returns an object with specific parts of the configuration. It is called as follows:
var config = this.getConfiguration();
The result is a JSON object with the following properties:
-
config.isCacheEnabled() : returns true if the cache is enabled.
-
config.language : the current user language
-
config.location : the "location" object configured in the config.json file.
getPersistence
Returns the persistence services that enables to perform cached AJAX call.
var persistence = this.getPersistence();
An example from the Digg feeds widget:
// Executes an AJAX call to obtain the DIGG feeds.
persistence.ajax({
emCache: {
disabled: !this.getConfiguration().isCacheEnabled(),
prefix: 'eidosmedia.widget|diggfeeds|',
ttl: 600,
safe: true
},
url : widgetContext.buildUrl( '/ws/widgets/digg/mostDuggFeed', widgetContext.getAppContext() ),
data : request,
success : function(respData) {
if ( count < respData.length ) {
respData = respData.splice(0, count);
}
response = widgetContext.addDummy(respData, count);
// Update the widget data with the standard method, as we don't override it.
widgetContext.updateBaseData( widgetContext.settings, response);
// Add custom listeners.
addListeners.call( widgetContext, response );
},
error : function(xhr, textStatus, errorThrown) {
var error = widgetContext
.processErrorResponse(xhr, textStatus, errorThrown);
widgetContext.showError(error);
}
});
processErrorResponse, showError
The processErrorResponse method is called to create a useful Javascript object, to be used (often) with the showError method.
The showError method is used to display an error message inside the widget container.
processErrorResponse is called as follows:
var errorObj = this.processErrorResponse( xhr, textStatus, errorThrown );
showError is called as follows:
this.showError( errorObj );
The correct usage for processErrorResponse is inside a jQuery AJAX error callback, as seen in the example:
var widgetContext = this;
// Executes an AJAX call to obtain the DIGG feeds.
$.ajax({
url: '',
data: [],
success : function(respData) {
// ...
},
error : function(xhr, textStatus, errorThrown) {
var errorObj = widgetContext
.processErrorResponse(xhr, textStatus, errorThrown);
widgetContext.showError( errorObj );
}
});
showError can be called also without using processErrorResponse, as the example shows:
this.showError( { message: 'Some error details here' } );
translateWidget
translateWidget translates all the HTML inside the widget container. It uses data-i18n attributes to perform the translation.
this.translateWidget();
getUserData, addUserData, removeUserData, setUserData
This methods allow to get, add, remove, and set specific data inside the user’s profile folder.
Syntax is as follows:
this.getUserData( name, callbackSettings ); // Obtains the user data.
this.addUserData( data, name, callbackSettings ); // Add some data to the user's data.
this.removeUserData( data, name, callbackSettings ); // Remove some data from the user's data.
this.setUserData( data, name, callbackSettings ); // Set the user data to some value.
In general, the parameters are:
-
data: the data to add, remove, set from the file.
-
name: the name of the file to be stored in the User profile folder, without the extension (e.g. 'recents', 'todolist', …; it creates a 'recents.json' file into the User profile folder)
-
callbackSettings: a Javascript object with two parameters (success and error, which are both functions), to call the methods asynchronously. If omitted, the call is synchronous.
Examples:
// assuming that, before, we had a 'var widgetContext = this;'...
// GET USER DATA
// Get recents asynchronously (recommended).
this.getUserData('recents', {
success: function( recents ) {
//...
},
error: function(xhr, textStatus, errorThrown) {
var errorObj = widgetContext
.processErrorResponse(xhr, textStatus, errorThrown);
widgetContext.showError( errorObj );
}
});
var recents = this.getUserData('recents'); // Get recents synchronously (not recommended)
// ADD USER DATA (if the file does not exist, it is created).
// add a recent to the list (sync).
this.addUserData( { /* item */ }, 'recents', {
success: function( newRecents ) {
// returns the update list of recents
//...
},
error: function(xhr, textStatus, errorThrown) {
var errorObj = widgetContext
.processErrorResponse(xhr, textStatus, errorThrown);
widgetContext.showError( errorObj );
}
});
// add a recent to the list (async).
var newRecents = this.addUserData( { /* item */ }, 'recents' );
// REMOVE USER DATA
// remove a recent from the list (sync).
this.removeUserData( { /* item identifier */ }, 'recents', {
success: function( newRecents ) {
// returns the update list of recents
//...
},
error: function(xhr, textStatus, errorThrown) {
var errorObj = widgetContext
.processErrorResponse(xhr, textStatus, errorThrown);
widgetContext.showError( errorObj );
}
});
// add a recent to the list (async).
var newRecents = this.removeUserData( { /* item */ }, 'recents' );
// SET USER DATA (overrides the current content with the new one).
// completely sets the new todo list (sync)
this.setUserData( [ {}, {}, }{} ], 'todolist', {
success: function( newTodoList ) {
// returns the update Todo List
//...
},
error: function(xhr, textStatus, errorThrown) {
var errorObj = widgetContext
.processErrorResponse(xhr, textStatus, errorThrown);
widgetContext.showError( errorObj );
}
});
// completely sets the new todo list (async).
var newTodoList = this.setUserData( [ {}, {}, }{} ], 'todolist' );
getPreview
Returns the URL of the server-side generated preview. Useful for Méthode Objects.
var preview = this.getPreview( id ); // e.g. this.getPreview( '0$1.231321421' );
// It returns a valid URL
openPreview
Opens the M&ecute;thode Swing Preview dialog.
this.openPreview( items, options );
The method accepts 2 parameters:
-
items: (object or array), mandatory - a Javascript Object representing the item information returd by query or a folder nativation/ Array including info on the file to load
-
options: (object), not mandatory - a Javascript Object including the preview options.
Important
|
The options object is a Javascript object with the following properties:
|
Example:
this.openPreview( items, { loadObject: true });
HTML file
The HTML template can be as free as desired. The only contraint is that the whole HTML code should be wrapped into a div, such as the following example:
<div>
</div>
The widget can be have a fixed height, a minimum height or can be responsive. This enables the Swing dashboard to adapt according to the screen dimensions.
To have a fixed height widget, specify the height in the style attribute of the div, as follows:
<div style="height:300px;">
<!-- ... -->
</div>
To have a widget with minimum height, specify the min-height in the style attribute of the div, as follows:
<div style="min-height:300px;">
<!-- ... -->
</div>
To have a responsive widget (a widget that occupies the available height), add the class emui-widget-vfill to the div.
<div class="emui-widget-vfill">
<!-- ... -->
</div>
Important
|
Méthode Swing uses Underscore.JS templating system to enhance the user experience. See Underscore.JS for further information, or the box below for some useful tips. Inside the template is then possible to use the Underscore.JS syntax, and use the methods and objects described in the following section. |
Available information inside the HTML template
As described above, the HTML template is called with the Underscore.JS template syntax. Inside the HTML template, it is possible to use the following objects:
-
widget: it contains the same methods described in the widgetContext section above. See widgetContext: list of available methods within the widget section for further details on the available methods.
-
settings: it is a Javascript object containing the widget settings as specified in the configuration.
-
data: contains all the data available to the widget( the ones specified in the updateData and loadData method described above ).
-
status: either 'init' or 'loaded', for the first rendering ( before loadData ) and the last one ( after updateData ).
Sample HTML template
<%
var title = data.title || "";
title = '<a href="#explore?query='+ data.id +'" class="emui-link">' + title +'</a>';
%>
<div class="emui-table-gallery emui-widget-vfill">
<h1>
<i class="<%=(settings.icon || 'icon-picture')%>"></i><%=title%></h1>
<div class="list">
<ul>
<% _.each(data.items, function( item, index ) {
var publishedDate = '',
image = '';
if (!item.empty) {
publishedDate = item.publishedDate;
image = ' style="cursor:pointer;background-image:url(' + widget.getPreview( item.id ) +'); background-size: cover;" data-preview="image" data-preview-index="' + index + '"';
}
var preview = '<div class="image"' + image + '>';
preview += '<div class="info">' + publishedDate +'</div>';
preview +='</div>';
%>
<li><%=preview%></li>
<% }); %>
</ul>
</div>
</div>
LESS file
Less is a CSS pre-processor, meaning that it extends the CSS language, adding features that allow variables, mixins, functions and many other techniques that allow you to make CSS that is more maintainable, themable and extendable.
LESS finally becomes CSS. Please refer to LESS website for further details.
Variable reference
Méthode Swing provides a set of common variables, as well as a set of predefined colors to maintain the coherence with Méthode Swing color palette.
To include the variable file inside your LESS, insert the following line at the beginning:
@import (reference) "../less/widgets-header.less";
Here follows an excerpt of the available variables:
// -------------------------
@black: #000;
@grayDarker: #080808;
@grayDark: #999;
@gray: #bcbcbc; // view background
@grayLight: #d8d8d8; // body background
@grayLighter: #e8e8e8;
@grayLighter2: #f8f8f8;
@grayLightest: #f8f8f8;
@white: #fff;
// Accent colors
// -------------------------
@blue: #a5c0dc;
@blueDark: #4e84bb;
@blueLighter: lighten(@blueDark, 10%);
@green: #77d89a;
@red: #9d261d;
@lightRed: #E24242;
@darkRed: darken(@lightRed, 10%);
@yellow: #ffdb80;
@orange: #ff9f6b;
@pink: #c3325f;
@purple: #7a43b6;
Which can be used as follows:
.selector {
background-color: @blueDark;
}
Again, please refer to LESS website for further details on how to write LESS files.
How to configure widgets in external folder
Additional widgets may be made available to Swing application by defining one or more nested components in Swing web context in server.xml. (for further details on Tomcat 9.x Resources configuration, please refer to Resources configuration).
This is an example of the external widgets configuration.
<Context docBase="com.eidosmedia.webclient.web-app"
path="/swing" reloadable="false">
<Resources
className="org.apache.catalina.webresources.StandardRoot">
<PreResources
className="org.apache.catalina.webresources.DirResourceSet"
base="/methode/meth01/extension/widgets" readOnly="true"
webAppMount="/app/widgets" />
</Resources>
</Context>
Customization
Addition of 3rd parties libs to Swing
In Méthode Swing it is possible to add 3rd-party libraries. Such libraries must be placed under
{SWING-APP}/plugins/libs
All the libraries contained in this folder are loaded separately into Méthode Swing.
Tip
|
The libraries are loaded asynchronously. |
Tip
|
It is suggested to place each library under a specific folder, e.g: {SWING-APP}/plugins/libs/exif/exif.js |
Warning
|
Méthode Swing loads ONLY the Javascript (*.js) files in the folder. |
Warning
|
Méthode Swing has no control over the 3rd parties lib. So, an external library could break the application. Please refer to the log to see which libraries have been loaded. |
New content creation dialog
With Méthode Swing it is possible to override the default creation dialog.
Registration of a new content creation dialog
To register a new content creation dialog, use the following namespace
eidosmedia.webclient.extensions.newcontent
and its function
register( contentTypes, options )
Method |
|
Parameter |
Required |
Returns |
|
Available content types
When registering the dialog, the content type can be chosen among these options:
-
story
-
gallery
-
liveblog
-
webcontainer
-
webpage
-
topic
-
topicplan
Properties of the creation dialog
The following paragraphs describe each of the available properties or methods for the custom panel.
title
[Optional] {String} title
defines the title of the dialog
Example
{
// ...
title: "For whom the bell tolls",
// ...
}
layout
The layout property is optional and allows to have some control on the dialog dimensions. Available values are :
-
fullWidth - the dialog occupies all the screen width.
-
fullHeight - the dialog occupies all the screen height.
-
fullPage - the dialog occupies all the screen width and height.
If necessary, fullWidth and fullHeight properties could be used in addition with width and height properties.
Example
{
// ...
layout: "fullPage"
// ...
}
width, height
If the layout property is not sufficient for your necessities, it is possible to customize the width and the height of the dialog by specifying the respective property.
Example
{
// ...
layout: 'fullWidth',
height: "425px"
// In this case we have a wide dialog with fixed height.
// ...
}
css
If the layout property is not sufficient for your necessities, it is possible to customize all the css properties. It works exactly like jQuery.css method. Please refer to jQuery documentation for further information.
Example
{
// ...
css: {
'fontSize': '12px',
'width': '423px'
}
}
dialogType
Dialog Type can be one of the following values.
-
full - the dialog is completely custom. It should be used when referencing an external url for the content creation. See Full custom dialog configuration documentation.
-
contained - the dialog is custom, but interacts with Methode Swing. The result is a modal that contains your custom HTML, but has the "Create" button as part of Swing. See Contained custom dialog configuration documentation.
-
template - the dialog is the standard Methode Swing dialog, but the template choice part is custom. See Template custom dialog configuration documentation.
-
tab - the dialog is the standard Methode Swing dialog, template and shape tabs are standard but It’s possible to add one ore more custom tabs. See Tab custom dialog configuration section
Example
{
// ...
dialogType: "full"
// ...
}
Full custom dialog configuration
A "full" custom dialog should be used when the customer has an indipendent Object Creation tool available on another website. The "full" dialog has minimal interaction with Swing, and merely opens an external URL in an iframe.
To activate the "full" custom dialog, dialogType property must be valued at full.
Configuration of a proxy
To allow the use of your external url inside Swing, it is necessary to use a Proxy.
Méthode Swing uses proxies to communicate to external services. This is necessary due to the Same-Origin Policy used by modern browsers.
The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. Same-origin Policy is used as a means to prevent some of the Cross-site Request Forgery attacks.
Proxies can be configured in Méthode Swing.
<!-- other configuration -->
<proxies>
<proxy>
<name>[PROXY-NAME]</name> <!-- e.g. resourcespace -->
<targetUri>http://192.168.203.129/resourcespace/plugins/api_search/</targetUri> <!-- e.g. destination target Uri -->
<useTemplate>false</useTemplate>
</proxy>
</proxies>
Important
|
The useTemplate param allows to use templates to build the URL. The following is an example of url which uses templates.
The new proxed URL must be called with ALL the parameters in its querystring, e.g. http://swing/[PROXY-NAME]/users/get?_port=8080&id=userID Note: if the parameter is missing, the URL will return an HTTP 500 error. Note: due to the nature of the Template Servlet, in this mode it is not possible to pass arrays as querystrings ( i.e. more than one querystring parameter with the same name ). |
Configuration of the url
To point to the external url, it is mandatory to configure the url option. Please notice that, considering that you have just configured the correct proxy for your application, the url will be actually a subset of the Swing url.
{ // ... url: 'http://localhost:9797/swing/newcontentproxy/index.html0 // ... }
Closing the dialog
The "full" custom dialog actually includes your custom external url inside a Swing modal dialog. Since there is no interaction between it and your code, the only way for the customer to close the Swing dialog is to put the following code inside their application.
// Creation code of your application..
// At the end of it, put the following code
if (window.top.eidosmedia) {
window.top.eidosmedia.closeCurrentDialog();
}
Accessing the Context Object
The "full" custom dialog actually includes your custom external url inside a Swing modal dialog. Since there is no interaction between it and your code, the only way for the customer to access the Swing context (with all the limitation of being in another iframe), is the following.
// Creation code of your application..
// At the end of it, put the following code
if (window.top.eidosmedia) {
var CTX = window.top.eidosmedia.getCTX();
// Get current user...
var currentUserName = CTX.getCurrentUser().getName();
// All methods of the CTX are available (such as getChannels, getWorkfolders, getTemplates)
}
Full example
eidosmedia.webclient.extensions.newcontent.register( ['story'], {
dialogType: 'full',
title: 'Custom story creation dialog',
url: 'http://localhost:8080/swing/testcustomcontent/index.html',
layout: 'fullPage'
});
The code above will let Swing understand that the operation is done.
Important
|
This will only work if the external url is Proxied inside Swing using the Proxy configuration. |
Contained custom dialog configuration
The contained dialog is used in other to insert custom HTML in the New Content Creation dialog of Swing. The contained dialog is wrapped inside Swing, and uses a custom template. Inside the dialog, it is possible to use the Context Object to retrieve important information. See Context Object (ctx parameter) for further information.
The dialog can be configured with additional properties.
template
[Optional if dialogType is 'full'] {String} template
defines the template of the dialog. The template is placed under the following path:
{SWING}/config/templates/newcontent/
Tip
|
Swing supports Tomcat 9.x, so custom panels can be configured outside {SWING-APP}. See the paragraph How to configure custom dialog in external folder for some tips in how to take advantage of this configuration option. |
The template is an HTML file, and there is maximum liberty in its content. Please refer to Contained custom dialog configuration documentation for further information.
Example
{
// ...
template: "mycustomnewcontent.html",
// ...
}
showCreateButton
{Boolean} showCreateButton
if true, the Create button is shown in the Modal footer, and the creation process is managed by Swing by calling the getCreationInfo method when the user clicks on the button.
Example
{
// ...
showCreateButton: true,
// ...
}
Full example
eidosmedia.webclient.extensions.newcontent.register( ['story'], {
template: 'newcustom.html',
dialogType: 'contained',
title: 'Custom story creation dialog',
layout: 'fullPage',
showCreateButton: true,
postFillForm: function(ctx, $dialog) {
// There are some APIs available to list channels, teams,
// access the metadata of the user, and so on...
},
getCreationInfo: function( ctx, dialog, callback ) {
var $dialog = $(dialog);
var team = $dialog.find('[data-field-type="team"]').val();
// ...
callback({
team: team,
channel: channel,
// ...
})
}
});
Methods of the creation dialog in Full or Contained mode
postFillForm
Method called when the dialog and its custom html has been loaded. It can be used to add custom listeners to buttons, make some elaborations, etc..
The syntax is the following:
postFillForm( ctx, dialog );
Method |
|
Parameter |
|
Parameter |
|
Returns |
|
Example
// options object...
{
postFillForm: function( ctx, dialog ) {
var $dialog = $(dialog);
var _teams = ctx.getTeams();
var teamHtml = _.map( _teams, function(t) {
return '<option>' + t.name + '</option>';
});
$dialog.find('[data-field-type="team"]').html( _.map() );
$('.my-custom-button', dialog ).on('click', function() {
// do something here
});
}
}
getCreationInfo
Method called when the user clicks on the "Create" button. In this method, the dialog should return a JSON object with all the information necessary to call the REST api /object/create.
Important
|
This will be called in the following circumstances:
|
The syntax is the following:
getCreationInfo( ctx, dialog, callback );
Method |
|
Parameter |
|
Parameter |
|
Parameter |
|
Returns |
|
Example
// options object...
{
getCreationInfo: function( ctx, dialog, callback ) {
var $dialog = $(dialog);
var team = $dialog.find('[data-field-type="team"]').val();
// ...
callback({
team: team,
channel: channel,
// ...
})
}
}
onCreate
Method called when the user clicks on the "Create" button and the getCreationInfo method is not defined. In this method, the dialog should return a JSON object with the information of the created content.
Important
|
This will be called in the following circumstances:
|
The syntax is the following:
onCreate( ctx, dialog, callback );
Method |
|
Parameter |
|
Parameter |
|
Parameter |
|
Returns |
|
Example
// options object...
{
onCreate: function( ctx, dialog, callback ) {
var $dialog = $(dialog);
var team = $dialog.find('[data-field-type="team"]').val();
// ...
callback({
id: content.id,
name: content.name,
// ...
})
}
}
Template custom dialog configuration
The template custom dialog overrides the template / shape choice panel inside the standard "New Content" dialog of Swing. Inside the dialog, it is possible to use the Context Object to retrieve important information or use a set of APIs to interact with the creation dialog (see below). See Context Object (ctx parameter) for further information on CTX object.
Important
|
Starting from version 5.2020.09 the new content creation dialog system has been renewed and redesigned in React with a modern, responsive UI. Due to this change, legacy template dialog customisations won’t work anymore. Template custom dialog is still supported but a refactoring of existing customization is required. |
Template configuration object example
{
// ...
dialogType: "template",
template: "mycustomnewcontent.html",
createContent: function ({inputs, formData, dataConfig, callbacks}) {},
renderTemplate: function ({loading, error, templates, ctx, dataConfig, callbacks}) {},
renderShape: function ({loading, error, shapes, ctx, dataConfig, callbacks}) {},
// ...
}
Configuration properties
dialogType
[Mandatory] {String}
Set to "template" for template custom dialog configuration
template
[Mandatory] {String}
defines the template of the dialog. The template is placed under the following path:
{SWING}/config/templates/newcontent/
Tip
|
Swing supports Tomcat 9.x, so custom panels can be configured outside {SWING-APP}. See the paragraph How to configure custom dialog in external folder for some tips in how to take advantage of this configuration option. |
The template is an HTML file, and there is maximum liberty in its content.
createContent
[Optional] {Function}
If defined, the process to create the content is completely customizable. This function is called on "Submit" button press. If this function is not defined the content is created using the default dialog creation flow.
Name |
Type |
Description |
|
{Object} |
Contains the full data set for the inputs controllers (teams, channels, editions, inserts, workfolders, …) |
|
{Object} |
Contains the data currently set by the user or programmatically using the `setFormData`api |
|
{Object} |
Contains the full data set about configurations |
|
{Object} |
Contains a set of functions api to comunicate with the dialog. See the following table for details |
Name |
Description |
Parameters |
|
Set an error status for the dialog, It’s possible set an error status for a particular component or display an error alert to the user |
{String or Object} A string to display an error alert or an object {input, message} to set an input field in status error |
|
Clear the error status for the dialog |
|
|
Set\unset the dialog in a loading status |
{Boolean} Loading status |
|
Close the dialog |
renderTemplate
{Function} renderTemplate
is called multiple times: whenever the dialog is loading data (with loading
parameter true), when there is an error (with error
parameter defined) or when templates data has been retrieved (loading
false, error
undefined, templates
array filled).
Name |
Type |
Description |
|
{Boolean} |
True if the dialog is in loading state to retrieve the templates |
|
{String} |
If an error occured contains the error otherwise will be |
|
{Array} |
Contains the retrieved set of templates based on dialog form inputs. |
|
{Object} |
The CTX object |
|
{Object} |
as described above |
|
{Object} |
Contains a set of functions api to comunicate with the dialog. See the following table for details |
Name |
Description |
Parameters |
|
Set the chosen template |
{Object} template |
|
as described above |
as described above |
|
Retrieve the data set by the user. Reserved string paramater values are 'name', 'issueDate', 'team', 'edition', 'insert', 'channel', 'location', 'workfolder', 'template', 'shape', 'createTopicFrom', 'conflictResolutionMode', 'moderation', 'summary' or the custom data key stored using |
{String} Form data key |
|
Store a custom data to be retrieved using |
{String} Form data key, {Any} Form data value. Be carefully to not override the reserved key values listed in |
renderShape
{Function} renderShape
same behavior of the renderTemplate
function but with shapes data. setShape
function is provided in callbacks
parameter to set the chosen shape.
Full example
The full customization example code can be found in {SWING}/config/templates/newcontent/
installation folder. See files newcontentTemplate(.js | .html | .css)
.
eidosmedia.webclient.extensions.newcontent.register(["story"], {
dialogType: "template",
template: "newcontent.html",
// Optional. Define it only if you need to take control of create content process
createContent: function ({ inputs, formData, dataConfig, callbacks }) {
const { setError, resetErrors, setLoading, close } = callbacks;
// ...
},
renderTemplate: function ({
loading,
error,
templates,
ctx,
dataConfig,
callbacks,
}) {
const {
setTemplate,
setError,
resetErrors,
setLoading,
getFormData,
setFormData,
} = callbacks;
// ...
},
renderShape: function ({
loading,
error,
shapes,
ctx,
dataConfig,
callbacks,
}) {
const { setShape } = callbacks;
// ...
},
});
Tab custom dialog configuration
Using tab custom dialog configuration is possible to add one or more custom tabs inside the standard "New Content" dialog of Swing along with the standard Template and Shape tabs. Inside the tabs you can use the Context Object to retrieve important information or use a set of APIs to interact with the creation dialog (see below). See Context Object (ctx parameter) for further information on CTX object.
Tab configuration object example (2 tabs)
{
// ...
dialogType: "tab",
title: { tab1: "Title Tab", tab2: "Title Tab 2" }
template: { tab1: "mycustomtab1.html", tab2: "mycustomtab2.html" },
createContent: function ({inputs, formData, dataConfig, callbacks}) {},
renderTab: {
tab1: function ({ inputs, formData, ctx, dataConfig, callbacks }) {},
tab2: function ({ inputs, formData, ctx, dataConfig, callbacks }) {}
}
}
Please note that title, template and renderTab are objects having keys tab1, tab2. These keys are used to indentify a specific tab setup. Any string can be used execept the reserved strings template and shape.
Configuration properties
dialogType
[Mandatory] {String}
Set to "tab" for tab custom dialog configuration
title
[Mandatory] {Object}
defines the title for the custom tabs.
template
[Mandatory] {Object}
defines the template for the custom tabs. The templates are placed under the following path:
{SWING}/config/templates/newcontent/
Tip
|
Swing supports Tomcat 9.x, so custom panels can be configured outside {SWING-APP}. See the paragraph How to configure custom dialog in external folder for some tips in how to take advantage of this configuration option. |
The template is an HTML file, and there is maximum liberty in its content.
createContent
[Optional] {Function}
If defined, the process to create the content is completely customizable. This function is called on "Submit" button press. If this function is not defined the content is created using the default dialog creation flow.
Name |
Type |
Description |
|
{Object} |
Contains the full data set for the inputs controllers (teams, channels, editions, inserts, workfolders, …) |
|
{Object} |
Contains the data currently set by the user or programmatically using the `setFormData`api |
|
{Object} |
Contains the full data set about configurations |
|
{Object} |
Contains a set of functions api to comunicate with the dialog. See the following table for details |
Name |
Description |
Parameters |
|
Set an error status for the dialog, It’s possible set an error status for a particular component or display an error alert to the user |
{String or Object} A string to display an error alert or an object {input, message} to set an input field in status error |
|
Clear the error status for the dialog |
|
|
Set\unset the dialog in a loading status |
{Boolean} Loading status |
|
Close the dialog |
renderTab
{Function} renderTab
can be called multiple times: at tab opening, whenever the dialog is loading data (with loading
parameter true), when there is an error (with error
parameter defined) or when input data changes.
Name |
Type |
Description |
|
{Object} |
Contains the full data set for the inputs controllers (teams, channels, editions, inserts, workfolders, …) |
|
{Object} |
Contains the data currently set by the user or programmatically using the `setFormData`api |
|
{Object} |
The CTX object |
|
{Object} |
as described above |
|
{Object} |
Contains a set of functions api to comunicate with the dialog. See the following table for details |
Name |
Description |
Parameters |
|
Set the chosen template |
{Object} template |
|
as described above |
as described above |
|
Retrieve the data set by the user. Reserved string paramater values are 'name', 'issueDate', 'team', 'edition', 'insert', 'channel', 'location', 'workfolder', 'template', 'shape', 'createTopicFrom', 'conflictResolutionMode', 'moderation', 'summary' or the custom data key stored using |
{String} Form data key |
|
Store a custom data to be retrieved using |
{String} Form data key, {Any} Form data value. Be carefully to not override the reserved key values listed in |
Full example
The full customization example code can be found in {SWING}/config/templates/newcontent/
installation folder. See files newcontentTab(.js | .html | .css)
.
eidosmedia.webclient.extensions.newcontent.register(["story"], {
template: { tab1: 'newcontenttab.html', tab2: 'newcontenttab2.html' },
title: { tab1: 'My first custom tab', tab2: 'Custom Shape' },
dialogType: 'tab',
// Optional. Define it only if you need to take control of create content process
createContent: function ({ inputs, formData, dataConfig, callbacks }) {
const { setError, resetErrors, setLoading, close } = callbacks;
// ...
},
renderTab: {
tab1: function({ inputs, formData, ctx, dataConfig, callbacks }) {
const { setTemplate, setError, resetErrors, setLoading, getFormData, setFormData } = callbacks;
},
tab1: function({ inputs, formData, ctx, dataConfig, callbacks }) {}
}
});
HTML Template
Swing provides a sample template inside the following folder.
{SWING}/config/templates/newcontent/
Please use it as a reference. In general, no restriction is given to the HTML code.
Context Object (ctx parameter)
Inside the different methods in the New Content Dialog configuration, the Context Object is available. See Context object documentation for reference.
Furthermore, the New Content Dialog context object has several specific methods available.
getTemplates
Return the list of templates, given some options. See the example for all the options available.
Syntax
ctx.getTemplates( options, callback );
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Required |
A set of options to retrieve the templates. See the example for all the options available. |
|
{Function} |
Required |
A callback function. See Callback definition for further information. |
Returns
Name |
Type |
Description |
|
{Array} |
An array with a list of templates |
Example
{
// ...
postFillForm: function(ctx, dialog, extraInfo) {
var options = {
workfolder: '/Globe/Art', // MANDATORY
type: 'topic' // optional, the template type for filtering.
// Could be "story", "gallery", "prs", "pkg"
}
// Synchronous way...
try {
var templates = ctx.getTemplates(options);
} catch(ex) {
// manage error here
}
// Better way...
ctx.getTemplates(options, function(err, data) {
var $dialog = $(dialog);
if (err) {
$dialog.find('.error-message').html(err.message).show();
return;
}
// data is an array of templates...
/* Like this:
[
{
"id": "199$1.0.21025653",
"name": "bio",
"type": "EOM::Story",
"contentType": "story",
"path": "/SysConfig/Globe/Templates/bio.xml",
"isDefault": false,
"dir": "/SysConfig/Globe/Templates",
"system_attributes": {
"workfolder": "",
"templateName": "",
"summary": "",
"wordCount": "",
"sugCategory": "",
"channel": "",
"edition": "",
"storyType": "",
"productInfo": {
"name": "",
"issueDate": ""
}
}
}, ...
]
*/
});
}
// ...
}
Note
The method can also be called synchronously, but this usage is not recommended.
getChannels
Return the list of channels, given some options. See the example for all the options available.
Syntax
ctx.getChannels( options, callback );
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Required |
A set of options to retrieve the channels. See the example for all the options available. |
|
{Function} |
Required |
A callback function. See Callback definition for further information. |
Returns
Name |
Type |
Description |
|
{Array} |
An array with a list of channels |
Example
{
// ...
postFillForm: function(ctx, dialog, extraInfo) {
var options = {
showTemplates: truem
showInserts: true,
showCalendar: true
}
// Synchronous way...
try {
var channels = ctx.getChannels(options);
} catch(ex) {
// manage error here
}
// Better way...
ctx.getChannels(options, function(err, data) {
var $dialog = $(dialog);
if (err) {
$dialog.find('.error-message').html(err.message).show();
return;
}
// data is an array of channels...
/* Like this:
[
{
"id": "199$0",
"name": "Globe-Print",
"displayName": "Globe-Print",
"type": "print",
"isDefault": false,
"editions": [
{
"name": "EUROPE",
"_default": false
},
{
"name": "USA",
"_default": false
},
{
"name": "ASIA",
"_default": false
}
],
"inserts": [
"Insert One",
"Insert Two"
],
"calendar": {
//...
},
"cobaltSite": false
}
]
*/
});
}
// ...
}
Note
The method can also be called synchronously, but this usage is not recommended.
getTeams
Return the list of teams, given some options. See the example for all the options available.
Syntax
ctx.getTeams( options, callback );
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Required |
A set of options to retrieve the teams. See the example for all the options available. |
|
{Function} |
Required |
A callback function. See Callback definition for further information. |
Returns
Name |
Type |
Description |
|
{Array} |
An array with a list of basefolders |
Example
{
// ...
postFillForm: function(ctx, dialog, extraInfo) {
var options = {
showChannels: truem
}
// Synchronous way...
try {
var teams = ctx.getTeams(options);
} catch(ex) {
// manage error here
}
// Better way...
ctx.getTeams(options, function(err, data) {
var $dialog = $(dialog);
if (err) {
$dialog.find('.error-message').html(err.message).show();
return;
}
// data is an array of teams...
});
}
// ...
}
Note
The method can also be called synchronously, but this usage is not recommended.
getWorkfolders
Return the list of workfolders, given some options. See the example for all the options available.
Syntax
ctx.getWorkfolders( options, callback );
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Required |
A set of options to retrieve the workfolders. See the example for all the options available. |
|
{Function} |
Required |
A callback function. See Callback definition for further information. |
Returns
Name |
Type |
Description |
|
{Array} |
An array with a list of workfolders |
Example
{
// ...
postFillForm: function(ctx, dialog, extraInfo) {
var options = {
team: 'Globe_Team', // one of them is necessary, according to your requirements
contentType: 'story'
}
// Synchronous way...
try {
var workfolders = ctx.getWorkfolders(options);
} catch(ex) {
// manage error here
}
// getBaseFolder way...
ctx.getWorkfolders(options, function(err, data) {
var $dialog = $(dialog);
if (err) {
$dialog.find('.error-message').html(err.message).show();
return;
}
// data is an array of workfolders...
});
}
// ...
}
Note
The method can also be called synchronously, but this usage is not recommended.
getSelectedOptions
Return the data info related to the selected topic item.
Syntax
ctx.getSelectedOptions();
Returns
Name |
Type |
Description |
|
{Object} |
A JSON object with topic item properties |
Example
{
// ...
postFillForm: function(ctx, dialog, extraInfo) {
const options = ctx.getSelectedOptions();
/* options like this:
{
channel: "Globe-Web/English",
edition: "English",
issueDate: "20200901", name: "USA 2020 Elections.xml",
workfolder: "/Globe/Politics"
}
*/
}
// ...
}
createDocument
Create a new document with the options passed. The newly created document is automatically opened.
Syntax
ctx.createDocument( options, callback );
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Required |
A set of options to create the document. See the details in the box belox. |
|
{Function} |
Required |
A callback function. See Callback definition for further information. |
Returns
Name |
Type |
Description |
|
{Object class} |
An instance of the Object Class. See Object class methods for further information on the methods available. |
Options
The request to the createDocument method is a JSON with the following properties:
-
name: the file name. It must end with .xml for stories or .pkg for topics.
-
template: the path of the source template. It is mandatory
-
team: the base team
-
channel: the document channel
-
insert: the information on inserts
-
edition: the edition
-
issueDate: if available, the issueDate in the format YYYYMMDD.
-
workfolder: the workfolder of the document
-
path: the document path
-
workStatus: optional to specify the status of the document. The workStatus must be a valid status, reachable from the initial status in which the document is created.
-
attributes: optional to specify the metadata of the document
-
newObjOption: a number describing the behaviour in case of files with the same name. Values are the following:
-
0 - An error is thrown
-
1 - The new file is automatically renamed
-
2 - The file is replaced
-
3 - A new version is created
-
Example
{
// ...
postFillForm: function(ctx, dialog, extraInfo) {
var _ctx = ctx;
// With your custom button...
$(dialog).on('click', '.create-button', function(event) {
var request = {
"name": "TestCreateCustom2.xml",
"template": "/SysConfig/Globe/Templates/story-external.xml",
"team": "Globe_Team",
"channel": "Globe-Print",
"insert": "Insert One",
"attributes": "<test>true</test>",
"workStatus": "NewsFlow/Editing",
"edition": "EUROPE",
"issueDate": "20170713",
"workfolder": "/Globe/Art",
"newObjOption": 2,
"path": "workfolder:///Globe/Art"
};
ctx.createDocument(request, function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
// The document is automatically opened
// But I can still retrieve its info
var newId = Obj.getId()
});
});
// ...
}
Note
The method cannot be called synchronously.
createTopic
Create a new topic with the structure passed. Please refer to the REST API documentation for further info: Topic Creation documentation. Please notice that in this case the document is NOT opened.
Syntax
ctx.createTopic( options, callback );
Parameters
Name |
Type |
Required |
Description |
|
{Object} |
Required |
A set of options to create the document. See the details in the box belox. |
|
{Function} |
Required |
A callback function. See Callback definition for further information. |
Returns
Name |
Type |
Description |
|
{Object class} |
An instance of the Object Class. See Object class methods for further information on the methods available. |
Example
{
// ...
postFillForm: function(ctx, dialog, extraInfo) {
var _ctx = ctx;
// With your custom button...
$(dialog).on('click', '.create-button', function(event) {
var request = {
"containerType":"TOPIC",
"source":"",
"attributes": "<test>true</test>",
"workStatus": "NewsFlow/Editing",
"path":"/TestTopicPlan/Topic",
"name":"I giochi a Rio",
"description":"I Giochi della XXXI...",
"correlates" : [ { "containerType": "CORRELATES", "source" : "loid:9$2.0.798314409", "correlationType": "RELATED_IMAGE" }],
"children":[
{
"containerType":"TOPICITEM",
"name":"La città di Rio De Janero",
"dueDate":"20160501",
"size":"2 colonne",
"channel":"Globe-Web",
"author":"Mario Rossi",
"comment":"This is a topic item comment",
"priority":"TASK_PRIORITY_NORMAL",
"content":"picture",
"workFolder":"/Globe/Sport",
"assignment":"test,prova1",
"asset":"",
"correlates" : [ { "containerType": "CORRELATES", "source" : "loid:9$2.0.798137329", "correlationType": "RELATED_IMAGE" }],
"children":[
{
"containerType":"TOPICSUBITEM",
"name":"Rio - Foto",
"dueDate":"20160501",
"size":"2 colonne",
"channel":"Globe-Web",
"author":"Mario Rossi",
"comment":"This is a sub topic item comment",
"priority":"TASK_PRIORITY_LOW",
"content":"PICTURE",
"workFolder":"/Globe/Sport",
"assignment":"test,prova1",
"asset":{
"source":"loid:9$2.0.795001757"
}
},
{
"containerType":"DIVIDER",
"source":"",
"name":"SUBITEM DIVIDER",
"font":{
"bold":true,
"color":"2558080",
"faceName":"Tahoma",
"italic":"false",
"lineThrough":"false",
"size":"14",
"underline":"true"
}
},
{
"containerType":"TOPICSUBITEM",
"name":"Rio - Foto",
"dueDate":"20160501",
"size":"2 colonne",
"channel":"Globe-Web",
"author":"Mario Rossi",
"comment":"This is a sub topic item comment",
"priority":"TASK_PRIORITY_LOW",
"content":"PICTURE",
"workFolder":"/Globe/Sport",
"assignment":"test,prova1",
"asset":{
"source":"loid:9$2.0.795001794"
}
}
]
},
{
"containerType":"DIVIDER",
"source":"",
"name":"SUBTOPIC DIVIDER",
"font":{
"bold":true,
"color":"000000",
"faceName":"Tahoma",
"italic":"false",
"lineThrough":"false",
"size":"14",
"underline":"true"
}
},
{
"containerType":"TOPICITEM",
"name":"Le zone dei giochi",
"dueDate":"20160501",
"size":"2 colonne",
"channel":"Globe-Web",
"author":"Mario Rossi",
"comment":"This is a topic item comment",
"priority":"TASK_PRIORITY_NORMAL",
"content":"picture",
"workFolder":"/Globe/Sport",
"assignment":"test,prova1",
"asset":"",
"children": []
}
]
};
ctx.createTopic(request, function(err, Obj) {
if (err) {
ctx.showError(err);
return;
}
// The document is automatically opened
// But I can still retrieve its info
var newId = Obj.getId()
});
});
// ...
}
Note
The method cannot be called synchronously.
Callback definition
Important
|
The callback parameter, when specified, is always defined as follows:
|
Obtain a usable Context Object
For several reason, it could be necessary to use the Swing Context Object. In an iframed custom template, the only way to obtain it is to call
window.top.eidosmedia.webclient.app.getCurrentDocumentContext()
which returns an available CTX. Please refer to Context object documentation for further reference.
How to configure custom dialog in external folder
Additional objects may be made available to Swing application by defining one or more nested components in Swing web context in server.xml. (for further details on Tomcat 9.x Resources configuration, please refer to Resources configuration).
This is an example of the external custom panels configuration.
<Context docBase="com.eidosmedia.webclient.web-app"
path="/swing" reloadable="false">
<Resources
className="org.apache.catalina.webresources.StandardRoot">
<PreResources
className="org.apache.catalina.webresources.DirResourceSet"
base="/methode/meth01/extension/newcontent" readOnly="true"
webAppMount="/config/templates/newcontent" />
</Resources>
</Context>
Preview extensions
Preview API can be found under the following namespace:
eidosmedia.webclient.extensions.preview
In such namespaces, three methods are available: openPreview, addContentLoader. They are explained in detail in the following paragraphs.
Location of the custom Preview extensions.
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Open preview
To open the preview of an object, you must call the following method:
eidosmedia.webclient.extensions.preview.openPreview( item, options );
The method accepts 2 parameters:
-
item: (object), mandatory - a Javascript Object with item information.
-
options: (object), not mandatory - a Javascript Object including the preview options.
Important
|
The options object is a Javascript object with the following properties:
|
Example:
eidosmedia.webclient.extensions.preview.openPreview({ id: '0$1.0.236095983' });
Add custom content
Custom content can be loaded in the lazyLoad part of the preview. To add a custom content, simply call the addCustomContent method as follows:
eidosmedia.webclient.extensions.preview.addCustomContent( name, action );
For example:
eidosmedia.webclient.extensions.preview.addCustomContent( 'mycustomextension', function( ctx, callback ) {
ctx.activeObject.getMetadata(function(metadata) {
var videoUrl = $(metadata).find('WireURL').text();
// We are calling the preview back with the value we want.
callback( videoUrl );
});
});
The method has two (mandatory) parameters:
-
name : the name of the custom content
-
action : the function to be called.
The action function has two parameters, ctx, which is the Context Object, and callback, which is the function to call back the preview with the desired value. See Basic structure of the Context Object for further details.
NOTE: to load your custom extension within the preview, simply add the following tag at the beginning of the preview template:
<load id="mycustomextension"/> // Replace mycustomextension with your extension's name
and use the following syntax to call your customextension within the preview:
Result: <%=data.mycustomextension%> // Prints "Result: custom extension! Preview item id: 0$123452324"
Add custom actions
It is possible to add custom actions in preview. To register an action, see how to add a custom command in Swing.
Tip
|
The action will be passed the Context Object as the first parameter. See Basic structure of the Context Object for further details. |
Tip
|
To add your custom action within the preview, you need to used the data-emaction parameter as follows: <button data-emaction="mycustomaction">Click me, I'm useful!</button> // Prompts " You clicked on this custom action! ... " |
Tip
|
You can use the loaded information when calling an action. For example, if you want to show and use the userInfo within a custom action, you can do as follows:
and, in the plugin folder,
|
Uploader extensions
Méthode Swing uploader can be extended with custom behaviour.
Location of the Uploader extensions
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Image data extractor
When uploading files to Swing it’s possible to define a image data extractor function which will be called before the load the default metadata from server.
Registration
Important
|
Image data extractor implementation with eidosmedia.webclient.extensions.objectpanel.addImageDataExtractor method is not supported anymore. |
Image data extractor extension was moved to object panel customizations.
Please refer to the onImageProcessing method on Object Panel documentation for further information.
Filename Validation
When uploading files to Swing it’s possible to define a filename validation function which will be called before the actual files are transfered to the server. To add a filename validator, it is necessary to register it inside Swing by calling the following Javascript function, inside your Javascript file:
eidosmedia.webclient.extensions.uploader.validateFilename = function( filename ){}
Parameters
-
"filename": The filename to validate.
Note
|
The function must the return the new filename. |
Implementation Example
eidosmedia.webclient.extensions.uploader.validateFilename = function( filename ) {
return "VALIDATED_" + filename;
};
Metadata Validation
When uploading files to Swing it’s possible to define a validation function which will be called before the actual files are transfered to the server. To activate this function it’s important to first define the correct validation namespace.
Namespace
Create a javascript file inside the plugin folder defining extending the objectpanel object with a new function called validateMetadata:
eidosmedia.webclient.extensions.objectpanel.validateMetadata = function( ctx, items, callbacks ){}
Parameters
-
"ctx": The ctx is a JSON object which represents the object’s context. Available only in init method. See Basic structure of the Context Object for further details.
-
"items": An array with the objects to be uploaded.
-
"callbacks": An object with success and error functions.
Validate data
Once the validateMetadata function is called it’s possible to cycle through the array of items and for each item work with its XML metadata document.
Caution
|
If all the checks on the XML documents are valid, call the callbacks.success function to proceed with the upload process; otherwise call the callbacks.error. |
Callbacks and parameters
When calling the callbacks.error function it’s mandatory to pass two arguments.
callbacks.error(
{ msgError: 'General Error Message'},
[{id: 'picId', msgError:'Specific Error Message'}]
);
The first parameter is an object with the general error message to display after the validation. The second is the items array we received as input in the validateMetadata function but modified with a msgError property for those items (and only for those items) which failed validation.
Final Implementation Example
eidosmedia.webclient.extensions.objectpanel.validateMetadata = function(ctx, items, callbacks){
var generalValidationOK = true;
var itemsWithError = [];
$(items).each(function(i, el){
var xmlMetadataDoc = el.data.metadata;
// call external validation method
var validationOK = _callMyValidationMethod(xmlMetadataDoc);
if ( !validationOK ){
generalValidationOK = false;
el.msgError = 'This item metadata is not valid!'
itemsWithError.push( el );
}
});
if ( generalValidationOK ){
callbacks.success();
} else {
callbacks.error(
{msgError: 'Error Message'},
itemsWithError
);
generalValidationOK = true;
}
};
Import URL: preview and import information.
With Swing it is possible to drag external URLd. Since there can’t be any control on the content of the URL, Swing tries to propose a generic preview, consisting in an iframe pointing to the specific URL.
Then, when trying to import the content, three standard cases may apply:
-
the content is recognized as an image. This will be imported as an image into the EOMDB.
-
the content is recognized as an HTML file. This will be imported as a URL into the EOMDB.
-
the content is not recognized as one of the above. This will be imported but its well-functioning is not guaranteed.
So, Swing allows to specify custom information to provide a more precise response according to the URL passed. It is possible to provide the preview information and the import information. A common use for this possibility is to perform regular expressions and provide additional information according to the url.
Specify preview information
Following the same guidelines of the other extensions, it is possible to specify a custom getPreviewInfoURL behaviour, registering a new uploader extension.
eidosmedia.webclient.extensions.uploader.add('getPreviewInfoURL', function( url, token, getConnectionURL ) { /* ... */ }
The parameters passed are:
-
the url.
-
the Swing application token.
-
the checkConnectionURL, an URL to be called to verify whether the token is valid.
The function must return a oEmbed-like json response, as the following example:
{
//"version": "1.0",
"type": "video",
"importType": "video",
//"provider_name": "YouTube",
//"provider_url": "http://youtube.com/",
//"width": 425,
//"height": 344,
//"title": "Amazing Nintendo Facts",
//"author_name": "ZackScott",
//"author_url": "http://www.youtube.com/user/ZackScott",
"html":
"<object width=\"425\" height=\"344\">
<param name=\"movie\" value=\"http://www.youtube.com/v/M3r2XDceM6A&fs=1\"></param>
<param name=\"allowFullScreen\" value=\"true\"></param>
<param name=\"allowscriptaccess\" value=\"always\"></param>
<embed src=\"http://www.youtube.com/v/M3r2XDceM6A&fs=1\"
type=\"application/x-shockwave-flash\" width=\"425\" height=\"344\"
allowscriptaccess=\"always\" allowfullscreen=\"true\"></embed>
</object>"
}
What really matters here is the html attribute. This will be used by the Swing preview to show the content of the imported URL. Other parameters are, at the moment, ignored.
Another important attribute is the importType. It can specified either here or in the getImportInfoURL method. Please check the method in the following paragraph.
Specify import information
Following the same guidelines of the other extensions, it is possible to specify a custom getImportInfoURL behaviour, registering a new uploader extension.
eidosmedia.webclient.extensions.uploader.add('getImportInfoURL', function( url, token, getConnectionURL ) { /* ... */ }
The parameters passed are:
-
the url.
-
the Swing application token.
-
the checkConnectionURL, an URL to be called to verify whether the token is valid.
The function must return a Javascript, as the following example
{
"importType": "picture",
"filename": "someSpecificFilename"
}
If importType is specified, Swing will know better how to save the content. Otherwise, it will try to check the type attribute and, if no information is provided, the contentType of the url.
It is also possible to "force" a filename. This is especially useful in case of url without extension (e.g. services that return images). In that case, it would be better to specify a valid filename.
Important
|
If the type is valued as text/html ( the basic contentType of an HTML page ), the content will be imported as URL. Available importTypes are: |
Important
|
getPreviewInfoURL and getImportInfoURL methods are optional. If not available, Swing will try to use the oEmbed protocol if available, and an internal preview system if the oEmbed protocol is missing. In that case, the importType will be guessed by the contentType of the URL response, and the preview will likely be an |
Final Implementation Example
eidosmedia.webclient.extensions.uploader.add('getPreviewInfoURL', function( url, token, checkConnectionURL ) {
if ( url.match(/mycustomdamextension/ ) {
return {
"type": "image",
"importType": "picture",
"html":
"<object width=\"425\" height=\"344\">
<param name=\"movie\" value=\"http://www.youtube.com/v/M3r2XDceM6A&fs=1\"></param>
<param name=\"allowFullScreen\" value=\"true\"></param>
<param name=\"allowscriptaccess\" value=\"always\"></param>
<embed src=\"http://www.youtube.com/v/M3r2XDceM6A&fs=1\"
type=\"application/x-shockwave-flash\" width=\"425\" height=\"344\"
allowscriptaccess=\"always\" allowfullscreen=\"true\"></embed>
</object>"
}
} else {
/* RETURNING NULL OR A FALSY VALUE OR AN OBJECT WITHOUT THE 'HTML' PROPERTY
WILL RESULT IN SWING USING ITS STANDARD PREVIEW MECHANISM */
return null;
}
});
/* Please notice that, having specified the importType inside the
getPreviewInfoURL method, the following method implementation is redundant */
eidosmedia.webclient.extensions.uploader.add('getImportInfoURL', function( url, token, checkConnectionURL ) {
if ( url.match(/mycustomdamextension/ ) {
return {
"importType": "picture"
}
} else {
/* RETURNING NULL OR A FALSY VALUE OR AN OBJECT WITHOUT THE 'HTML' PROPERTY
WILL RESULT IN SWING USING ITS STANDARD MECHANISM */
return null;
}
});
Custom URL handling
With Méthode Swing it’s possible to add manipulation to a custom url.
Registration of a custom manipulation
To register a custom manipulation, use the following namespace
eidosmedia.webclient.extensions.manageCustomUrl
and its function
register( options )
Method |
|
Parameter |
Required Supported functions:
|
Returns |
|
The following is a very simple registration for a custom manipulation.
(function(){
eidosmedia.webclient.extensions.manageCustomUrl.register({'handleUrl': function( data, ctx, callback ) {
/**
* Save the current url
*/
var uri = data.uri;
/**
* Save the handle drop flag
*/
var handleDrop = false;
try {
/**
* The area object it's useful to verify if the call come form the editor of the story
*/
var area = ctx.area;
if (area.getType() == 'editor' && area.getName() == 'story') {
/**
* In our example we decide to handle only the url of eidosmedia site
* Change the if statement according to your needs
*/
if (uri == 'https://www.eidosmedia.com/') {
var contentTitle = 'Eidosmedia link site';
handleDrop = true;
/**
* Prepare the xml to insert in the current active document context
*/
var xml = '<a href="' + uri + '">' + contentTitle + '</a>';
ctx.activeDocument.insertXml(xml);
}
}
/**
* notify a callback, if specified, only if the drop has not been handled so Swing can manage
* the url in the standard way
*/
if (!handleDrop && callback) {
callback(data);
}
} catch (ex) {
console.log("manageCustomUrl-handleUrl custom manipulation exception caught", ex);
/**
* notify a callback, if specified, only if the drop has not been handled so Swing can manage
* the url in the standard way
*/
if (!handleDrop && callback) {
callback(data);
}
}
}, 'getPreviewInfo': function( data, ctx ) {
/**
* Save the current url
*/
var uri = data.uri;
var currentXml = data.xml;
var previewInfo;
try {
/**
* The area object it's useful to verify if the call come form the editor of the story
*/
var area = ctx.area;
if (area.getType() == 'editor' && area.getName() == 'story') {
/**
* In our example we decide to handle only the url of eidosmedia site
* Change the if statement according to your needs
*/
if (uri == 'https://www.eidosmedia.com/') {
var path = ''; // path of an image in the eomdb;
var customIcon = 'fa fa-exclamation-circle'; // the custom icon to use
previewInfo = {'path': path, 'icon': customIcon}
}
}
} catch (ex) {
console.log("manageCustomUrl-getPreviewInfo custom manipulation exception caught", ex);
}
return previewInfo;
}});
})();
Note
|
Wrap all the custom manipulation with a try…catch block to allow Swing to handle the url if something goes wrong. |
Popovers
In Methode Swing it is possible to customize some popovers available in the application
Usage Ticket Popover
Usage Ticket popover is located under the following path:
/{swing-app-folder}/app/templatesUI/popinfo/usageticket-popinfo.html
Caution
|
Méthode Swing uses Underscore.JS templating system to enhance the user experience. See Underscore.JS for further information, or the box below for some useful tips. |
The template is rendered with a main object:
-
data, which is an object with a single property, usageTickets, which contains all the usage tickets.
Custom OEmbed Providers
In Methode Swing it is possible to configure custom oembed providers.
Prepare the plugin to add custom oembed providers
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Add a custom oembed provider
In order to add a custom oembed provider to Methode Swing, it is necessary to use the following namespace:
eidosmedia.webclient.extensions.oembedProviders
The syntax is the following:
eidosmedia.webclient.extensions.oembedProviders.add((customOmbedProviders);
Where:
-
customOmbedProviders [array] is a list of custom oembed providers (oembed provider object) to add to the already available ones.
EmbedProviderObject are defined in this way:
-
name [string] is the name of the custom oembed provider.
-
type [string] [photo | video | rich ] - is the type of the oembed provider.
-
urlschemearray [array] a list of regular expression to matxh the custom url oembed provider.
-
apiendpoint [string] an endpoint url if requetsed by the custom oembed provider. It can be null.
-
extraSettings [object] extra setting needed by the custom oembed provider. It can be null.
Note
|
It’s possible to configure an oembed provider to use a swing proxy. In this case the apiendpoint value must be the same of the proxy name and the attribute useSwingProxy of the extraSettings object must be set to true, the attribute dataType must be set according to the return value of the embed service that who made the extension has decided to integrate. In general it is set to the json value. |
Example
eidosmedia.webclient.extensions.oembedProviders.add(
[
{
name: 'scmptv',
type: 'video',
urlschemearray: ['widgets\\.scmp\\.com/video/.+'],
apiendpoint: null,
extraSettings: {
templateRegex: /.*id=(\w+).*/,
template: '<iframe src="http://widgets.scmp.com/video/video_iframe.php?id=$1" width="100%" allowfullscreen="true" allowscriptaccess="always"' +
'scrolling="no" frameborder="0" style="max-height: none !important; height: 540px;"></iframe>',
nocache: 1
}
},
// custom oembed provider that use swing proxy
{
name: 'myvideoplace',
type: 'video',
urlschemearray: ["myvideoplace\\.tv/.+"],
apiendpoint: 'mvp', // same of the proxy name
extraSettings: {
dataType: 'json',
useSwingProxy: true
}
}
]
);
Custom Version Compare handling
With Méthode Swing it’s possible to add manipulation to version compare.
Registration of a custom version compare handling
To register a custom version compare manipulation, use the following namespace
eidosmedia.webclient.extensions.versionCompare
and its function
register( options )
Method |
|
Parameter |
Required Supported functions:
|
Returns |
|
The following is a very simple registration for a version compare manipulation.
(function(){
eidosmedia.webclient.extensions.versionCompare.register({'selectVersion': ( versions ) => {
let versionNumber;
try {
/**
* Select the version number to compare
*/
versionNumber = versions[1].version_number;
} catch (ex) {
console.log("custom select version exception caught", ex);
}
return {versionNumber};
}});
})();
Note
|
Wrap all the custom manipulation with a try…catch block to allow Swing to work correctly if something goes wrong. |
Styling
Addition of external CSS to Swing
In Méthode Swing it is possible to add external CSS files. Such files must be placed under
{SWING-APP}/plugins/assets
All the files contained in this folder are loaded asynchronously into Méthode Swing.
Tip
|
It is suggested to place each library under a specific folder, e.g: {SWING-APP}/plugins/assets/font-test/font-test.css |
Warning
|
By default, these CSS are loaded only at application level as "assets.css". To load and apply the CSS inside the editor context you must put the following line
as the first line of the CSS. Only the CSS files with editors directive (@editor or @dwpeditor) are applied inside the editors, all CSS files with application directive (@app) or without directive are excluded. Méthode Swing loads ONLY the CSS (*.css) files in the folder. Of course, if the CSS file refer to other files (such as fonts or background images) these will be working properly. |
Warning
|
Méthode Swing has no control over the CSS. So, an external CSS could break the application layout. Please refer to the log to see which libraries have been loaded. |
Context Menu
In Methode Swing it is possible to configure context menus in the Explorer area
Prepare the plugin to add menus and action
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Add a context menu
In order to add a custom context menu to Methode Swing, it is necessary to use the following namespace:
eidosmedia.webclient.extensions.contextMenu
The syntax is the following:
eidosmedia.webclient.extensions.contextMenu.add(name, options);
Where:
-
name [string] is the name of the custom menu, alias a unique identifier.
-
options [optional, object] is a Javascript object containing the properties of the custom actions.
The options parameter can be omitted. In this case, Swing will use the previously registered command with the same name property. See example below.
If options is specified, it must follow the guidelines of a generic Swing command. See Commands documentation for further information.
Example
eidosmedia.webclient.commands.add({
name: 'complex',
label: 'Perform some complex operation...',
isActive: function(ctx) {
return ctx.activeObject.getType() === 'Image';
},
action: function( ctx, params, callback ) {
alert('Performing action on ' + ctx.activeObject.getName());
}
});
eidosmedia.webclient.extensions.contextMenu.add('complex');
Topics Calendar Filters
Methode Swing allows to customize the filter used inside the Topics Calendar view
Configure a custom filter
Filters are made of an HTML template and a related JS file.
Caution
|
Default templates are put in the base folder {SWING-APP}/config/templates/topiclist |
Filters can be configured outside {SWING-APP}. See the paragraph How to configure topic filters in external folder for some tips in how to take advantage of this new configuration option.
Important
|
Topic List Templates are based on the same algorithm of Swing Custom Search Filter, with few minor differences, listed below. Please refer to the Custom search filter documentation for a detailed explanation of the filter inner workings. |
Configure the JS file
To add a filter, the JS should be structured as follows.
eidosmedia.webclient.topicList.addFilter( options );
In detail, the options are:
eidosmedia.webclient.topicList.addFilter({
// @property "template": {string} - the path to the filter template. Path is relative to the 'config/topiclist/' folder.
// @required
template: 'topiclistfilter.html',
/**
* Function called after loading the template, but BEFORE loading the filter
* use it to add listeners.
* @param {ContextObject}
* @param {Object} options - the a list of options.
* Please see below for the list of options.
*/
onLoad: function( ctx, options ) {
},
/**
* Function called after having executed the query.
* @param {ContextObject}
* @param {Object} - filterConditions: an object containing all the conditions obtained from the query
* @param {Array} results - the results of the query
* @param {Function} callback - the option to call after processing the result.
* Please see below for the list of options.
*/
processResults: function( ctx, filterConditions, results, callback ) {
/*
Here it is possible to process results,
elaborate the custom conditions, etc.
*/
}
});
Each parameter is detailed below.
template
This property defines the template for the filter.
{
// ...
template: "test.html",
// ...
}
Warning
|
The path of the template starts from the topiclist/ folder. |
onLoad
onLoad is a function called when the filter is loaded for the first time. This function is called AFTER the DOM has been filled, so that all the DOM elements of the filter are available. It can be used to add custom listeners for events.
It is called with 2 parameters:
-
ctx: the Context Object. See Context Object documentation for further details. In this case, though, the context object has neither activeObject nor selection, and only contains information on the Swing area.
-
options. It is a Javascript Object with a few properties. See code below for further details.
{
options: {
panel: DOMObject, // the DOM reference to the filter container
data: {
groups: [], // Array of groups
topicListCfg: {}, // Topic list configuration as set in Swing main configuration,
userChannels: [], // Array of channels for the user
channels: [], // List of all the available channels
workflows: [], // List of all the workflow steps available
}
}
}
{
onLoad: function( ctx, options ) {
var $panel = $(options.panel);
// Put your code here...
}
}
Tip
|
Return value of the function is not important. |
processResults
The processResults function is called whenever the filter is executed. It is possible to elaborate the results as preferred.
It is called with a few parameters:
( ctx, filterConditions, results, callback )
-
ctx: the Context Object. See Context Object documentation for further details. In this case, though, the context object has neither activeObj nor selection, and only contains information on the Swing area.
-
filterConditions: a list of all the conditions set in the filter. It is an array of all the data-xvalue and data-custom-xvalue available in the filter.
-
results: the list of results of the query
-
callback: the callback to be called with the processed results
{
// An example used to filter for "Standing Objects"
processResults: function( ctx, filterConditions, results, callback ) {
// console.log( filterConditions );
var ownerTeamFilter = _.findWhere(filterConditions, { conditionKeyword: 'ownerteam' });
if (ownerTeamFilter && ownerTeamFilter.conditionValue) {
ownerTeamFilter = ownerTeamFilter.conditionValue.split(',');
if (ownerTeamFilter.length) {
var _groups = _.filter(ownerTeamFilter, function( tp ) { return tp.indexOf('-GROUP') > -1; });
_groups = _.map( _groups, function( gp ) { return gp.replace('-GROUP', ''); } )
results = _.filter( results, function(tp) {
if ( tp.virtual_attributes_json && tp.virtual_attributes_json.va && tp.virtual_attributes_json.va.oteam ) {
return _groups.indexOf( tp.virtual_attributes_json.va.oteam ) > -1;
}
return false;
});
}
}
callback( results );
}
}
Configure the HTML File
While creating the HTML, the same mechanism as the Search Filter creation can be used. Both filters share the same keywords, same attributes and operators.
Please refer to the HTML and Keywords reference in the Filter documentation for further information.
How to configure topic filters in external folder
Additional topic filters may be made available to Swing application by defining one or more nested components in Swing web context in server.xml. (for further details on Tomcat 9.x Resources configuration, please refer to Resources configuration).
This is an example of the external filters configuration.
<Context docBase="com.eidosmedia.webclient.web-app"
path="/swing" reloadable="false">
<Resources
className="org.apache.catalina.webresources.StandardRoot">
<PreResources
className="org.apache.catalina.webresources.DirResourceSet"
base="/methode/meth01/extension/topicfilters" readOnly="true"
webAppMount="/config/templates/topiclist" />
</Resources>
</Context>
Searching
Search Configuration
Méthode Swing Search is an important component of Swing. It allows to perform searches in different domains (EOMDB, Web…) and it is highly extendable.
Tip
|
To completely disable the search, simply add "disabled": true to the configuration.
|
Tip
|
To disable the search preview results (so that all query are viewed directly in the Explorer area, if it is available), simply add "disableResultsPreview": true to the configuration. NOTE: please notice that it works only for EOMDB searches. Other searches will be previewed as always.
|
Tip
|
It is possible to define the click action performed on resultset items by configuring the itemClickAction property. Allowed values are:
|
Tip
|
It is possible to define a fixed set of "custom queries" available in the top-left dropdown. This offer a practical shortcut to the most common used queries. It is also possible to choose whether to execute the custom queries automatically or not, with the executeQueryAutomatically parameter.
|
Tip
|
It is possible to insert the query path. Use the id property even in case of path. |
Tip
|
It is possible to automatically hide custom filters when a search is performed in candidate.
|
Column catalog configuration
Inside the search configuration, for EOMDB domains, it is possible to configure multiple column catalogs for the results shown in the Swing Explorer View.
<search>
<!-- ... -->
<allowMultipleColumnCfg>true</allowMultipleColumnCfg>
<defaultColumnCfg>methodeResultSetList</defaultColumnCfg>
<catalogs>
<catalog>methodeResultSetList</catalog>
<catalog>methodeResultSetThumbnails</catalog>
<catalog>SwingResultSet</catalog>
</catalogs>
</search>
-
allowMultipleColumnCfg (true / false) - If true, the "Explore" button in the search is a dropdown and lists all the configured column catalogs.
-
defaultColumnCfg ("methodeResultSetList") - This is the column catalog used when the user clicks on the "Explore" button. Beware that each domain can override the default by providing a different defaultColumnCfg
-
catalogs a list of available columnCatalog names that will appear in the dropdown. Beware that each domain can override the default by providing a different set of catalogs.
-
databaseIndexes - The databaseIndexes property gives the user the possibility to specify the default index in which the default-folder filter. See Custom filters documentation for further info on the default-folder filter. Configuration of databaseIndexes property should be as follows:
<search>
<!-- ... -->
<databaseIndexes>
<databaseIndex>
<name>Editorial</name>
<index>Production@meth01_eomjse1;Wires@meth01_eomjse1</index>
</databaseIndex>
<databaseIndex>
<name>Archive</name>
<index>Archive@meth02_eomjse1</index>
</databaseIndex>
</databaseIndexes>
</search>
Domain configuration
Warning
|
As far as the Search configuration is concerned, for the parameters found under the <domain> key, no merge will be applied and the hierarchy to be respected is the usual one: |
Search configuration is included within a single search object:
<search>
<domains>
<domain>...</domain>
<domain>...</domain>
<domain>...</domain>
</domains>
It is possible to search within different search domains. Supported domains are:
-
EOMDB - internal database search
-
Web - search on different services ( their availability depends on the APIs. Support for the API may drop without warning )
-
Contacts - search within Méthode users.
-
Pinboard - search within the Pinboard.
-
Social (if available) - search in social networks.
-
Custom - custom search domains specified by the user.
Note
|
Only EOMDB and Web domains are customizable. |
Note
|
Disable specific domains - It is possible to disable the different searches by setting the specific privileges ( "_PadmaPriv_enableSearchExternalSource", "_PadmaPriv_enableSearchContacts", "_PadmaPriv_enableTemporaryPinboard" ) |
General domain properties
Each domain has the following properties:
Name | Description | Values |
---|---|---|
name |
Domain name. Must be unique and without spaces. |
|
type |
Domain type. NOTE: there can be multiple EOMDB domains, while it is suggested to have a unique Web domain. |
eomdb / web |
connectionName |
Used only by EOMDB domains, indicates the connection name configured in the MRAS configuration. For backward compatibility the previous <repositoryId> and <repositoryName> is correctly read anyway. |
|
defaultColumnCfg |
Used to override the default search defaultColumnCfg property. |
|
showMetadata |
Used only by EOMDB domains, if true the results will also contain the "attributes" property. Be aware that this will slow down the search. |
false |
hidden |
If true, domain is hidden from the search |
true / false |
defaultFor |
If specified, in case of specific searches ( e.g. search from image or video placeholder ), the domain with the corresponding searchType will be selected. |
image / video |
groupResults |
For EOMDB domains, if true the results are grouped and sorted according to the type |
true / false |
label |
The domain label |
|
icon |
Default icon for the domain |
|
view |
For EOMDB databases, it is possible to specify a custom ColumnCatalog. By default, the column catalog is "SwingResultSet" (internal to Swing). See Search templates configuration, usage and creation to understand how the information is used. |
|
itemsPerPage |
Number of item per page (quicksearch) |
8 |
disablePagination |
If true, no pages are created |
true / false |
quicksearchLimit |
Max number of results in quicksearch mode. |
100 |
openFilter |
If a filter is available and the value is true, the filter is opened by default. |
false |
conditions |
It is an array of additional conditions (filters) to be applied to the search. See Conditions configuration for further details. |
Default conditions (filter by type) |
archives |
It is an array of indexes, through which the user can choose. See Indexes configuration (archives) for further details. |
Indexes configuration (archives)
Each of them can be configured as follows:
Name | Description |
---|---|
label |
Name used in the search to visually identify the index |
archive |
The index name. It can contain multiple indexes, separated by a ";" (in this case, all indexes MUST be on the same repository) |
repName |
The EOMDB repository name. Mandatory for all archives |
prefix |
If specified, every search with that archive selected will be prepended with this prefix. E.g. in web searches, it is possible to specify "site:www.yoursite.com" as a prefix in order to force the search only on that website. |
isDefault |
Is true, the index is selected by default |
Sample archive configuration
<archives>
<archive>
<label>Editorial</label>
<archive>production@meth01_eomse1</archive>
<repName>Editorial</repName>
<isDefault>true</isDefault>
<visible>true</visible>
<enabled>true</enabled>
</archive>
<archive>
<label>Wires</label>
<archive>ap@eomjse3_meth01;nyt@eomjse3_meth01</archive>
<repName>Wires</repName>
<isDefault>false</isDefault>
<visible>true</visible>
<enabled>true</enabled>
</archive>
<archive>
<label>Archive</label>
<archive>archive@meth01_eomjse1</archive>
<repName>Archive</repName>
<isDefault>true</isDefault>
<visible>true</visible>
<enabled>true</enabled>
</archive>
</archives>
Warning
|
In case of custom domains (created with a Plugin), it is possible to specify the archives as a function written in the following way:
|
Conditions configuration
Conditions represent additional specifications added to a query. That is, if the user choose a condition whose value is type:EOM::Story, the results are limited to the EOMDB stories. (In a way, they can be considered as filters).
There are two different types of conditions:
-
default conditions - Such conditions are added in any search that the user performs. They can be seen as permanent filters, or are conditions that always limit or specify the searches that the user makes.
-
alternative conditions - Such conditions, instead, appear in the top right part of the quicksearch form (see picture below). The user can choose among them, to filter the results of a search.
Default conditions
Default conditions should be configured as follows:
<conditions>
<condition>
<isDefault>true</isDefault>
<value>owner:myself</value>
</condition>
<condition>
<isDefault>true</isDefault>
<value>modified_lastdays:10</value>
</condition>
<condition>
<isDefault>true</isDefault>
<value>sort:ObjectInfo/modified;D</value>
</condition>
<condition>
<isDefault>true</isDefault>
<value>metadata:"My/Path=my value"</value>
</condition>
</conditions>
This sample configuration limits all EOMDB quick-searches to the files whose owner is the current user, and that have been modified in the last 10 days. So, default conditions must have isDefault parameter set to true, and the value parameter set to the condition, as visible in Swing search keywords documentation paragraph.
Tip
|
All the conditions are put with an AND operator, but within a condition it is possible to specify OR operators. In this case, please put the condition within parenthesis. Example:
|
Caution
|
Conditions are domain-specific. The described conditions are available only for EOMDB domains. For custom domains, it is you that have to code the behaviour. |
Alternative conditions
They are configured as follows:
<conditions>
<condition>
<label>Story</label>
<icon>emui-icon-newspaper</icon>
<value>type:eom::story</value>
</condition>
<!-- Other conditions -->
</conditions>
Tip
|
The same keyword reference table ( Swing search keywords documentation ) can be used also for the Alternative conditions. |
Domains: sample configuration
<search>
<domains>
<domain>
<name>eomdblocal</name>
<type>eomdb</type>
<label>Local archive</label>
<icon>emui-icon-database</icon>
<defaultFor>image</defaultFor>
<itemsPerPage>8</itemsPerPage>
<groupResults>false</groupResults>
<quicksearchLimit>48</quicksearchLimit>
<useExternalSuggestion>true</useExternalSuggestion>
<externalSuggestionURL>http://suggestqueries.google.com/complete/search?q={data.value}&client=firefox&callback=?</externalSuggestionURL>
<conditions>
<!-- this is a default condition -->
<condition>
<isDefault>true</isDefault>
<value>modified_lastdays:10</value>
</condition>
<!-- these are the alternative (variable) condition -->
<condition>
<label>Free search</label>
<labelkey>search.types.freesearch</labelkey>
<icon>icon-search</icon>
<value>type:</value>
</condition>
<condition>
<label>Story</label>
<labelkey>search.types.story</labelkey>
<icon>emui-icon-newspaper</icon>
<value>type:eom::story</value>
</condition>
<condition>
<label>WireStory</label>
<labelkey>search.types.wirestory</labelkey>
<icon>icon-file-text</icon>
<value>type:wirestory</value>
</condition>
<condition>
<label>Images</label>
<labelkey>search.types.images</labelkey>
<icon>icon-picture</icon>
<value>type:image</value>
</condition>
<condition>
<label>Gallery</label>
<labelkey>search.types.gallery</labelkey>
<icon>emui-icon-pictures</icon>
<value>type:eom::mediagallery</value>
</condition>
<condition>
<label>Audio</label>
<labelkey>search.types.audio</labelkey>
<icon>icon-music</icon>
<value>type:audio</value>
</condition>
<condition>
<label>Topic</label>
<labelkey>search.types.topic</labelkey>
<icon>emui-icon-topic</icon>
<value>type:eom::topic</value>
</condition>
<condition>
<label>Search by name</label>
<labelkey>search.types.byname</labelkey>
<icon>icon-file</icon>
<value>param:name:</value>
</condition>
</conditions>
<archives>
<archive>
<name>production</name>
<label>Editorial</label>
<archive>production@meth01_eomse1</archive>
<isDefault>true</isDefault>
<visible>true</visible>
<enabled>true</enabled>
</archive>
<archive>
<name>globecms</name>
<label>GlobeCMS</label>
<archive>globecms@meth01_eomse1</archive>
<isDefault>false</isDefault>
<visible>true</visible>
<enabled>true</enabled>
</archive>
<archive>
<name>wires</name>
<label>Wires</label>
<archive>wires@meth01_eomse1</archive>
<isDefault>false</isDefault>
<visible>true</visible>
<enabled>true</enabled>
</archive>
<archive>
<name>archive</name>
<label>Archive</label>
<archive>archive@meth01_eomse1</archive>
<isDefault>false</isDefault>
<visible>true</visible>
<enabled>true</enabled>
</archive>
<archive>
<name>configuration</name>
<label>Configuration</label>
<archive>configuration@meth01_eomse1</archive>
<isDefault>false</isDefault>
<visible>true</visible>
<enabled>true</enabled>
</archive>
</archives>
</domain>
<domain>
<name>web</name>
<type>web</type>
<label>Web search</label>
<icon>icon-globe</icon>
<itemsPerPage>8</itemsPerPage>
<useExternalSuggestion>true</useExternalSuggestion>
<conditions>
<condition>
<label>Free search</label>
<icon>icon-circle-blank</icon>
<value>type:web</value>
</condition>
<condition>
<label>News</label>
<icon>emui-icon-newspaper</icon>
<value>type:news</value>
</condition>
</conditions>
<archives>
<archive>
<name>google</name>
<label>Google</label>
<icon>icon-google</icon>
<archive>google</archive>
<isDefault>true</isDefault>
<visible>true</visible>
<enabled>true</enabled>
<exclusive>true</exclusive>
</archive>
</archives>
</domain>
</domains>
</search>
Swing search keywords documentation
Swing searches can be filtered by using keywords. Such keywords are then elaborated and transformed to create the adequate XML query for the EOMDB.
These keywords can be used within the Swing search, the Swing Explorer Folder filter, and the Swing search filters.
Warning
|
The supported keywords are meaningful for EOMDB searches only. If you want to use filters for custom domains, feel free to use any keyword you prefer. The filters will be passed in the conditions array of the Search Controller (options parameter). See Search controller documentation for further details. |
Available keywords
channel
Returns only the objects of a given channel.
Syntax
channel:(CHANNEL) userchannel:(CHANNEL)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). |
Tip
|
userchannel differs from channel in the fact that only the channels relative to the current user are available.. |
content
Search a specific text in the content of an object.
Syntax
content:"CONTENT"
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). |
contentmetadata
Search for a text in both content and metadata.
Syntax
contentmetadata:"CONTENT"
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). |
created_lastdays
Allow to obtain the documents created in the last N days
Syntax
created_lastdays:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any numeric value. |
creator
See user, creator, owner.
freexml
Allow to insert a specific xml in the query. Please use it with moderation.
Syntax
freexml:"CONTENT"
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Note: please use single quotes when a double quote is used inside the value. |
lastmodifier
Returns the objects last modified by a specific user.
Syntax
lastmodifier:(USER|myself)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Return the objects modified by the specified user. |
|
|
Return the objects modified by the current user |
limit
Limits the results to a specific number.
Syntax
limit:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
Any numeric value |
|
locker, lockedby
Search for objects locked by a given user
Syntax
locker:(USER|myself)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Return the objects locked by the specified user. |
|
|
Return the objects locked by the current user |
Tip
|
|
searchmetadata
Search a specific value in all the metadata.
Syntax
searchmetadata:"CONTENT"
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). |
metadata
Search a specific value in a given xpath.
Syntax
metadata:"{X-PATH}={VALUE}"
Values
Keyword | Example | Description |
---|---|---|
|
|
See previous example. Note: Quotes are mandatory. If the value contains double quotes, use single quotes instead. |
metadatarange
Search a specific value in a given xpath, with the "range" operator ( inside the se:attributes tag )
Syntax
metadatarange:"{X-PATH}={VALUE}"
Values
Keyword | Example | Description |
---|---|---|
|
|
See previous example. Note: Quotes are mandatory. If the value contains double quotes, use single quotes instead. |
Important
|
The RANGE value must be in the following format: YYYYMMDDhhmmss;YYYYMMDDhhmmss. |
modified_lastdays
Allow to obtain the documents modified in the last N days
Syntax
modified_lastdays:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any numeric value. |
name
Search an object with a specific filename
Syntax
name:"CONTENT"
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value |
owner
See user, creator, owner.
range
See metadatarange.
restrictto
Returns the objects inside a path.
Syntax
restrictto:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
Any string value (with quotes if there is a space). |
|
sort
Complete sorting mechanism.
Syntax
sort:"{X-PATH};{VALUE}"
Values
Keyword | Example | Description |
---|---|---|
|
|
See previous example. Note: Quotes are mandatory. If the value contains double quotes, use single quotes instead. |
Tip
|
In
|
sortby
Simple descending sort according to a parameter in the ObjectInfo.
Syntax
sortby:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Return the objects sorted by creation date, descending. |
|
|
Return the objects sorted by modified date, descending. |
status, workflow
Search objects with a given status ( workflow ).
Syntax
status:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). |
type
Returns only the objects of a given type.
Syntax
type:(TYPE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Return the objects of specified type. |
usageticket
Allow to search within the usage tickets.
Syntax
usageticket:"tp:{type};;c:{creator};;rng:{range}"
Values
Keyword | Example | Description |
---|---|---|
|
|
|
Tip
|
|
user, creator, owner
Search for objects created by a given user
Syntax
user:(USER|myself)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Return the objects created by the specified user. |
|
|
Return the objects created by the current user |
Tip
|
|
userchannel
See channel.
workflow
See status, workflow.
workfolder
Returns the objects inside a workfolder.
Syntax
workfolder:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
Any string value (with quotes if there is a space). |
|
Search templates configuration, usage and creation
Méthode Swing uses templates to render the search results.
Configuration of result templates
To use a template, it is necessary to configure the searchTemplate options in the Domain section. See Domain configuration for further details.
Caution
|
It is HIGHLY discouraged to change the default search themes for Methode types. Their layout can be customized by operating on the specific column catalog (SwingResultSet). |
In the ResourceSpace example, we used the following settings:
<searchTemplate>
<type>rsimage</type>
<template>search-preview-resourcespace.html</template>
</searchTemplate>
<searchTemplate>
<type>rstext</type>
<template>search-preview-resourcespace-text.html</template>
</searchTemplate>
"searchTemplate" : [
{ type: "rsimage", template: "search-preview-resourcespace.html" },
{ type: "rstext", template: "search-preview-resourcespace-text.html" }
]
This settings specifies that we are using two templates for two different types.
Note
|
We could have used the same template for different types. |
Usage and creation of a template
Each template is an HTML file which can be customized according to the user’s necessity.
All the widgets are put inside the following path:
{SWING-APP}/config/templates/search/{TEMPLATE-NAME}
Preview files can be configured outside {SWING-APP}. See the paragraph How to configure search templates in external folder for some tips in how to take advantage of this new configuration option.
Default templates are:
-
src-preview-eom.html for Methode types (used in search, candidate and correlates)
-
src-preview-user.html for type: EOM::User
-
src-preview-webcontent.html for type: web::Content
Customize the templates
Caution
|
Méthode Swing uses Underscore.JS templating system to enhance the user experience. See Underscore.JS for further information, or the box below for some useful tips. |
The template is rendered with a main object:
-
item, which contains all the information about the item.
item: the item info
The item object inside template contains all the information retrived from the search source. That is, in case of external sources, the one you decide to pass back to the search. In general though, all Méthode objects should have the following properties:
// item: common properties { EXAMPLE }
{
"id": "1.0.113665564",
"columns": "SEE BOX BELOW"
"name": "Obama, Hollande agree on much -- but not Afghanistan.xml",
"description": "",
"type": "EOM::Story",
"owner": "johndoe",
"creator": "johndoe",
"created": 1337764225,
"last_modifier": "johndoe",
"modified": 1409816672,
"locker": "",
"locked": 1423560030,
"status_info": {
"name": "NewsFlow/Editing",
"identifier": "RGB(255,0,0)",
"comment": ""
},
"size": 6898,
"system_attributes": {
"workfolder": "/Globe/Politics",
"templateName": "/SysConfig/Globe/Templates/story.xml",
"summary": "New French President Francois Hollande told President Barack Obama on Friday that he will stick by his pledge .",
"wordCount": "998",
"sugCategory": "",
"channel": "Globe-Web",
"storyType": "",
"productInfo": {
"name": "Globe-Web",
"issueDate": "20120524"
}
},
"system_attributes_xml": "XML HERE",
"createdStr": "20120523091025",
"modifiedStr": "20140904074432",
"channel": "Globe-Web",
"issueDate": "20120524",
"preview": "/WebClient/api/rest/object/preview?token=12dbbac2-6d8d-445d-8a26-8f79ff0aca84&id=1.0.113665564&fa=lowres"
}
Beyond these properties, ALL the results will at least have the following properties:
// item: other properties which will be always available for ANY object ( also external )
{
title: 'Object title if available, otherwise equals to filename',
preview: 'the preview URL which uses the Methode Preview server',
previewThumbnail: 'the preview URL which uses the Methode Preview Thumbnail server'
content: 'if not already available, the summary from the system attributes'
}
Important
|
There is also the eomActions property, which has the HTML of the actions available for the object. If you want to have some actions available for the item, be sure to include this property inside a DOM element whose class is actions somewhere in the template. |
item.columns: columnCatalog properties
The EOMDB results come with an additional property, named columns. The property is a JSON array containing the values specified in the ColumnCatalog associated with the search.
The default column catalog applyed by Swing is as follows (this can been overwritten in the columnCfgCatalogs.swing.xml file):
<!-- Swing ResultSet views -->
<catalog name="SwingResultSet" dir="/" type="methodeResultSetList" listable="true">
<EOMCfgView>
<props sort="name+type&ascending" activeViewer="off" autoScroll="none" />
<column fieldId="1" width="300" name="Title" priority="5">
<choice op="notEmpty" minLength="5">
<data source="info/system_attributes/props/title" />
<data source="info/attributes/ObjectMetadata/General/Headline" />
<data source="info/attributes/Metadata/DocTitle" />
<data source="info/attributes/ObjectMetadata/iptc/headline" />
<data source="info/attributes/ObjectMetadata/iptc/caption" />
<data source="info/attributes/ObjectMetadata/iptc/image_name" />
<data source="info/attributes/Metadata/Title" />
<data source="info/attributes/meta/wire/title" />
<data source="info/attributes/ObjectMetadata/GeneralMetadata/Headline" />
<data source="info/attributes/meta/wire/title" />
<data source="info/attributes/ObjectMetadata/iptc/caption" />
<data source="info/attributes/Metadata/Keywords" />
<data source="info/attributes/Metadata/DocKeywords" />
<data source="info/name" />
</choice>
</column>
<column fieldId="2" width="300" name="Summary" priority="5">
<choice op="notEmpty" minLength="1">
<data source="info/system_attributes/props/summary" />
<data source="info/attributes/Metadata/iptc/caption" />
</choice>
</column>
<column fieldId="3" name="Date" source="info/created" width="130" />
<column fieldId="4" name="Type" width="90" source="info/type" priority="1" />
<!-- Wires -->
<column fieldId="5" name="Agency" width="90" priority="4">
<choice op="notEmpty" minLength="1">
<data source="info/attributes/ObjectMetadata/iptc/credit" />
<data source="info/attributes/ObjectMetadata/Source"/>
<data source="info/attributes/Metadata/Source"/>
</choice>
</column>
<column fieldId="6" name="Category" width="90" priority="4">
<choice op="notEmpty" minLength="1">
<data source="info/attributes/ObjectMetadata/iptc/category" />
<data source="info/attributes/ObjectMetadata/Category"/>
<data source="info/attributes/Metadata/Category"/>
</choice>
</column>
<!-- Production -->
<column fieldId="7" name="WorkFolder" source="info/system_attributes/props/workFolder" width="90" priority="4"/>
<column fieldId="8" name="Channel" source="info/system_attributes/props/productInfo/name" width="90" priority="4"/>
<column fieldId="9" width="90" priority="4" name="Status">
<data source="info/status_info/identifier" format="si:colorRect"/>
<data source="info/status_info/name" format="tk:/$2" priority="3"/>
</column>
<column fieldId="10" width="70" priority="3" name="Locker" source="info/locker" format="lk:icon_name"/>
</EOMCfgView>
</catalog>
Here an example of a record that represents the previous columns property:
[
{
"name": "Summary",
"value": "President Barack Obama is photographed during a presidential portrait sitting for an official photo ...",
"id": "2"
},
{
"name": "Type",
"value": " Image",
"id": "4",
"priority": "1"
},
{
"name": "Locker",
"value": "johndoe",
"id": "10"
}
]
If desired, it is possible to specify your own column catalog in the search domain configuration of the EOMDB. See Domain configuration for further information.
How to configure the Web Search Domain
To configure the Web Search domain (Google), it is necessary to add the custom apikey in the MRAS configuration file, such as:
<config>
<restApi>
<!-- ... -->
<searchEngines>
<searchEngine id="google" dataSourceClass="com.eidosmedia.restserver.websearch.google.GoogleCustomSearchDataSource">
<generic apiKey="YOUR_API_KEY" searchEngineCx="015464143803231643050:kgucpqylmq4"/>
</searchEngine>
</searchEngines>
</restApi>
</config>
How to configure search templates in external folder
Additional search templates may be made available to Swing application by defining one or more nested components in Swing web context in server.xml. (for further details on Tomcat 9.x Resources configuration, please refer to Resources configuration).
This is an example of the external search templates configuration.
<Context docBase="com.eidosmedia.webclient.web-app"
path="/swing" reloadable="false">
<Resources className="org.apache.catalina.webresources.StandardRoot">
<PreResources
className="org.apache.catalina.webresources.DirResourceSet"
base="/methode/meth01/extension/search" readOnly="true"
webAppMount="/config/templates/search" />
</Resources>
</Context>
Extensions: manipulate the search free text and XML
It is possible to manipulate the free text input BEFORE it is sent to validation and, in case of EOMDB searches, transformed into XML. For EOMDB searches, too, it is possible to add an additional validator to change the query XML just before the execution. The methods are described below.
addTextValidator
eidosmedia.webclient.search.addTextValidator(options);
In detail, the options are:
/**
* CUSTOM TEXT VALIDATOR
*/
eidosmedia.webclient.search.addTextValidator({
// @property "domain": {string} - a specific search domain to apply the filter to
// @required - domain or domainType
"domain": "eomdblocal",
// @property "domainType": {string} - if specified, filter is applied to all the domains of the same type
// @required - domain or domainType
// "domainType": "eomdb"
}, function( searchInfo ) {
// Search info contains the following properties:
// - "textInput" {string} - the current search text.
// - "conditions": {array of objects} - the conditions currently selected by the user, filters included.
// Please beware that changes in the conditions made here will NOT be reflected in the search.
// This methods only allows simple alterations to the search free text.
var _textInput = searchInfo.textInput;
// Simple elaboration.
if ( _textInput === 'obama' ) {
_textInput = '"Barack Obama"';
}
// This method must return the new search text, and only this.
return _textInput;
});
addXMLValidator
eidosmedia.webclient.search.addXMLValidator(options, callback);
In detail, the options are:
/**
* CUSTOM XML VALIDATOR
*/
eidosmedia.webclient.search.addXMLValidator({
// @property "domain": {string} - a specific search domain to apply the filter to
// @required - domain or domainType
"domain": "eomdblocal",
// @property "domainType": {string} - if specified, filter is applied to all the domains of the same type
// @required - domain or domainType
// "domainType": "eomdb"
}, function( searchInfo, callback ) {
// Search info contains the following properties:
// - "textInput" {string} - the current search text.
// - "conditions": {array of objects} - the conditions currently selected by the user, filters included.
// - "queryXML": {string} the final XML of the query
// Please beware that changes in the conditions made here will NOT be reflected in the search.
/* IMPORTANT: Please notice the difference with "addTextValidator". This function uses a callback
to return the value */
var _queryXML = searchInfo.queryXML;
// Some elaboration here...
// This method must call the "callback" with the new XML
callback( _queryXML );
});
Search: integration of external DAM services
Méthode Swing allows the integration of external Digital Asset Management (DAM) services.
These services can be used within the Swing Quicksearch. It is also possible to elaborate the results received from such services and use them inside Méthode documents.
This document is a step-by-step tutorial on how to integrate an external DAM service. To make this process easer, we are also integrating the "ResourceSpace" service as a complete example.
1. Set up the search proxy
Méthode Swing uses proxies to communicate to external services. This is necessary due to the Same-Origin Policy used by modern browsers.
The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. Same-origin Policy is used as a means to prevent some of the Cross-site Request Forgery attacks.
Proxies can be configured in Méthode Swing.
<!-- other configuration -->
<proxies>
<proxy>
<name>[PROXY-NAME]</name> <!-- e.g. resourcespace -->
<targetUri>http://192.168.203.129/resourcespace/plugins/api_search/</targetUri> <!-- e.g. destination target Uri -->
<useTemplate>false</useTemplate>
</proxy>
</proxies>
Important
|
The useTemplate param allows to use templates to build the URL. The following is an example of url which uses templates.
The new proxed URL must be called with ALL the parameters in its querystring, e.g. http://swing/[PROXY-NAME]/users/get?_port=8080&id=userID Note: if the parameter is missing, the URL will return an HTTP 500 error. Note: due to the nature of the Template Servlet, in this mode it is not possible to pass arrays as querystrings ( i.e. more than one querystring parameter with the same name ). |
Warning
|
[PROXY-NAME] must be equal to [DOMAIN-TYPE] (described in Domain configuration). |
2. Preparing the External DAM integration file
In general, all the extensions of Méthode Swing are places under
{SWING-APP}/plugins
So, all the Javascript described in the following sections should be placed under
{SWING-APP}/app/plugins/{EXTENSION-FOLDER}/{EXTENSION-NAME}.js
Caution
|
Do not use the word libs as an extension folder. The libs folder is reserved for loading external libs. See the proper documentation to obtain further info on the topic. |
Tip
|
DEBUG MODE: by default, all plugins are aggregated into a single plugins.js file at the Tomcat startup. When creating a plugin, it may be frustrating to restart the Tomcat Server every time a change is made. To avoid this, set the configuration property debugEnabled to true. Then, that extension will be loaded on every refresh of the page. |
Tip
|
In our example, it will be placed under {SWING-APP}/app/plugins/resourcespace/resourcespace.js. |
3. Set up the custom search
Swing Search system is modular. The following paragraph describes in details each module.
Search structure
Swing Search system is modular and consists in three main modules:
-
Search input (domains): the module covering the user input, the search domain, the search archives and the filters available.
-
Search compiler: a compiling system that validates and translates the input into a language which is understandable by the controller. (For example, the EOMDB compiler validates the input and translates a user search, such as "U.S. politics", into a XML for the Méthode Query).
-
Search controller: the module that, effectively, executes the search and retrieves the result.
When the user searches for something, the compiler validates the content. If content is not valid, the search input is warned and the search is not executed (i.e. the search controller is not even called). If the content is valid, the search controller tries to call the external search services and retrives the results.
When the results are available, they are processed by the preview engine that shows a small preview of each result. From that point, according to the current context (e.g. Editor area, …) and the actions which have been configured, the user can perform some specific operations.
Domain setup
Tip
|
Domain configuration follows the same properties as shown in the Search Configuration. However, here it must be specified as a Javascript object. |
Example
{
"name": "customtest",
"type": "customtest",
"label": "Local archive",
"icon": "emui-icon-database",
"itemsPerPage": 8,
"quicksearchLimit": 48,
"useExternalSuggestion": true,
"externalSuggestionURL": "http://suggestqueries.google.com/complete/search?q={data.value}&client=firefox&callback=?",
"conditions": [
{
"isDefault": true,
"value": "modified_lastdays:10"
},
{ "label": "Free search", "labelkey": "search.types.freesearch",
"icon": "icon-search", "value": "type:",
"type": "" },
{ "label": "Story", "labelkey": "search.types.story",
"icon": "emui-icon-newspaper", "value": "type:eom::story",
"type": "story" },
{ "label": "Images", "labelkey": "search.types.images",
"icon": "icon-picture", "value": "type:image",
"type": "image" }
],
"archives": [
{ "name": "production", "label": "Editorial",
"archive": "production@meth01_eomse1",
"isDefault": true, "visible": true, "enabled": true },
{ "name": "globecms", "label": "GlobeCMS",
"archive": "globecms@meth01_eomse1",
"isDefault": false, "visible": true, "enabled": true }
]
}
Tip
|
Please refer to the Search Configuration for a reference of the meaning of each property. Even though the examples are all in XML, the concepts are equal. |
To dinamically add a domain to the configuration, it is necessary to call the following Javascript function, inside your Javascript file:
eidosmedia.webclient.extensions.search.addDomain( /** domain settings **/ );
The domain behaviour must be defined in a JavaScript file and put inside the following path:
{SWING-APP}/app/plugins/{PROXY-NAME}
Domain controller can be configured outside {SWING-APP}. See the paragraph How to configure a domain controller in external folder for some tips in how to take advantage of this new configuration option.
Example: ResourceSpace integration
Note
|
the key searchTemplate will be explained in Search templates configuration, usage and creation. |
For our example we don’t need neither conditions nor archives, but the example contains them (commented) to simplify the code reuse.
// Add a new domain in the search dialog.
eidosmedia.webclient.extensions.search.addDomain({
"name": "resourcespace",
"type": "resourcespace",
"label": "ResourceSpace Search",
"icon": "icon-foursquare",
"itemsPerPage": 8,
"useExternalSuggestion": false,
"searchTemplate" : [
{ type: "rsimage", template: "search-preview-resourcespace.html" },
{ type: "rstext", template: "search-preview-resourcespace.html" }
],
"compiler": function( options, callbacks ) { /* ... SEE BELOW ... */ },
"controller": function( options, callbacks, ctx ) { /* ... SEE BELOW ... */ },
"allowImport": false, // Or it can be a function, see below
"correlateOnImport": true,
"getImportInfo": function( ctx ) { /* ... SEE BELOW ... */ }
/* It is possible to add Archives and conditions. Please refer to Domains configuration. */
});
Compiler setup
The Search Compiler validates the user input and translates into the language which is understood by the search controller.
As seen in the Search structure section, the compiler is a middle layer between the search component (a.k.a. the input form) and the search controller (a.k.a. the search engine). The Compiler can be used to perform any transformation of the search input to be passed into the controller, as well as to provide some sort of validation that, in case of not valid arguments, interrupts the search before it starts, so not even calling the server.
Such validation logic can easily be moved inside the search controller, nevertheless the user may find useful to separate the Compiler and the Controller logic.
The Search compiler is a Javascript function called as follows:
// ... other configuration
"compiler": function( options, callbacks ) {
/* ... CODE HERE ... */
},
// ... other configuration
The compiler is a Javascript function called with two main parameters:
-
options [JSON object] - information about the current search
-
callbacks [JSON object] - function to be called ( success and error)
options
-
conditions: user specified conditions
-
archives: subset of domain the user wants to limit the search to
-
searchType: the specific type of search
The compiler is called with the following options:
{
"domain": DOMAIN_NAME,
"input": "my search input",
"conditions": [ /* Array of conditions */ ],
"archives": [
"archive3"
],
"searchType": "image"
}
-
domain contains the domain name
-
input contains the search input
-
conditions contains all the conditions specified by the user (also archive and type, which are just a specific condition.
-
archives lists only the archives selected
-
searchType lists the type selected.
With this information, it is possible to call the service with the specific parameters.
callback
This is the function that is called when the validation is completed.
It MUST be called with the following parameters.
callback( result );
Where result should include at least all the properties of options plus, if an error occurred, the following two properties:
-
error: set to true
-
errorMessage: the error message.
Tip
|
If you want, you can now add any other property that will be directly passed to the Search Compiler. |
So, for example, a compiler that does absolutely nothing would be:
"compiler": function( options, callbacks ) {
var result = options;
// Some validation here...
// Return the result as is to the compiler
callback( result );
},
and, in case of error:
"compiler": function( options, callbacks ) {
var result = options;
// Some validation here...
// EXAMPLE
if (options.input === "FORBIDDEN") {
result.error = true;
result.errorMessage = "You cannot search for this term";
}
callback( result );
},
Important
|
If you don’t call the callback function, the search will never be executed! |
Important
|
If you don’t pass the required parameters to the Controller, this will not be able to perform the search! |
Example: ResourceSpace integration
Resource space does not need any specific validation, so there is nothing to configure and Méthode; Swing will simply go directly to the search Controller.
Controller setup
Controller is the most importart part of the search. Without a controller, the search cannot be executed and the results cannot be retrieved.
To add a controller, it is add a controller property to the Domain setup:
// ... other configuration
"controller" : function( options, callbacks, ctx ) {
/* ... SEE BELOW ... */
},
// ... other configuration
Note
|
Different domains of the same type have the same controller. So, it is the user choice to create different types for similar functionalities, or to have a single controller to behave differently according to the options. |
The controller is a Javascript function called with three main parameters:
-
options [JSON object] - information about the current search
-
callbacks [JSON object] - function to be called ( success and error)
-
ctx [JSON object] - the classic context object.
options
Same as the compiler options.
callbacks
Callbacks are Javascript function internally used to determine if the search has been successful or not.
The user is not required to know how the callbacks work, but they should be called as follows:
callbacks.success( [PARAMETERS] ); // in case of success.
callbacks.error( [PARAMETERS] ); // in case of error.
where:
-
[PARAMETERS] are either the items (in case of success) or the exception (in case of error) [ in any case, it is a JSON object ].
Success example:
callbacks.success( { items: items } );
Caution
|
Please maintain the structure of the items are shown in the example (a JSON object with items which is an array of objects). |
Error example:
callbacks.error( { message: 'Error during the search' } );
How to build a controller
The following code shows how a controller can be built. The code is well commented and should be easily understandable.
// Add a new controller for the search.
"controller": function( options, callbacks ) {
var API_KEY = 'V0aRlntBV163dNJK5prQv5E1IXNUwGKudTIGZcq8xissufD8lBpQ2I1TgkRn_Xlvm8RvL_ezBOzTOS4s4IV40g';
// If the user did not put any input, show an error.
// In this specific case (resourceSpace), search without terms is allowed,
// so the following code is commented
/*
if (!options.input) {
callbacks.error( { message: 'No input provided' } );
return;
}
*/
/*
Archive management
resourceSpace example did NOT use any archive, so this part is omitted.
Another example (such as wikipedia), used the archive to build the link, as shown
in the following (commented) example.
*/
/*
// Takes the first archive, or 'en' as default
var archive = (options.archives && options.archives.length) ? options.archives[0] : 'en';
// Build the url necessary for wikipedia.
var url1 = 'http://' + (archive || 'en') +
'.wikipedia.org/w/api.php?action=query&list=search&callback=&srsearch=' +
encodeURI(options.input) + '&format=json&rawcontinue&srprop=snippet';
*/
// Prepares the url
var url = eidosmedia.webclient.app.context + "/resourcespacesearch/";
// With the try..catch no error will escape!
try {
$.ajax({
url: url,
data: {
"key": API_KEY,
"search": options.input,
"prettyfieldnames": true,
"original": true
},
success: function( items ) {
var response = {};
response.items = items || [];
// Do something with the response...
// Prepare JSON ( see the next paragraph for that ).
// If we used a default template, we would have to adapt the response JSON
// to Swing Templates, as shown here.
/*
for( var j in response.items ) {
response.items[j].id = response.items[j]["original_link"];
response.items[j].type = "rsImage";
response.items[j].methodeType = "image";
response.items[j].title = response[j].Title;
response.items[j].hideStatus = true;
response.items[j].preview = response.items[j].content = response.items[j]["original_link"];
}*/
// OR
// If we used a custom template, we could just use the JSON 'as-is'
// REMEMBER TO SET AT LEAST ID AND TYPE FOR EACH ITEM.
for( var j in response ) {
response.items[j].id = response.items[j]["original_link"];
response.items[j].type = "rsImage";
response.items[j].methodeType = "image";
}
// Call the successful callback.
callbacks.success( response );
},
error: function( ex ) {
// Call the error callback.
callbacks.error( ex );
}
});
} catch( ex ) {
// Call the error callback.
callbacks.error( ex );
}
}
Controller setup: dynamic page load.
As of Swing 3.0.0, it is possible for custom domain to load only a subset of results. Everytime the user requires additional results, the controller is called again with specific paramers in order to allow the search of the required items only.
To do so, it is necessary to structure the response object adding two additional properties:
-
totalCount : this is the total number of results of the query if there were no limits.
-
resultCount: this is the number of results provided by the current query (e.g. items.length )
This allows Swing to understand that the search is passing a subset of a larger amount of results. The calculation of pages is done automatically.
When the user requires a new page, the controller is called again with the same parameters. However, the options parameter will have an additional property:
-
pageInfo.start : the number of the starting required result ( e.g. the "from" object )
-
pageInfo.end : the number of the end required result ( e.g. the "to" object )
Important
|
pageInfo is not passed in case of the first page. |
Here follows a pseudo-code example:
// Add a new controller for the search.
"controller": function( options, callbacks ) {
// other infos...
// PAGE MANAGEMENT
var hasPage = !!options.pageInfo;
// Prepares the url
var url = eidosmedia.webclient.app.context + "/resourcespacesearch/";
var request = {
"key": API_KEY,
"search": options.input,
"prettyfieldnames": true,
"original": true
}
if ( hasPage ) {
request.from = options.pageInfo.start;
request.to = options.pageInfo.end;
}
// With the try..catch no error will escape!
try {
$.ajax({
url: url,
data: request,
success: function( resp ) {
var response = {};
response.items = resp.items || [];
// Do something with the response...
if (!hasPage) {
// We pass the total amount of results to force dynamic pagination
response.totalCount = resp.totalResults;
response.resultCount = response.items.length;
}
// Call the successful callback.
callbacks.success( response );
},
error: function( ex ) {
// Call the error callback.
callbacks.error( ex );
}
});
} catch( ex ) {
// Call the error callback.
callbacks.error( ex );
}
}
4. How to structure results in JSON for Méthode Swing
JSON results must be structured accordingly to be correctly interpreted by Méthode Swing Search. In fact, each item must have an id and a type property. (And a methodeType property if the import is allowed).
Caution
|
It is certainly possible to specify one of the default Méthode types. However, this is strongly discouraged in order to avoid any possibility of overriding the original behaviour. |
Tip
|
Since the id and type properties are required, it is strongly advised (read: MUST) that:
Also, if the allowImport is enabled, the item should specify the correspondent methodeType. There are several different MethodeType supported values:
|
Having said that, the user has two possibilities:
-
use a default template. See below for further information.
-
use a custom template. See Search templates configuration, usage and creation for details on how to write the template.
5. Usage and creation of result templates
Documentation for this section is part of the general search documentation and is available here.
6. Import objects in a Méthode document
By specifying the allowImport property to the proper value, Méthode Swing automatically adds the possibility to download the object in the configured workfolder (according to the context: in Explorer Area, the current folder; in Editor Area, the configured workfolder of the current document).
allowImport can be a boolean, or a function which returns true if in that case the import is allowed, false otherwise. It is called with a parameter containing all the information about the item.
Tip
|
A common use for the function is to verify if to allow the import only for specific types. |
// ... other configuration
"allowImport": function( ctx ) {
// Allow import only for images.
if (ctx.activeObject.getInfo().type.toLowerCase() === 'rsimage') {
return true;
}
return false;
},
// ... other configuration
// OR
"allowImport": true / false
Furthermore, it is possible to specify the getImportInfo function, which is used to return the Import information. Consider the example:
{
// ... other configuration
"allowImport": function( ctx ) {
// Allow import only for images.
if (ctx.activeObject.getInfo().type.toLowerCase() === 'rsimage') {
return true;
}
return false;
},
// ... other configuration
"getImportInfo": function( ctx ) {
var objInfo = ctx.activeObject.getInfo();
// IMPORTANT. If the "url" is relative, this won't work.
// To obtain the absolute url, use the ctx.getAbsoluteUrl( url ) method.
return {
"url": ctx.getAbsoluteUrl( objInfo.original_url ),
"filename": objInfo.id + '.png', // See below
"conflictResolutionMode": 'conflict.user', // See below
"conflictAlternatives": ['conflict.autoRename', 'conflict.useExisting', 'conflict.replace', 'conflict.newVersion', 'conflict.doNotCreate'], // See below
"attributes": "Here you can specify the XML metadata",
"uniqueId": "Specify the uniqueness_string here",
"info": {
"otherCustomProperties": "Some value"
}
}
}
}
Caution
|
The function is not necessary, but if it is specified, it must return a JSON object with two parameters:
If specified, uniqueId (an optional String value that uniquely identifies a content and is demanded to be unique in a whole repository) property will be added to Méthode Unique Id. conflictResolutionMode allows to define the default behaviour when importing an item already existing. It can be one of 'conflict.autoRename', 'conflict.useExisting', 'conflict.replace', 'conflict.newVersion', 'conflict.doNotCreate' or a special value 'conflict.user' that shows a dialog and let the user decide how to handle the conflict. conflictAlternatives is used when conflictResolutionMode is 'conflict.user' and allows to filter the conflict resolution modes proposed to the user. NOTE: Methode Editorial API Server tries to understand the Methode Type from the URL extension. So, if the url is special (e.g. the result of a call, such as "http://www.myservlet.com/generatePreview.dll?id=dSDAWdsdqw12314", this won’t be recognized as an Image. In these cases, it is necessary to provide a suggested filename by adding the filename property to the getImportInfo result. |
Important
|
The allowImport and the getImportInfo receive the Context Object as the only parameter. For retrocompatibility, all methods and properties available in Methode Swing versions prior to 1.4.3 are still available, but it is strongly discouraged to use them. Instead, refer to Context object in search (ctx parameter) for further info on how to use the Context object. |
And that’s it! You can now import your custom content within Méthode. Good luck!
Additional properties
availableKeywords
availableKeywords property is an object structured as follows:
"availableKeywords":{
"keyword1":{ source:['suggestion1', 'suggestion2'] ,icon:'icon-save' },
"keyword2":{ source:[], icon: 'emui-icon-area-myarea' },
"keyword3":{ source:[], icon:null }
}
Each keyword has two properties:
-
source: a array of suggestions for that specific keyword
-
icon: an icon for the suggestion
The result is the following:
Context object in search (ctx parameter)
Context Object properties for the Search
The Search context has the following values:
Parameter | Values | Description |
---|---|---|
area.getName() |
"search" or "search" according to the position of the search. |
|
area.getContext() |
"modal" or "candidate" according to the position of the search. |
|
component.getType() |
"querypreview" or "quickpreview" or "contentanalyzer" according to the position in the search. |
|
component.getId() |
String |
Not available |
activeObject.getId() |
String |
Return the ID of the current object |
activeObject.getInfo() |
JSON |
Return the info of the current object |
activeObject.getType() |
JSON |
Return the type of the current object |
selection |
JSON Array |
Not available (empty array) |
Complete Resource Space configuration
/**
* Plugin name: ResourceSpace
* The plugin adds the possibility to integrate Resource Space DAM
*/
// Add a new domain in the search dialog.
eidosmedia.webclient.extensions.search.addDomain({
"name": "resourcespace",
"type": "resourcespace",
"label": "ResourceSpace Search",
"icon": "icon-foursquare",
"itemsPerPage": 8,
"allowNoInput": true,
"useExternalSuggestion": false,
"searchTemplate" : [{ type: "rsimage", template: "search-preview-image.html" }],
/* It is possible to add Archives and conditions. Please refer to Domains configuration. */
"allowImport": function( item ) {
return true;
},
"getImportInfo": function( item ) {
var objInfo = ctx.activeObject.getInfo();
return {
"url": objInfo.original_url,
"attributes": "Here you can specify the XML metadata",
"uniqueId": "Specify the uniqueness_string here",
"info": {
"otherCustomProperties": "Some value"
}
}
},
"controller": function( options, callbacks ) {
var API_KEY = 'V0aRlntBV163dNJK5prQv5E1IXNUwGKudTIGZcq8xissufD8lBpQ2I1TgkRn_Xlvm8RvL_ezBOzTOS4s4IV40g';
// If the user did not put any input, show an error.
// In this specific case (resourceSpace), search without terms is allowed,
// so the following code is commented
/*
if (!options.input) {
callbacks.error( { message: 'No input provided' } );
return;
}
*/
/*
Archive management
resourceSpace example did NOT use any archive, so this part is omitted.
Another example (such as wikipedia), used the archive to build the link, as shown
in the following (commented) example.
*/
/*
// Takes the first archive, or 'en' as default
var archive = (options.archives && options.archives.length) ? options.archives[0] : 'en';
// Build the url necessary for wikipedia.
var url1 = 'http://' + (archive || 'en') +
'.wikipedia.org/w/api.php?action=query&list=search&callback=&srsearch=' +
encodeURI(options.input) + '&format=json&rawcontinue&srprop=snippet';
*/
// Prepares the url
var url = eidosmedia.webclient.app.context + "/resourcespacesearch/";
// With the try..catch no error will escape!
try {
$.ajax({
url: options.getUrl(),
data: {
"key": API_KEY,
"search": options.input,
"prettyfieldnames": true,
"original": true,
"previewsize": "thm"
},
success: function(response) {
// Do something with the response...
// Prepare JSON ( see the next paragraph for that ).
// If we used a default template, we would have to adapt the response JSON
// to Swing Templates, as shown here.
for( var j in response ) {
response[j].id = response[j]["original_link"];
response[j].type = "rsImage";
response[j].methodeType = "image";
response[j].title = response[j].Title;
response[j].hideStatus = true;
response[j].preview = response[j].content = response[j]["preview"];
}
// OR
// If we used a custom template, we could just use the JSON 'as-is'
// REMEMBER TO SET AT LEAST ID AND TYPE AND METHODE TYPE FOR EACH ITEM.
//for( var j in response ) {
// response[j].id = response[j]["original_link"];
// response[j].type = "rsImage";
// response[j].methodeType = "image";
//}
// Call the successful callback.
callbacks.success( { items: response } );
},
error: function( ex ) {
// Call the error callback.
callbacks.error( ex );
}
});
} catch( ex ) {
// Call the error callback.
callbacks.error( ex );
}
}
});
How to configure a domain controller in external folder
Additional domain controllers may be made available to Swing application by defining one or more nested components in Swing web context in server.xml. (for further details on Tomcat 9.x Resources configuration, please refer to Resources configuration).
This is an example of the external domain controller configuration.
<Context docBase="com.eidosmedia.webclient.web-app"
path="/swing" reloadable="false">
<Resources
className="org.apache.catalina.webresources.StandardRoot">
<PreResources
className="org.apache.catalina.webresources.DirResourceSet"
base="/methode/meth01/extension/plugins" readOnly="true"
webAppMount="/app/plugins" />
</Resources>
</Context>
Custom Filters
Swing allows to design and add custom filters to your searches.
Configure a custom filter
Filters are made of an HTML template and a related JS file.
Caution
|
Default templates are put in the base folder {SWING-APP}/config/templates/search/filters For custom templates, it is recommended ( read mandatory ) that you put them in a specific folder: {SWING-APP}/config/templates/search/filters/{TEMPLATE-FOLDER} |
Filters can be configured outside {SWING-APP}. See the paragraph How to configure search filters in external folder for some tips in how to take advantage of this new configuration option.
Design the template
The template is a simple HTML file.
There are no real boundaries inside the template, but it is strongly suggested to follow the guidelines below.
There are various attributes to be aware of:
Attribute | Description |
---|---|
data-xvalue |
This is the main parameter. It is the one that defines the type of filter. See Supported keywords for a list of available filters. |
data-preload |
In specific cases ( e.g. owner, status, type…) if the value is true, Swing preloads the component with all the available values. See Supported keywords for a list of the keywords with support data-preload. |
data-xprefix |
This attribute is used to specify fixed prefix to the rules. For example, see metadata keyword. |
data-default |
This attribute is used to set a default value for the filter (e.g. a text for the input element, a date for the calendar, etc). The value is also used after a reset. |
data-identifier |
This attribute is used to identify a field. It is used in the setSearchValue method. See onLoad to see the method in use. |
data-operator |
Possible values are "AND", "OR", "NOT". If not specified, the condition is added with an AND operator. See the Warning below for further info. |
data-block-operator |
Possible values are "AND", "OR", "NOT". If not specified, the condition is added with an AND operator. See the Warning below for further info. |
Warning
|
data-operator and data-block-operator are different. data-block-operator should be used ONLY with SELECT MULTIPLE or BOOTSTRAP TAGSINPUT or, in general, with any element which returns multiple values. data-block-operator defines the operator with which the whole selection is added to the query, while data-operator defines which operator is used to join each of the selected values. For example, the following HTML code:
The result will be AND ( EOM::Story OR Image ). And the following:
The result will be AND ( NOT EOM::Story NOT Image ). |
Style guidelines
As will be clear from the predefined HTML suggestions, a "filter block" should be created as follows:
<div class="emui-row">
<div class="emui-title">{BLOCK-TITLE}</div>
<div class="emui-content">
{BLOCK-CONTENT}
</div>
</div>
Inside the block content, it is suggested to use standard HTML5 components, such as:
Input box
<input type="text" class="form-control" data-xvalue="{XVALUE}" placeholder="My placeholder" data-operator="AND"/>
Select, dropdown
<select class="form-control" data-xvalue="{XVALUE}" data-operator="AND">
<option value="">Any workflow</option>
<option value="NewsFlow/Editing">NewsFlow/Editing</option>
<option value="NewsFlow/For Approval"></option>
</select>
Warning
|
It is important to insert an option without value ( or, better, value set to "" ), so the the user can, if necessary, exclude that particular filter. |
Select multiple
Select multiple needs an additional data-block-operator attribute ( if omitted, default is AND ). See the specific paragraph for further information.
<select class="form-control" multiple data-identifier="custom-select-multiple" data-xvalue="type" data-operator="NOT" data-block-operator="AND">
<option>EOM::Story</option>
<option>EOM::CompoundStory</option>
<option>EOM::Webpage</option>
<option>Image</option>
</select>
The result will be AND ( NOT EOM::Story NOT Image ).
Radio buttons
It is possible to use radio buttons for some reasons, like enabling or disabling some fields. If you want to save the value, add a data-identifier attribute, without data-xvalue. Please stick to Bootstrap 3 syntax for radio buttons.
<!-- Sample radio button -->
<div class="emui-row">
<div class="emui-title">Options radios</div>
<div class="emui-content">
<div class="radio">
<label>
<input type="radio" name="optionsRadios" data-identifier="optionsRadios1" value="option1" checked>
Option one is this and that—be sure to include why it's great
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="optionsRadios" data-identifier="optionsRadios2" value="option2">
Option two can be something else and selecting it will deselect option one
</label>
</div>
<div class="radio disabled">
<label>
<input type="radio" name="optionsRadios" data-identifier="optionsRadios3" value="option3" disabled>
Option three is disabled
</label>
</div>
</div>
</div>
DatePicker and DateTimePicker components
It is possible to use the "datepicker" component using the following HTML. To use the dateTimePicker, write "datetimepicker" in the data-emui-type attribute.
Warning
|
It is extremely important to decide where to put the data-xvalue attribute in the case of datepicker or datetimepicker. If, as in the example, it is places in the input field, the value returned is the Date converted in the format specified by the data-format attribute. If, instead, it is placed directly in the div with the data-emui-type attribute, the value returned is a Javascript Date Object. See [range] for a better example of this second usage. |
Example with data-xvalue in the input field
<div class="input-append date" data-emui-type="datepicker">
<input data-format="dd-MM-yyyy" class="form-control" placeholder="Created" data-xvalue="created" type="text" data-operator="AND"></input>
<span class="add-on"><i data-date-icon="icon-calendar"></i></span>
</div>
In this case, when doing ctx.getSearchValue(), a string with the selected format will be returned.
Example with data-xvalue in the date field
<div class="input-append date" data-emui-type="datepicker" data-xvalue="created" data-operator="AND">
<input class="form-control" placeholder="Created" type="text"></input>
<span class="add-on"><i data-date-icon="icon-calendar"></i></span>
</div>
In this case, when doing ctx.getSearchValue(), a Javascript Date Object will be returned. Plus, the calendar will have the localized format specified in the Configuration.
Tip
|
See [created] for an example of these components. |
Bootstrap tagsinput
Swing filters natively support Bootstrap Tags input (Bootstrap Tags Input). Bootstrap Tags Input needs an additional data-block-operator attribute ( if omitted, default is AND ). See the specific paragraph for further information.
<div class="emui-row">
<div class="emui-title">TYPES</div>
<div class="emui-content">
<input type="text" value="" data-role="tagsinput" data-identifier="type-tagsinput" data-xvalue="type" data-operator="OR" data-operator="AND" />
</div>
</div>
It also requires a Javascript initialization.
{
// ...
onLoad: function( ctx, params ) {
$('[data-identifier="type-tagsinput"]', params.panel).tagsinput({
typeahead: {
source: [ "EOM::Story", "Image", "EOM::MediaGallery", "EOM::WebPage" ]
}
});
},
// ...
}
Reset filter button
A "Reset filter" button is automatically added in the filter template.
Tip
|
Use the attribute data-default if you want the various filters to have a specific value after reset. |
CSS guidelines
Tip
|
Use the form-control class to fix the width of the components to 100% of the filter panel. |
Configure the JS file
To add a filter, the JS file should be structured as follows.
eidosmedia.webclient.search.addFilter( options );
In detail, the options are:
/**
* CUSTOM FILTER
* @name: Swing custom filter
*/
eidosmedia.webclient.search.addFilter({
// @property "domain": {string} - it corresponds to the value configured in the <name> parameter of a specific search domain to apply the filter to
// @property "domainType": {string} - it corresponds to the value configured in the <type> parameter of one or more searchs domain. So, if specified the filter is applied to all the domains with the same type
// @required - only one parameter between domain or domainType
"domain": "eomdblocal",
// "domainType": "eomdb",
// @property "template": {string} - the path to the search template. Path is relative to the 'config/search/filters/' folder.
// @required
template: 'swing-filter.html',
/**
* Function called after loading the template, but BEFORE loading the query
* use it to add listeners.
* @param {ContextObject}
* @param {Object} params - the params of the search element
* @param {Function} params.setSearchValue(identifier, value) - a method that allows to set a value for a specific field with the specified data-identifier.
* @param {Node} params.panel - the current DOM node for the search filter panel
*/
onLoad: function( ctx, params ) {
// ...
},
/**
* Function called whenever a condition in the search is changed.
* @param {ContextObject}
* @param {String} condition - the string with the changed condition
*/
onConditionChange: function( ctx, condition ) {
console.log('CONDITION CHANGED');
console.log(condition)
},
/**
* Function called after loading the query
* use it to fix the custom elements.
* @param {ContextObject}
* @param {Object} params - the params of the search element
* @param {Node} params.el - the current DOM node analized
*/
onQueryLoaded: function( ctx, params ) {
// ...
},
/**
* This function must return the value in the form <key>:<value> for each of the
* elements configured.
* @method getSearchValue
* @param {Object} params - the params of the search element
* @param {Node} params.panel - the current DOM node for the search filter panel
* @param {Node} params.el - the current DOM node analyzed
* @param {String} params.dataId - the value of the data-xvalue attribute
* @param {String} params.dataIdentifier - the value of the data-identifier attribute
* @param {Function} getSearchValue() - the method that returns the search value calculated by default.
* @param {Function} params.setSearchValue(identifier, value) - a method that allows to set a value for a specific field with the specified data-identifier.
*/
getSearchValue: function( ctx, params ) {
// ...
}
});
Each parameter is detailed below.
domain and domainType
The filter can be coupled with either a domain or a domainType. In the latter case, all domain of the same type will share the same filter.
The domain parameter requires the same name configured in the Search configuration. See Domains configuration for further details. Please see the box below for information regarding the default-folder
filter.
The domainType parameter can be one of the following: eomdb
.
Important
|
By specifying Under filter/default-folder-filter/ folder, it is possible to find the Swing default folder filter. Please use it as a reference. |
template
This property defines the template for the filter.
{
// ...
template: "test.html",
// ...
}
Warning
|
The path of the template starts from the search/filters/ folder. If you placed the template in a subfolder (e.g. search/filters/testfilter/), the template should be valued as "testfilter/test.html". |
onLoad
onLoad is a function called when the filter is loaded for the first time. This function is called AFTER the DOM has been filled, so that all the DOM elements of the filter are available. This function is called BEFORE the query has been loaded. It can be used to add custom listeners for events.
Tip
|
Unless the filter is heavily customized, the onLoad function can be ignored. |
It is called with 2 parameters:
-
ctx: the Context Object. See Context Object documentation for further details. In this case, though, the context object has neither activeObj nor selection, and only contains information on the Swing area.
-
params. It is a Javascript Object with 2 properties:
-
panel: the DOM reference to the filter panel.
-
setSearchValue: a method to set the value of a field in the Search filter. See the following example for further details.
-
{
onLoad: function( ctx, params ) {
var $panel = $( params.panel );
// Do some things...
// setSearchValue( identifier, value ) - sets the value of a field which has a 'data-identifier' attribute;
params.setSearchValue('createdField', '09-08-2015')
}
}
Tip
|
Return value of the function is not important. |
onUpdateFilterElements
onUpdateFilterElements is a function called whenever the filter elements should be updated.
It is called with the following parameters:
-
ctx: the Context Object. See Context Object documentation for further details. In this case, though, the context object has neither activeObj nor selection, and only contains information on the Swing area.
-
panel: the DOM reference to the filter panel.
-
filters. It is an array of Javascript Object with 2 main properties:
-
identifier: the filter indetifier.
-
value: the related filter value.
-
{
onUpdateFilterElements: function( ctx, panel, filters ) {
for (let j = 0; j < filters.length; j++) {
const filterElement = filters[j];
if (filterElement.identifier == 'author') {
const value = filterElement.value;
}
}
}
}
Tip
|
Return value of the function is not important. |
onConditionChange
onConditionChange is a function called whenever a condition inside the search is changed (the ones on the top left dropdown). It can be used to change the filter HTML according to a specific condition.
It is called with 2 parameters:
-
ctx: the Context Object. See Context Object documentation for further details. In this case, though, the context object has neither activeObj nor selection, and only contains information on the Swing area.
-
params. It is a Javascript Object with 2 properties:
-
panel: the DOM reference to the filter panel.
-
condition. The condition that has changed. (As a string).
-
{
onConditionChange: function( ctx, params ) {
if (params.condition === 'type:image') {
// I'm selecting, for example the condition image.
// Show only the part related to the image.
$(params.panel).find('[data-filter="image"]').show();
}
}
}
Tip
|
Return value of the function is not important. |
onQueryLoaded
onQueryLoaded is a function called AFTER the query has been loaded. It can be used to customize behaviour after the query values have been loaded.
Tip
|
Unless the filter is heavily customized, the onQueryLoaded function can be ignored. |
It is called with 2 parameters:
-
ctx: the Context Object. See Context Object documentation for further details. In this case, though, the context object has neither activeObj nor selection, and only contains information on the Swing area.
-
params. It is a Javascript Object with 2 properties:
-
panel: the DOM reference to the filter panel.
-
setSearchValue: a method to set the value of a field in the Search filter. See the following example for further details.
-
{
onQueryLoaded: function( ctx, params ) {
// ...
}
}
Tip
|
Return value of the function is not important. |
getSearchValue
/**
* This function must return the value in the form <key>:<value> for each of the
* elements configured.
* @method getSearchValue
* @param {Object} params - the params of the search element
* @param {Node} params.panel - the current DOM node for the search filter panel
* @param {Node} params.el - the current DOM node analyzed
* @param {String} params.dataId - the value of the data-xvalue attribute
* @param {String} params.dataIdentifier - the value of the data-identifier attribute
* @param {Function} params.getSearchValue() - the method that returns the search value calculated by default.
* @param {Function} params.setSearchValue(identifier, value) - a method that allows to set a value for a specific field with the specified data-identifier.
*/
getSearchValue: function( ctx, params ) {
/*
* ctx object, in this case, contains only info about the current view and tab.
*/
/*
* Use this method ONLY if you need to perform further elaborations ( e.g. in case
* you don't want to pass some values, or in case this element is hidden but
* you still want to pass it, or in case of multiple connected inputs to produce
* a single value ).
*/
/*
* IMPORTANT
* If this value must not be used for the query, return null.
*/
// EXAMPLE: force Globe/Images folder.
if ( params.dataId === 'restrictto' ) {
return 'restrictto:/Globe/Images';
} else if ( params.dataId === 'created' ) { {
// EXAMPLE: let's ignore this value
return null;
} else {
// Returns the value as calculated by Swing.
return params.getSearchValue();
}
}
Important
|
As it will be clear from the Supported keywords paragraph, the filters are built as a set of <key>:<value>. This is done by finding all the DOM elements with data-xvalue attribute, and elaborating their contents. This is done automatically for simple elements such as the one shown in the documentation. For more complex elements, it is possible to override the default behaviour with this getSearchValue function. |
It is called with 2 parameters:
-
ctx: the Context Object. See Context Object documentation for further details. In this case, though, the context object has neither activeObj nor selection, and only contains information on the Swing area.
-
params. It is a Javascript Object with 4 properties:
-
{Node}
el: the DOM reference to the current filter ( the element which has the data-xvalue attribute ). -
{Node}
panel: the DOM reference to the filter panel -
{String}
dataId: the value of the data-xvalue attribute. It is the current key which is processed. -
{String}
dataIdentifier - the value of the data-identifier attribute. -
{Function}
getSearchValue: a function which builds the string in the correct format ( <key>:<value> ). -
{Function}
setSearchValue( identifier, value ): a method to set the value of a filter with a specific data-identifier attribute.
-
Tip
|
Unless the filter is heavily customized, the getSearchValue function can be ignored. |
Warning
|
If you want a specific filter to be ignored, the return value of the function should be null. |
Supported keywords
Warning
|
The supported keywords are meaningful for EOMDB searches only. If you want to use filters for custom domains, feel free to use any keyword you prefer. The filters will be passed in the conditions array of the Search Controller (options parameter). See Search controller documentation for further details. |
Keyword | Description |
---|---|
|
Returns only the objects of a given channel. If userchannel is used, only the channels available to the current user are visible. |
|
Search a specific text in the content of an object. |
|
Search for a text in both content and metadata. |
|
Given a date, returns the objects created in that period. |
|
Allow to obtain the documents created in the last N days |
|
See user. |
|
Allow to insert a specific xml in the query. Please use it with moderation. |
|
Given a date, returns the objects whose issue date is in that period. |
|
Returns the objects last modified by a specific user. |
|
Limits the results to a specific number. |
|
Search for objects locked by a given user |
|
Search a specific value in a given xpath. |
|
Search a specific value in a given xpath, with the "range" operator ( inside the se:attributes tag ) |
|
Given a date, returns the objects modified in that period. |
|
Allow to obtain the documents modified in the last N days |
|
See user. |
|
See metadatarange. |
|
Returns the objects inside a path. |
|
Complete sorting mechanism. |
|
Simple descending sort according to a parameter in the ObjectInfo. |
|
Search objects with a given status ( workflow ). |
|
Returns only the objects of a given type. |
|
Allow to search within the usage tickets. |
|
Search for objects created by a given user |
|
channel. |
|
See status. |
|
Returns the objects inside a workfolder. |
channel
Returns only the objects of a given channel.
Syntax
channel:(CHANNEL) userchannel:(CHANNEL)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). |
Tip
|
userchannel differs from channel in the fact that only the channels relative to the current user are available.. |
Suggested HTML implementations
Free channel input
<div class="emui-row">
<div class="emui-title">Channel</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="channel" placeholder="Channel" data-operator="AND"/>
</div>
</div>
Choice from a list of channels
<div class="emui-row">
<div class="emui-title">Channel</div>
<div class="emui-content">
<select data-xvalue="channel" class="form-control" data-operator="OR">
<option value="">All channels</options>
<option value="Globe-Print">Globe-Print</options>
<option value="Globe-Web">Globe-Web</options>
</select>
</div>
</div>
Preload user channels (ONLY for userchannel keyword)
<div class="emui-row">
<div class="emui-title">Channel</div>
<div class="emui-content">
<select data-xvalue="userchannel" class="form-control" data-preload="true" data-operator="OR">
</select>
</div>
</div>
Warning
|
In case of userchannel keyword, it is possible to use data-preload="true". In that case, only the current user’s channels are available. |
content
Search a specific text in the content of an object.
Syntax
content:"CONTENT"
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). |
Suggested HTML implementations
<div class="emui-row">
<div class="emui-title">Content</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="content" placeholder="Content"data-identifier="contentField1"/>
</div>
</div>
contentmetadata
Search for a text in both content and metadata.
Syntax
contentmetadata:"CONTENT"
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). |
Suggested HTML implementations
See content for a suggested implementation: please remember to replace data-xvalue="content" with data-xvalue="contentmetadata".
created_lastdays
Allow to obtain the documents created in the last N days
Syntax
created_lastdays:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any numeric value. |
creator
See user, creator, owner.
freexml
Allow to insert a specific xml in the query. Please use it with moderation.
Syntax
freexml:"CONTENT"
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Note: please use single quotes when a double quote is used inside the value. |
Tip
|
In case of freexml, double quotes need to be replaced by @@. Alternatively, CDATA can be used to wrap "content".
|
Suggested HTML implementations
If checked, only items with an issue date are searched.
<div class="emui-row">
<div class="emui-content">
<div class="checkbox">
<label>
<input type="checkbox" data-xvalue="freexml" value="<SysAttributes><props><productInfo><issueDate q:op='EXIST'/></productInfo></props></SysAttributes>"/>
Only items with issue date
</label>
</div>
</div>
</div>
Advanced HTML Sample
Here follows a complex example that makes use of freexml to search into Virtual Attributes according to the user input.
<div class="emui-row">
<div class="emui-title">Owner Team</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="oteamVA" />
</div>
</div>
<div class="emui-row">
<div class="emui-title">C Team</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="cteamVA" />
</div>
</div>
<!-- hidden field for virtual-attributes existence -->
<input type="hidden" data-identifier="vaexist" data-xvalue="freexml" />
The javascript part must be included within the Filter definition.
getSearchValue: function( ctx, params ) {
// Example to manage the virtual attributes
if (params.dataId === 'oteamVA') {
// Saves for later reuse
this.oTeam = params.getSearchValue();
return null;
} else if (params.dataId === 'cteamVA') {
// Saves for later reuse
this.cTeam = params.getSearchValue();
return null;
} else if (params.dataIdentifier === 'vaexist') {
var xml = "<va xmlns:eom='http://www.eidosmedia.com/eom'>" +
'<parent_uuid>fbed282e-35e2-11e2-9e81-0545e1a77e80</parent_uuid>' +
(this.oTeam ? '<oteam>' + this.oTeam + '</oteam>' : '') +
(this.cTeam ? '<cteam>' + this.cTeam + '</cteam>' : '') +
'<vid>3</vid>' +
'<vt>1511298626</vt>' +
'<vm>eidosmedia_support</vm>'
'</va>';
return xml;
}
return params.getSearchValue();
}
lastmodifier
Returns the objects last modified by a specific user.
Syntax
lastmodifier:(USER|myself)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Return the objects modified by the specified user. |
|
|
Return the objects modified by the current user |
Suggested HTML implementations
See user, creator, owner. The supported value and the HTML implementations are the same. Please remember to replace "owner", "user" or "creator" with "lastmodifier".
limit
Limits the results to a specific number.
Syntax
limit:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
Any numeric value |
|
Suggested HTML implementations
<div class="emui-row">
<div class="emui-title">Limit results</div>
<div class="emui-content">
<input type="number" class="form-control" data-xvalue="limit" min="0" max="5000"/>
</div>
</div>
locker, lockedby
Search for objects locked by a given user
Syntax
locker:(USER|myself)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Return the objects locked by the specified user. |
|
|
Return the objects locked by the current user |
Tip
|
|
Suggested HTML implementations
See user, creator, owner. The supported value and the HTML implementations are the same. Please remember to replace "owner", "user" or "creator" with "locker".
metadata
Search a specific value in a given xpath.
Syntax
metadata:"CONTENT"
Values
Keyword | Example | Description |
---|---|---|
|
metadata:"{{SETTINGS}}/Metadata/Editorial/ContentType=my value here" |
Any string value (with quotes if there is a space). |
Suggested HTML implementations
<div class="emui-row">
<div class="emui-title">Metadata</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="metadata" placeholder="Metadata" data-identifier="metadataField1"/>
</div>
</div>
If you want the user to put only the value, because the x-path is already defined ( and should not be changed ), use the data-xprefix attribute, as in the following example:
<div class="emui-row">
<div class="emui-title">Editorial/ContentType</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="metadata" data-xprefix="/Editorial/ContentType=" placeholder="ContentType"/>
</div>
</div>
In this second case, the user will only need to write the value of the /Editorial/ContentType/ xpath.
Important
|
It is possible to specify additional properties within the metadata keyword. At the moment, the only supported setting is the search operator. To configure it, add {{op=MATCH}} in the data-prefix or to the value of the metadata. The content inside the {{ … }} will be processed and all the settings inside applied to the search. Currently supported settings are:
A sample with settings:
|
metadatarange
Search a specific value in a given xpath, with the "range" operator ( inside the se:attributes tag )
Syntax
metadatarange:"{X-PATH}={VALUE}"
Values
Keyword | Example | Description |
---|---|---|
|
|
See previous example. Note: Quotes are mandatory. If the value contains double quotes, use single quotes instead. |
Important
|
The RANGE value must be in the following format: YYYYMMDDhhmmss;YYYYMMDDhhmmss. |
Suggested HTML implementations
See Modified: Interval of dates for a sample implementation.
In this example, we are creating a "Created range" filter, allowing the user to specify both date and time. Please notice that:
Tip
|
|
Javascript
See Modified: Interval of dates for a sample implementation. Please refer only to the first part of the getSearchValue function.
Modified: Interval of dates
With this filter implementation, it is possible to play a little bit with the fields to allow the use of an interval of dates.
Let’s see a complete example:
HTML
<!-- MODIFIED -->
<div class="emui-row">
<div class="emui-title">Modified</div>
<div>
<div class="emui-content" style="width: 40%;float: left;">
<div class="emui-title">From:</div>
<div class="input-append date" data-emui-type="datepicker" data-xvalue="modified-date-from">
<input id="modified-date-from" class="form-control" placeholder="From" type="text" data-identifier="fromField1"></input>
<span class="add-on"><i data-date-icon="icon-calendar"></i></span>
</div>
</div>
<div class="emui-content" style="width: 40%;float: left; margin-left:30px">
<div class="emui-title">To:</div>
<div class="input-append date" data-emui-type="datepicker" data-xvalue="modified-date-to">
<input id="modified-date-to" class="form-control" placeholder="To" type="text" data-identifier="toField1"></input>
<span class="add-on"><i data-date-icon="icon-calendar"></i></span>
</div>
</div>
<div class="emui-content" style="display: none; visibility: hidden;">
<div class="input-append date" data-emui-type="datepicker" data-xvalue="modified">
<input id="date-to" class="form-control" type="text" data-identifier="modifiedField1"></input>
</div>
</div>
</div>
</div>
Warning
|
It is extremely important to decide where to put the data-xvalue attribute in the case of datepicker or datetimepicker. If, as in the example, it is places in the input field, the value returned is the Date converted in the format specified by the data-format attribute. If, instead, it is placed directly in the div with the data-emui-type attribute, the value returned is a Javascript Date Object. |
Tip
|
In this case, the data-xvalue is placed in the DIV element of the datepicker. |
Javascript
// NOTE: We are including ONLY the "getSearchValue" method of the Javascript file. The rest looks the same as documented below.
getSearchValue: function(ctx, params) {
/*
* ctx object, in this case, contains only info about the current view and tab.
* Use this method ONLY if you need to perform further elaborations ( e.g. in case
* you don't want to pass some values, or in case this element is hidden but
* you still want to pass it, or in case of multiple connected inputs to produce
* a single value ).
*/
/* EXAMPLE WITH DATA-XVALUE IN THE DATEPICKER DIV. A DATE OBJECT IS RETURNED. */
// Does nothing.
if (params.dataId === 'modified-date-from') {
// First, save the date-from value for later
this.dateFrom = null;
if(params.getSearchValue() !== null){
this.dateFrom = params.getSearchValue()[0];
}
// We return null because we don't want it to be processed by the filter engine.
return null;
}
else if (params.dataId === 'modified-date-to') {
// Then, save the date-to value for later
this.dateTo = null;
if(params.getSearchValue() !== null){
this.dateTo = params.getSearchValue()[0];
}
// We return null because we don't want it to be processed by the filter engine.
return null;
} else if (params.dataId === 'modified') {
// At last, I have the hidden "modified" field, which I can build as desired.
if (this.dateFrom === null && this.dateTo === null) {
// User did not specify anything. We don't specify the "modified" field
return null;
} else if (this.dateFrom !== null && this.dateTo !== null) {
// User specified both the "from" date and the "to" one.
// We build the modified value as "DATEFROM;DATETO";
/* NOTE: IN CASE OF RANGE / METADATARANGE FILTER, the format MUST BE YYYYMMDDHHmmss instead of YYYYMMDD */
return moment(this.dateFrom).format('YYYYMMDD') + ';' + moment(this.dateTo).format('YYYYMMDD');
} else if (this.dateFrom === null) {
// User specified ONLY the "to" date.
// We can decide that, in this case, the from date is a year before.
var today = new Date();
var yyyy = today.getFullYear() - 1;
this.dateFrom = moment(today).year(yyyy).toDate();
/* NOTE: IN CASE OF RANGE / METADATARANGE FILTER, the format MUST BE YYYYMMDDHHmmss instead of YYYYMMDD */
return moment(this.dateFrom).format('YYYYMMDD') + ';' + moment(this.dateTo).format('YYYYMMDD');
} else {
// User specified ONLY the "from" date.
// We can decide that, in this case, the to date is today.
var today = new Date();
this.dateTo = moment(today).toDate();
/* NOTE: IN CASE OF RANGE / METADATARANGE FILTER, the format MUST BE YYYYMMDDHHmmss instead of YYYYMMDD */
return moment(this.dateFrom).format('YYYYMMDD') + ';' + moment(this.dateTo).format('YYYYMMDD');
}
}
else {
// In any other case, for any other field, we return the value inserted by the user.
return params.getSearchValue();
}
/* ALTERNATIVE EXAMPLE WITH DATA-XVALUE IN THE INPUT DATEPICKER. A STRING IS RETURNED. */
if (params.dataId === 'modified-date-from') {
// First, save the date-from value for later
this.dateFrom = params.getSearchValue();
// We return null because we don't want it to be processed by the filter engine.
return null;
}
else if (params.dataId === 'modified-date-to') {
// Then, save the date-to value for later
this.dateTo = params.getSearchValue();
// We return null because we don't want it to be processed by the filter engine.
return null;
}
else if (params.dataId === 'modified') {
// At last, I have the hidden "modified" field, which I can build as desired.
if (this.dateFrom === null && this.dateTo === null) {
// User did not specify anything. We don't specify the "modified" field
return null;
} else if (this.dateFrom !== null && this.dateTo !== null) {
// User specified both the "from" date and the "to" one.
// We build the modified value as "DATEFROM;DATETO";
return this.dateFrom + ';' + this.dateTo;
} else if (this.dateFrom === null) {
// User specified ONLY the "to" date.
// We can decide that, in this case, the from date is a year before.
var today = new Date();
var yyyy = today.getFullYear() - 1;
var newDateFrom = yyyy + '' + '0101';
// We build the new interval.
return newDateFrom + ';' + this.dateTo;
} else {
// User specified ONLY the "from" date.
// We can decide that, in this case, the from date is 15 days after today.
var today = new Date();
today.setDate(today.getDate() + 15);
var dd = today.getDate();
var mm = today.getMonth() + 1;
if (dd < 10) dd = '0'+ dd;
if (mm < 10) mm = '0'+ mm;
var newDateTo = today.getFullYear() + '' + mm + dd;
return dateFrom + ';' + newDateTo;
}
} else {
// In any other case, for any other field, we return the value inserted by the user.
return params.getSearchValue();
}
}
Explanation
Tip
|
We are exploiting the fact that the filter engine processes fields in the order they appear. So, at first we include two fields, whose data-xvalue attribute is modified-date-from and modified-date-to. Then, we include a hidden field named modified, which is the supported keyword. By hiding it, we prevent the user from filling it. By including it, the modified field will be processed exactly like any other, so we can process it in the Javascript file, as presented. |
modified_lastdays
Allow to obtain the documents modified in the last N days
Syntax
modified_lastdays:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any numeric value. |
owner
See user, creator, owner.
range
See metadatarange.
restrictto
Returns the objects inside a path.
Syntax
restrictto:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
Any string value (with quotes if there is a space). |
|
Suggested HTML implementations
Free input
<div class="emui-row">
<div class="emui-title">Restrict to path (and subfolders)</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="restrictto" placeholder="Path" />
</div>
</div>
Choice from a list
<div class="emui-row">
<div class="emui-title">Restrict to path (and subfolders)</div>
<div class="emui-content">
<select data-xvalue="restrictto" class="form-control">
<option value="">All paths</options>
<option value="/Globe/Stories/Politics">/Globe/Stories/Politics</options>
<option value="/Globe/Stories/Sport">/Globe/Stories/Sport</options>
</select>
</div>
</div>
sort
Complete sorting mechanism.
Syntax
sort:"{X-PATH};{VALUE}"
Values
Keyword | Example | Description |
---|---|---|
|
|
See previous example. Note: Quotes are mandatory. If the value contains double quotes, use single quotes instead. |
Tip
|
In
|
Suggested HTML implementations
Free input
<div class="emui-row">
<div class="emui-title">Sort</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="sort" placeholder="Sort" />
</div>
</div>
Choice from a list of sorting mechanisms
<div class="emui-row">
<div class="emui-title">Sort</div>
<div class="emui-content">
<select data-xvalue="sort" class="form-control">
<option value="">Default sort</options>
<option value="ObjectInfo/modified;ND">Modified, DESC</options>
<option value="ObjectInfo/modified;NA">Modified, ASC</options>
<option value="ObjectInfo/created;ND">Created, DESC</options>
<option value="ObjectInfo/created;NA">Created, ASC</options>
</select>
</div>
</div>
sortby
Simple descending sort according to a parameter in the ObjectInfo.
Syntax
sortby:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Return the objects sorted by creation date, descending. |
|
|
Return the objects sorted by modified date, descending. |
Suggested HTML implementations
<div class="emui-row">
<div class="emui-title">Sort by:</div>
<div class="emui-content">
<select class="form-control" data-xvalue="sortby">
<option value="">Default sort</option>
<option value="Created">Created</option>
<option value="Modified">Modified</option>
</select>
</div>
</div>
status, workflow
Search objects with a given status ( workflow ).
Syntax
status:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). |
Suggested HTML implementations
Tip
|
By adding the data-preload="true" attribute, the select element will be preloaded with all the workflow steps available. |
<div class="emui-row">
<div class="emui-title">Workflow</div>
<div class="emui-content">
<select class="form-control" data-xvalue="workflow" data-preload="true"></select>
</div>
</div>
It is also possible to specify the values manually. Be careful in putting a value="" in case no filter should be applied.
<div class="emui-row">
<div class="emui-title">Workflow</div>
<div class="emui-content">
<select class="form-control" data-xvalue="workflow">
<option value="">Any workflow</option>
<option value="NewsFlow/Editing">NewsFlow/Editing</option>
<option value="NewsFlow/For Approval"></option>
</select>
</div>
</div>
type
Returns only the objects of a given type.
Syntax
type:(TYPE)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Return the objects of specified type. |
Suggested HTML implementations
Tip
|
By adding the data-preload="true" attribute, the select element will be preloaded with all the types available. |
<div class="emui-row">
<div class="emui-title">Type</div>
<div class="emui-content">
<select class="form-control" data-xvalue="type" data-preload="true"></select>
</div>
</div>
It is also possible to specify the values manually. Be careful in putting a value="" in case no filter should be applied.
<div class="emui-row">
<div class="emui-title">Type</div>
<div class="emui-content">
<select class="form-control" data-xvalue="type">
<option value="">Any type</option>
<option value="EOM::Story">EOM::Story</option>
<option value="EOM::MediaGallery">EOM::MediaGallery</option>
</select>
</div>
</div>
It is also possible to have a multiple selection of types. REMEMBER to change the data-operator attribute to OR to make it work. data-block-operator should be omitted or "AND".
<div class="emui-row">
<div class="emui-title">Type</div>
<div class="emui-content">
<select class="form-control" data-xvalue="type" data-operator="OR" data-preload="true" multiple data-block-operator="AND"></select>
</div>
</div>
usageticket
Allow to search within the usage tickets.
Syntax
usageticket:"tp:{type};;c:{creator};;rng:{range}"
Values
Keyword | Example | Description |
---|---|---|
|
|
|
Tip
|
|
Suggested HTML implementations
There is no a real suggested HTML implementation. It could be useful to create three different choices for the different fields ( types, creator and range ), and combine them in the filter JS.
user, creator, owner
Search for objects created by a given user
Syntax
user:(USER|myself)
Values
Keyword | Example | Description |
---|---|---|
|
|
Any string value (with quotes if there is a space). Return the objects created by the specified user. |
|
|
Return the objects created by the current user |
Tip
|
|
Suggested HTML implementations
Tip
|
By adding the data-preload="true" attribute, the select element will be preloaded with all the users available. |
<div class="emui-row">
<div class="emui-title">Owner</div>
<div class="emui-content">
<select class="form-control" data-xvalue="owner" data-preload="true"></select>
</div>
</div>
It is also possible to specify the values manually. Be careful in putting a value="" in case no filter should be applied.
<div class="emui-row">
<div class="emui-title">Owner</div>
<div class="emui-content">
<select class="form-control" data-xvalue="owner">
<option value="">Any user</option>
<option value="johndoe">johndoe</option>
<option value="Kurt">Kurt Cobain</option>
</select>
</div>
</div>
userchannel
See channel.
workflow
See status, workflow.
workfolder
Returns the objects inside a workfolder.
Syntax
workfolder:(VALUE)
Values
Keyword | Example | Description |
---|---|---|
|
Any string value (with quotes if there is a space). |
|
Suggested HTML implementations
Free path input
<div class="emui-row">
<div class="emui-title">Search in workfolder</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="workfolder" placeholder="Path" />
</div>
</div>
Choice from a list of paths
<div class="emui-row">
<div class="emui-title">Search in workfolder</div>
<div class="emui-content">
<select data-xvalue="workfolder" class="form-control">
<option value="">All paths</options>
<option value="/Globe/Stories/Politics">/Globe/Stories/Politics</options>
<option value="/Globe/Stories/Sport">/Globe/Stories/Sport</options>
</select>
</div>
</div>
How to configure search filters in external folder
Additional search filters may be made available to Swing application by defining one or more nested components in Swing web context in server.xml. (for further details on Tomcat 9.x Resources configuration, please refer to Resources configuration).
This is an example of the external filters configuration.
<Context docBase="com.eidosmedia.webclient.web-app"
path="/swing" reloadable="false">
<Resources
className="org.apache.catalina.webresources.StandardRoot">
<PreResources
className="org.apache.catalina.webresources.DirResourceSet"
base="/methode/meth01/extension/searchfilters" readOnly="true"
webAppMount="/config/templates/search/filters" />
</Resources>
</Context>
Explorer: filter on queries
Queries created in Swing
Queries generated from Swing will work like they do inside the search. Please see Search custom filter for reference on how to create and register a filter for the Swing searches.
Queries created in Prime, with filter.
Queries created in Prime can have a filter specified in their System Attributes. An example is the following:
<?xml version="1.0" encoding="utf-8"?>
<props>
<!-- ... -->
<filter>myFilter</filter>
<!-- ... -->
</props>
In Prime, this opens up a specific panel myFilter.html. To have the same functionality in Swing, it is necessary to register the filter with the following namespace
eidosmedia.webclient.extensions.queryFilters.register( filterName, options);
As the following example shows, the configuration is equal to the Swing query filters. Please see Search custom filter for reference on how to create and register a filter for the Swing searches.
The variables specified in the query correspond to the name of the data-xvalue attribute of the input. See example below:
Important
|
An additional defaultValues property can be defined. This means that the filter is executed with those values when the query is launched for the first time. The defaultValues property can also be a function that must returns a JSON object.+ See example at the end of the page. |
Important
|
Operators are ignored in this kind of filter. The filter is used to retrieve a value for all the variables specified with the data-xvalue attribute. |
Query XML
<?xml version="1.0" encoding="UTF-8"?>
<EOMSearch
xmlns="http://EidosMedia.com/EOM/SearchEngine"
xmlns:se="http://EidosMedia.com/EOM/SearchEngine"
xmlns:q="http://EidosMedia.com/EOM/SearchEngine/query"
xmlns:qm="http://EidosMedia.com/EOM/SearchEngine/query/macro"
xmlns:qa="http://EidosMedia.com/EOM/SearchEngine/query/alias"
xmlns:qui="http://EidosMedia.com/EOM/SearchEngine/query/UI"
xmlns:i="http://EidosMedia.com/query/interpolate">
<q:Query type="INDEX">
<q:Properties>
<q:MaxResultItems value="200" />
<q:Index name="@meth01_eomjse1" />
</q:Properties>
<q:Boolean>
<ObjectInfo>
<q:OR>
<type>EOM::Story</type>
<type>EOM::CompoundStory</type>
</q:OR>
</ObjectInfo>
<se:SysAttributes>
<props>
<productInfo>
<q:OR>
<name>
<i:metadata select="production.channel" />
</name>
</q:OR>
</productInfo>
<workfolder>
<i:variable name="production.workfolder.path" />
</workfolder>
</props>
</se:SysAttributes>
</q:Boolean>
<q:Where />
<qui:Query_UI version="1.1" domain="methode">
<qui:selItem list="repositories" />
</qui:Query_UI>
</q:Query>
</EOMSearch>
Filter HTML
<div class="emui-row">
<div class="emui-title">Channel</div>
<div class="emui-content">
<select class="form-control" data-xvalue="production.channel">
<option>Globe-Web</option>
<option>Globe-Print</option>
<option>Globe-Tablet</option>
</select>
</div>
</div>
<div class="emui-row">
<div class="emui-title">Workfolder</div>
<div class="emui-content">
<input type="text" class="form-control" data-xvalue="production.workfolder.path" />
</div>
</div>
Filter Javascript
eidosmedia.webclient.extensions.queryFilters.register('myFilter', {
// template is placed under /config/search/filters
template: 'explorer-filters/swing-filter-explorer-query.html',
defaultValues: {
"production.workfolder.path": "/Globe/Art"
},
/**
* Default values as function
* @param {Object} options - options to be used create default filter values, available properties: currentUser
*
* defaultValues: function(options) {
* return {
* "production.workfolder.path": "/Globe/Art"
* };
* }
*/
/**
* Function called after loading the template, but BEFORE loading the query
* use it to add listeners.
* @param {ContextObject}
* @param {Object} params - the params of the search element
* @param {Node} params.el - the current DOM node analized
*/
onLoad: function( ctx, params ) {
console.log('ON onLoad')
},
/**
* Function called after loading the query
* use it to fix the custom elements.
* @param {ContextObject}
* @param {Object} params - the params of the search element
* @param {Node} params.el - the current DOM node analized
*/
onQueryLoaded: function( ctx, params ) {
console.log('ON QUERY LOADED')
},
/**
* This function must return the value in the form <key>:<value> for each of the
* elements configured.
* @method getSearchValue
* @param {Object} params - the params of the search element
* @param {Node} params.el - the current DOM node analized
* @param {String} params.dataId - the value of the data-xvalue attribute
* @param {Function} getSearchValue() - the method that returns the search value calculated by default.
*/
getSearchValue: function( ctx, params ) {
console.log('GET SEARCH VALUE');
return params.getSearchValue();
}
});