At Nuxeo we are always eager to integrate the latest features available from the global software development community. We’ve seen this in the adoption of Polymer to improve user interface development and the introduction of automation scripting using the excellent Nashorn engine.

For a while now we’ve used the excellent select2 project for the widget that we use to suggest and select documents, directory entries and users and groups. Being JavaScript-based, it has allowed us to do some interesting things with operations and in-browser processing. In practice, a Nuxeo operation is used to populate the list of options a user is offered in the suggestion widget. The widget is configured in Studio to pass parameters to an operation which uses the Nuxeo API to obtain suggestion entries from the repository and returns the result in a JSON object. The select2 script parses the JSON and updates the webpage with the suggestions. Custom JavaScript functions can be included in the suggestion definition which allows users to override the general behavior of the widget.

Recently a client asked how they can select two users in a form - the multiple user suggestion widget works nicely for this - but in this case they wanted to select one user and store it in one field, and then select another user and store it in a second field. But how to prevent someone from selecting the same user twice? The second selector would have to know the value of the first selection, and there should be a way to remove that user from the suggestion list.

Multiple user suggestion widget

JavaScript can be used to obtain the value of the first selection. To pass the value to the operation driving the suggestion widget, a small improvement was added to the widget that allows additional parameters to be passed to the operation. The additional parameters are set in a JavaScript function that is included in the suggestion definition.

To cause the suggestion widget to return a list of users not including the first selected user, there are three options:

  • Write a custom operation in Java
  • Build a traditional automation chain which uses the default operation to generate the user list, and an MVEL script to remove the selected user from the operation result
  • Build an automation script that does the same thing as the automation chain

The last scenario is an excellent example of how to leverage JavaScript to customize Nuxeo behaviors. The new Automation Scripting feature can be used to generate the user list using the default Get User/Group Suggestion operation, and use standard JavaScript to filter the list.

Obtaining the Value of the First Selection

In Studio we have a form which has two Single User/Group Suggestion widgets labeled User 1 and User 2. The first suggestion widget is completely standard. When a user selects a user from the first selection, the value is stored in the DOM. We can inspect the HTML of the page to determine the id of the element holding the selection:

<input id="document_create:nxl_layout_File_create:nxw_user1_select2" class="select2-offscreen" style="width: 100%;" tabindex="-1" name="document_create:nxl_layout_File_create:nxw_user1_select2" type="hidden" value="huey" />

Inspecting the page HTMLInspecting the page HTML

We can use jQuery to target input elements with id ending with ‘user1_select2’ and use that to obtain the selection value.

<small>function setUsernameToRemove(temp,params,query){
    var firstSelectionId = "input[id$='user1_select2']";
    var firstSelectionValue = jQuery(firstSelectionId).attr("value");
    temp.usernameToRemove = firstSelectionValue;
    return temp;
}</small>

This function is entered in the Inline Javascript parameter of the second selector’s widget definition. A custom parameter named additionalOperationParameters parameter is set with the name of the function. When the suggestion script runs, it will call the function and pass the usernameToRemove parameter to the operation.

Widget ConfigurationWidget Configuration

Building the CustomUserSuggestion Automation Script

Automation Scripting was introduced in Nuxeo 7.2. It is an evolution of the traditional Nuxeo automation chain feature which uses JavaScript to invoke Nuxeo operations and tie them together with logic. To start a new automation script, go to Nuxeo Studio and in the Automation section make a new Automation Scripting entry.

The automation script looks like this:

 <small>function run(input, params) {
  var suggestion = JSON.parse(UserGroup.Suggestion(input, {
    'searchTerm': params.searchTerm,
    'searchType': params.userSuggestionSearchType}).getString());
  var result = [];
  for (var obj in suggestion) {
    if (suggestion[obj].username != params.usernameToRemove) {
      result.push(suggestion[obj]);
    }
  }
  ctx.resultsString = JSON.stringify(result);
  var resultsBlob = Context.RestoreBlobInputFromScript(null, {
    script: 'This=new org.nuxeo.ecm.core.api.impl.blob.StringBlob(resultsString,"application/json");'
  });
  return resultsBlob;
}</small> 

All automation scripts include a run() function that accepts the input object and chain parameters. In this script, we invoke the default User/Group Suggestion operation, parse the result, and place it in a string. Then we iterate through the suggestion list and add the items that we want to keep to another array, and return that array as a JSON string contained in a StringBlob. The select2 widget will parse the StringBlob and use it to populate the dropdown menu.

The automation script in Nuxeo StudioThe automation script in Nuxeo Studio

With the automation script in place, we can go back to the widget definition and set a custom parameter operationId which references the automation by name. The operationId needs to be prefixed with javascript., so in this example it would be javascript.CustomUserSuggestion.

Now, when we go to the form and select a user in the first suggestion box, it will be impossible to select the same user in the second suggestion box. Problem solved.

More Information

There are a few entries in our documentation center to read for more info.

For another example similar to this one that demonstrates how the additionalOperationParameters function can be used to provide multi-factor selection criteria, see How to make a selection based on the value of another value in a layout.

To learn more about the suggestion widget, see Suggestion Widget Types.

And for an introduction to JavaScript-based automation scripting, see Automation Scripting.