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
- 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:
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"/>
id links to the field definition in the model, the
path is the
xpath to find the data within the source XML file, and
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
<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.
- 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.)
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.