I’ve been working on a web-based editor for MODS records, to replace our current metadata management systems for our digitization project. As Art Rhyno has pointed out, Cocoon Forms (formerly known as “Woody”) provides a wonderful platform for developing complex web forms.

Try it out

Here’s an online demo which allows you to edit some sample MODS records. It currently doesn’t save the edited record, it just displays it back to you in XML. If you’d like to look under the hood, you can download it. To run it, install Cocoon, unpack the MODS editor into a convenient directory, and add it to the mount table something like this:

<mount src="/Docume~1/Peter/MyDocu~1/projects/mods/" uri-prefix="mods"/>

You can then access it at http://localhost:8888/mods/index.html (adjusting the port and such as needed).

Reasons to love Cocoon Forms

  • continuations. The management of the flow of the process (perhaps including several forms in sequence) is managed in a snippet of server-side javascript, in which the display of a particular form to the user is done by a function call. The javascript then snoozes until the user submits the form, upon which the javascript figures out what to do next.
  • a model-view-controller-style structure. You define the abstract data structure (model) in one place, the appearance of the HTML form (view) in another, and the binding of data from the source XML to the model (controller) in yet another.
  • Cocoon’s system of pipelines is available throughout the process. In a simple case, you can define the model, binding, and template each in its own XML file; but you can also have them defined by an XML stream issuing from a pipeline, having been customized as needed by all the tools available in that context. Perhaps selection lists need to be populated by database queries, or perhaps the list of elements to be displayed in this form needs to be filtered by an XSLT transformation so that it shows only the fields needed for describing maps.

How it works

As a simple example, here’s the publication date in a MODS record:

<mods:dateIssued>1994</mods:dateIssued>

The model defines this field thus:

<fd:field id="dateissued">
  <fd:label>Issued</fd:label>
  <fd:datatype base="string"/>
</fd:field>

(We’re treating this field as a string for now, but we can write validation rules to make sure we get a valid date). The binding from the XML source to the model looks like this:

<fb:value id="dateissued" path="mods:dateIssued" direction="both"/>

The id links to the field definition in the model, the path is the xpath to find the data within the source XML file, and direction specifies that the binding should be done both when loading and saving. (Again, we’re keeping this simple: we actually need to allow for multiple dateIssued fields, so we ought to use a repeater, which gives the user easy control over repeated fields.) Finally, the template looks like this:

<ft:widget-label id="dateissued"/>: <ft:widget id="dateissued">
  <fi:styling size="15"/> 
</ft:widget>

We put the label (as defined in the model), a colon, and a 15-character text box containing the value. It can all get much more complex than that, of course, but the building blocks are not difficult to master.

To-do list

  • draw the model, binding and templates through pipelines that filter them according to the type of resource. This will allow me to have one master definition of all MODS elements, and a set of stylesheets that filter out the elements you don’t need when e.g. describing a map.
  • make more use of CForms’ ability to make parts of the form depend on other parts; so when you select a “type” from a dropdown, the other fields rearrange themselves to present what’s appropriate for that type
  • write validation rules. These are included in the model on an field-by-field basis, and can be quite sophisticated (looking at values in other fields to determine what’s allowed in this one, etc.)

Final Questions

Will we get a truly usable editing interface this way, suitable for managing full MODS records? Will all the server-side work that Cocoon does slow things down too much? Could we work in more AJAX to make the workflow more smooth? Should I drop this and do it with XForms? Or Ruby on Rails? There’s plenty of room for optimization of what I’ve got so far; but whether it will be enough remains to be seen.