This is part 3 of a series on drag and drop with XPages and Dojo. Part 1 is here. Part 2 is here.

Rearranging a data table

In our previous lesson, we showed how to programmatically add the elements we need to the DOM to successfully morph an HTML data structure (a list) into a Dojo drag and drop (Dojo.dnd) container. We will build on this concept to successfully embellish a more complex structure -a data table- and culminate with a view, which is in reality a nested table when displayed in the web browser.

Let’s begin by creating a new XPage in our application (see example application.) We’ll call this XPage “Draggable_Table.” We’ll drag a repeat control onto the XPage and set the data source as our “Produce” (alias “vProduce”) view. Let’s drag a table control into the repeat control, give it a dimension of 2x2 and type in our column headers of “name” and “type” respectively into the two cells of the first row of our table. Now we’re going to place computed fields into the two cells in the second row of our table control and bind their values to the rowData data source and the “Name” and “Type”columns of our data source respectively. Your XPage design view should look similar to this:

Going back to our table’s property editor, let’s name our table something descriptive, say “dndtable” (we’ll reference the name in the Javascript Dojo.dnd activation phase of our example in a bit) and give the table a style of container. Recall that Dojo looks for HTML elements with the style of container to manipulate their contents. In the outline editor of our XPage, drill down to and select the second table row element and, using the properties editor, give it a style of dojoDndItem. This row corresponds to the row containing our repeating data that we want to dynamically rearrange using Dojo.dnd. Recall that dojoDndItem is a style class that Dojo.dnd looks for to denote an element that can be dragged and dropped. Lastly, drill down in the outline editor to the first table cell of the second row of our table and give the cell a styleClass of dojoDndHandle. We want the first cell of our repeating data to serve as the “drag handle” for our dragging operations and styling the cell as such will accomplish this.

Before we switch to our XPage’s Source view, we must make sure we have specified all the resources we need to enable the Dojo.dnd behavior. Recall from our previous example that we needed to instruct Dojo to load the modules Dojo.dnd.source and Dojo.parser, the CSS for Dojo.dnd (using our Javascript technique to reference the CSS residing on our Domino server) and some custom CSS in our application that further styles some Dojo.dnd elements for a more descriptive user interface. To review:

TIP: The quickest way to copy a series of resources from one XPage to another is to copy them from the source editor. To copy all the required resources for Dojo.dnd enablement, copy everything between <xp:this.resources> and </xp:this.resources>, inclusive.
  1. From the “basics” section of the “All Properties” tab of our XPage’s property browser, add a resource using the “plus” sign of type xp:dojoModule and name dojo.dnd.Source.
  2. Add another resource of type xp:dojoModule and name it dojo.parser.
  3. Add another resource of type xp:styleSheet and set its href property to the computed value of the dnd.css file located on our Domino server using the technique and script described in Part 2. (Also describe in detail in the article REFERENCING WEB SERVER FILE SYSTEM RESOURCES IN XPAGES.)
  4. Add another resource of type xp:script and set its clientSide property to true. We’ll populate this script in the source editor in the next step.
  5. From the “Style” tab of our XPage’s property browser add the dnd.css stylesheet from our application’s style sheets resources.

Now we need to switch to our XPage’s source editor to rearrange the repeat control’s domain and add the final bits of Javascript that will enable Dojo.dnd for our example. First, recall that the repeat control is repeating everything inside of it, which is not what we want. We only want the second table row of our table definition to repeat, using the sequential values of our view data source. (See Declan Lynch’s post on repeat controls in tables in his excellent XPages tutorial for more on this.) To do this, we’ll put the opening tab of our repeat control <xp:repeat… in between the xp:tr tags of the two rows of our table. We’ll similarly put the closing tag of our repeat control after the closing xp:tr tag of our second row before the xp:table closing tag. Your table’s source should look like this:

  1. <xp:table styleClass="container" id="dndtable">
  2. <xp:tr>
  3. <xp:td>name</xp:td>
  4. <xp:td>type</xp:td>
  5. </xp:tr>
  6. <xp:repeat id="repeat1" rows="30" value="#{vProduce}"
  7. var="rowData" indexVar="rowIndex">
  8. <xp:tr styleClass="dojoDndItem">
  9. <xp:td styleClass="dojoDndHandle">
  10. <xp:text escape="true" id="computedField1"
  11. value="#{rowData.Name}">
  12. </xp:text>
  13. </xp:td>
  14. <xp:td>
  15. <xp:text escape="true" id="computedField2"
  16. value="#{rowData.Type}">
  17. </xp:text>
  18. </xp:td>
  19. </xp:tr>
  20. </xp:repeat>
  21. </xp:table>

Notice the start of the repeat control on line 6 and the closing of the repeat control on line 20. Also note (and correct if necessary) the various styleClass tags that translate to style tags when rendered in the browser.

The last step in our example is to add, via Javascript, the tagging we are not able to declare in the XPages design environment and activate Dojo.dnd. As in the example in part 2, we need to determine what the id of our container is. We’ve named our container -the table- dndtable which is merely the least significant component of the name that Domino will assign to it when rendered in the browser. You can render the page to your browser and inspect the source code (easiest way) or just know that, by convention, Domino will name your control view:_id1:dndtable. We use this information to obtain a handle to our Dojo.dnd container and add the missing required attributes to it. Once done, we can instruct Dojo to parse the page and “turn on” any functionality it finds. We put this code inside the xp:script element in our xpage that we set to clientSide=true like so:

  1. dojo.addOnLoad(function() {
  2. var wl = document.getElementById("view:_id1:dndtable");
  3. wl.setAttribute('dojoType','dojo.dnd.Source');
  4. wl.setAttribute('withHandles','true');
  5. dojo.parser.parse();
  6. });

Our page is now ready to be saved and viewed in a web browser. Notice that because only the first cell of any given data row is set to be a drag handle you cannot drag a row from the second cell. You may set the entire row to be a drag handle if that is your desired behavior.

Rearranging view items

A view element in XPages is rendered as a table-within-a-table. The outer table contains view embellishments such as navigation controls (prev|next) and view name and the inner table contains the actual view data. As a result, converting a standard XPages view control in a Dojo.dnd-enabled one is quite similar to the exercise of converting a table. The major differences being the targeting of the Dojo.dnd container element and the lack of any need to rearrange repeat control logic in our source editor (as the repeat logic is intrinsic in the view control.)

Let’s create an XPage called “Draggable_View” and add all the resource requirements we need to enable Dojo.dnd on our page. Next we’ll drag a view control onto our page and wire it to our “Produce” view. Accept the defaults to allow all the columns in our view to display. Now we drill down to our view element in our XPage’s outline and view the view’s “All Properties” tab in the properties browser. To tag our view’s datatable (the embedded table with the view data within the view table) as a Dojo container, set dataTableStyleClass to container. To set the datatable’s rows as draggable Dojo.dnd items, set rowClasses to dojoDndItem.

Lastly, to set our Dojo.dnd drag handles, select the first View Column by either drilling down to the first View Column element in the Outline or by clicking on the view column representation in Designer and set its styleClass property to dojoDndHandle. The last step is to switch over to our XPage's source view and specify the name of the container in our Dojo.dnd Javascript initialization routine (by convention view:_id1:viewPanel1) in the same manner as we've done in previous examples.

Link to example application (zip file, on skydrive) for this tutorial.

By now you’ve seen that the basic steps in getting Dojo.dnd to work in Xpages is to properly identify the dragging containers, elements and handles and initialize the behavior using a combination of declarative steps and programming.  Our next tutorial will will be on how to drag elements from one container to another with the simple use case of being able to drag elements from one folder representation into another. We’ll (hopefully) finish up with the advanced topic of saving our browser’s state (after we’ve rearranged elements using Dojo.dnd) back to the server without having to submit and refresh the entire page.

SHAMELESS PLUG: Like what you see? Hire Me! Contact info@critical-masses.com or use the contact page to learn more about engaging Jake Ochs for your development needs.