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.
Proxy Options
The proxy can be configued with the following options:
-
http.jersey.client [true | false (default)] - Determines whether to use Jersey as client to perform all the as proxy for all HTTP requests through this proxy
-
http.read.timeout [30000] - Specify the socket read timeout (in milliseconds) to read the response from the target endpoint.
-
http.socket.timeout [3000] - Specify the socket connection timeout (in milliseconds) to establish a connection of the target endpoint.
-
reachout.httpProxy [true | false (default)] - if true enables the proxy to use an external proxy for HTTP requests. To do so, a following environment variable to the JVM where the Swing WebApp is running:-
em.reachout.httpProxyURImust be specified: the URI of the HTTP proxy, including port number (e.g: https://em.proxy:80/).
When configured, all HTTP requests will be done through the configured proxy URI. This option is irrelevant if you set false to "http.jersey.client" option. -
useTemplate [true | false (default)] - if true allows to use templates to build the target URL
<!-- other configuration -->
<proxies>
<proxy>
<name>[PROXY-NAME]</name> <!-- e.g. resourcespace -->
<http.jersey.client>false</http.jersey.client>
<http.read.timeout>30000</http.read.timeout>
<http.socket.timeout>3000</http.socket.timeout>
<reachout.httpProxy>false</reachout.httpProxy>
<targetUri>http://192.168.203.129/resourcespace/plugins/api_search/</targetUri> <!-- e.g. destination target Uri -->
<useTemplate>false</useTemplate>
</proxy>
</proxies>
|
The useTemplate param allows to use templates to build the URL. The following is an example of url which uses templates. |
<proxies>
<proxy>
<name>[PROXY-NAME]</name> <!-- e.g. resourcespace -->
<targetUri>http://192.168.203.129:{_port}</targetUri> <!-- e.g. destination target Uri -->
<useTemplate>true</useTemplate>
</proxy>
</proxies>
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 call 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 ).
|
[PROXY-NAME] must be equal to [DOMAIN-TYPE] (described in Domain setup). |
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
|
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. |
|
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. |
|
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
|
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 }
]
}
|
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
| the key searchTemplate will be explained in 5. Usage and creation of result templates. |
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. */
});
This results in:
=== 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
Considering the following search:
we have: . 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.
|
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 );
},
|
If you don’t call the callback function, the search will never be executed! |
|
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
| 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 } );
| 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 )
|
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).
|
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. |
|
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 5. Usage and creation of result templates 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.
|
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"
}
}
}
}
|
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. |
|
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)
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(),
getContext: 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" (for editors). |
area.getContext() |
String |
Returns the area context. |
"story-editor", "report-editor", "dwp-editor", "topic@editor", "topic@search", "topic@binder", "topicplan@editor", "topicplan@search", "topicplan@binder", "topicitem", "upload", "diagram-workflow", "search", "planning-calendar" |
component.getType() |
String |
Returns the component type. |
"toolbar", "grid", "objectpanel"… |
activeObject |
Object |
Returns an object with a set of methods. Refer to : Methods of the single object for the list 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. Each activeObject is coupled with one selected item. Methods of the single object operate to that item. |
|
selection |
Array of Object |
Returns an array with the currently selected items. Each item has the same set of methods available. Refer to : Methods of the single object for the list of methods. |
|
Each context has a different value for these properties. |
Methods available in the Context Object
Further details on the methods available in the Context Object can be found in the Context Object Methods reference.
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>