MAT's document component can be used, without the rest of MAT, to
view, annotate, align, or compare annotated documents. You may
want to embed this capability in your own Web tool or workflow.
This document describes how to include the appropriate Web pages
from the MAT distribution; how to generate a document which the
MAT document component can understand; and how to enable hand
annotation, comparison and alignment.
For instance, let's say you have a Java servlet which accesses a
database in which your annotations are stored. You might use our Java library to produce a
serialized document in the appropriate format, retrieve it in your
Web application via AJAX, and pass this serialization to the
embedded standalone document viewer. Alternatively, you could
forward your annotations to your Web application in your own
format, and use our JavaScript library
to create the appropriate document.
An example can be found in
$MAT_PKG_HOME/web/examples/standalone_viewer_example.html.
The following includes are required from
$MAT_PKG_HOME/web/htdocs:
The Javascript files must be loaded in the order given. If you're
running the MAT Web server with the
default application prefix, you can load them in your document
head as follows (where "yourserver" is the host where the MAT Web
server is running):
<script type="text/javascript" src="http://yourserver:7801/MAT/js/mat_utils.js"></script>
<script type="text/javascript" src="http://yourserver:7801/MAT/js/mat_core.js"></script>
<script type="text/javascript" src="http://yourserver:7801/MAT/js/core_ui.js"></script>
<script type="text/javascript" src="http://yourserver:7801/MAT/js/mat_doc_display.js"></script>
<script type="text/javascript" src="http://yourserver:7801/MAT/js/mat_standalone_doc_viewer.js"></script>
<link rel="stylesheet" type="text/css" href="http://yourserver:7801/MAT/css/mat_core.css">
Alternatively, you can copy these six files to your own Web
server.
No other files are required. Although the MAT UI relies heavily
on the Yahoo! UI Toolkit, the standalone doc viewer does not, nor
does it rely on any other toolkit.
In order to create the standalone viewer, you need, minimally, a
tag set and a DIV where the viewer will be rendered.
<script type="text/javascript"> var Tags = [{label: "PERSON", css: "background-color: #CCFF66"},
{label: "LOCATION", css: "background-color: #F99CC"},
{label: "ORGANIZATION", css: "background-color: #99CCFF"}];
var docDiv = document.getElementById("docDiv");
// Set up the viewer.
var viewer = new MAT.DocDisplay.StandaloneViewer({
tags: Tags,
div: docDiv
});
</script>
There's a lot more you can do, which we'll return to when we look
at the viewer details. For now, let's move on to creating
documents.
The document you provide should be a Javascript object which
corresponds to the MAT JSON format, versions 1 or 2. For instance:
<script type="text/javascript">
var Document1 = {
"signal": "David Asher is a former coordinator of North Korea policy at the State Department.",
"metadata": {},
"asets": [{"type": "ORGANIZATION", "attrs": [], "annots": [[65, 81]]},
{"type": "LOCATION", "attrs": [], "annots": [[39, 50]]},
{"type": "PERSON", "attrs": [], "annots": [[0, 11]]}]
};
</script>
We assume that you'd create these documents automatically
somehow, by converting documents in your favorite format into MAT
JSON format, or from your previous interactions with MAT. The
document you pass can also be a JSON string in this format, rather
than the resulting structure, or, alternatively, you can use the
MAT JavaScript UI to create the appropriate document, e.g.:
<script type="text/javascript">
var Document1 = viewer.newDocument("David Asher is a former coordinator of North Korea policy at the State Department."); Document1.createAnnotation("PERSON", 0, 11);
Document1.createAnnotation("LOCATION", 39, 50);
Document1.createAnnotation("ORGANIZATION", 65, 81);
</script>
To display this document, just call renderSingleDocument():
<script type="text/javascript">
viewer.renderSingleDocument(Document1);
</script>
The viewer will reset itself before it displays the document, so
you can reuse the viewer as often as you want.
You can also display an alignment
of multiple documents which all have the same document signal.
Keep in mind that this mechanism only works for span annotations.
<script type="text/javascript"> viewer.renderDocumentAlignment([
{doc: Document1, position: "above", initial: "1"},
{doc: Document2, position: "above", initial: "2"},
{doc: GoldDocument, position: "behind", initial: "G"}
]);
</script>
In this example, the argument to renderDocumentAlignment is a
Javascript array of objects with the following keys and values:
key |
value |
description |
---|---|---|
doc |
a MAT JSON document |
either a JSON string, a
Javascript object, or an object created by newDocument() |
position |
a string |
either "above" (annotations
appear above the text), "behind" (annotations appear behind
the text) or "below" (annotations appear below the text) |
initial |
a one-character string |
a shorthand reference to the
document in the viewer |
The stacking order of the documents is determined by the order of
the entries in the Javascript array: earlier elements are above
later elements. There can be only one element with a position of
"behind", obviously.
The viewer will reset itself before it displays the document
alignment, so you can reuse the viewer as often as you want.
Unlike document alignments, a true document comparison works for both spanned
and spanless annotations. These documents are created by the
Python library, using the same pairing algorithm used by the
scorer. So in order to generate such a document, you'll need to do
some work in your own Web backend, either by capturing the output
of the MATCreateComparisonDocument
utility, or (if your Web backend is Python) by directly calling
the libraries which that utility calls. Once you have such a
document (either a JSON object or its corresponding string), you
can create the comparison view as follows:
<script type="text/javascript"> viewer.renderDocumentComparison(doc);
</script>
or
<script type="text/javascript"> viewer.renderDocumentComparison(doc, {
pivot: {
docName: ...,
initial: ...
},
others: [{
position: ...,
docName: ...,
initial: ...
}, ...]
});
</script>
In this second case, the second argument is a JavaScript object
which describes the documents, and gives you more control over how
the documents are referenced in the comparison view. The pivot is
the reference document; the others are the documents which you're
comparing to the reference document. The others array should be in
the same order as the documents that you passed to the comparison
creation document utility. The position and initial attributes
have the same interpretation as they do for document alignments;
the docName is a longer name by which you want the document to be
described. Note that you can't change the position of the pivot;
it is always behind the text.
If you want to do hand annotation in your document, or display
annotation tables, you'll need to add a few more headers, and
you'll need to provide access to the YAHOO! UI Toolkit, which we
use to manage the annotation popups.
Add the following headers immediately before the load line for
mat_standalone_doc_viewer.js:
<script type="text/javascript" src="http://yourserver:7801/MAT/resources/yui/build/yuiloader/yuiloader.js"></script>
<script type="text/javascript" src="http://yourserver:7801/MAT/js/workbench_ui_popup_mgr.js"></script>
<link href="http://yourserver:7801/MAT/css/workbench_ui_annotation.css" rel="stylesheet" type="text/css">
If you want to display annotation tables, you'll need one more
header:
<script type="text/javascript" src="http://yourserver:7801/MAT/js/workbench_ui.js"></script>
Once you've done this, you need to do three more things.
First, we need to ensure that YUI is loaded before we
create the viewer. Because of how browsers load documents, this is
harder than it should be. You'll need to place the code which
creates the viewer in an onload() function, and you'll also
need to make use of the
MAT.DocDisplay.StandaloneViewer.waitForYUI() function. Second, if
you want to do hand annotation, create your viewer with the
"annotatable" attribute set, and enable hand annotation using the
enableHandAnnotation method. These steps are all illustrated here:
<html>
<head>
....
<script>
function onload() {
MAT.DocDisplay.StandaloneViewer.waitForYUI(function () {
var viewer = new MAT.DocDisplay.StandaloneViewer({
tags: Tags,
annotatable: true,
div: docDiv
});
viewer.enableHandAnnotation();
});
}
</script>
....
</head>
<body onload="onload()">
....
</body>
</html>
You can separate this last step, if, say, you want to control
whether hand annotation is enabled via an external radio button.
Note: there is a bug in
Firefox 9 where, if the first element of the document body is a
block element whose default style has a top margin, such as
<p>, the annotation popup will insert an invisible monitor
element which erroneously blocks the collapse of the top margin of
that first block element. You can get around this by enclosing the
entire body of the document in a <div>.
When you create a viewer, there are a lot of parameters you can
set; by far, the most important is how you tell the viewer about
the annotations you want it to recognize. There are three possible
ways of doing this, with increasing levels of power and
complexity:
Choose the parameter that best suits your needs, but choose only one. You can use the MATAnnotationInfoToJSON tool to generate the simplified or expanded annotation set descriptors for the "atr" or "taskATRFragment" parameters.
The viewer is instantiated with a single argument, a Javascript
object with the following keys and values:
key |
value |
description |
---|---|---|
tags |
a tag table |
see above and below. Either this, or
atr, or taskATRFragment must be provided. |
atr |
a more complex tag table |
the fomat of this parameter must be a simplified
JSON annotation set descriptor. Either this, or tags,
or taskATRFragment must be provided. |
taskATRFragment |
a most complex tag table |
the format of this parameter must be an expanded
JSON annotation set descriptor. Either this, or tags,
or atr must be provided. |
div |
a Javascript DOM object |
the DOM object corresponding
to the DIV in which you'd like to view your output |
taskName |
a string |
the name you want to use if
the standalone viewer wants to display a task name.
Optional. This may not be used anywhere. |
taskConfig |
a MAT UI task configuration object |
This configuration governs a number of
internal customizations for the task. There is no further
documentation on this feature; please refer to the source
code for more details. |
annotatable |
a boolean |
if true, the viewer will be
set up to permit hand annotation. Optional. Default is
false. If true, you can then use the enableHandAnnotation()
and disableHandAnnotation() methods. |
language |
a language name |
if you provide taskATRFragment, and your task
contains multiple languages, use this parameter to specify
which language you want. Otherwise, a default language will
be used (see textRightToLeft, tokenlessAutotagDelimiters,
and tokenlessAutotagRespectsDelimiters). |
textRightToLeft |
a boolean |
if true, the viewer will
display text right to left. Optional. Use this to display
documents in, e.g., Arabic or Hebrew. Equivalent to
specifying text_right_to_left="yes" in a <language>
element in the task XML. If you provide
taskATRFragment, this is ignored unless there are multiple
languages and you don't specify the language parameter. |
tokenlessAutotagDelimiters |
a string |
If present, specifies edge characters for
tokenless autotagging. Equivalent to specifying the
tokenless_autotag_delimiters attribute in a <language>
element in the task XML. If you provide
taskATRFragment, this is ignored unless there are multiple
languages and you don't specify the language parameter. |
tokenlessAutotagRespectsDelimiters |
a boolean |
If false, disables any sensitivity to edge characters, including whitespace, in tokenless autotagging (useful for non-whitespace-delimited languages, like Chinese). Equivalent to specifying the tokenless_autotag_respects_delimiters attribute in a <language> element in the task XML. If you provide taskATRFragment, this is ignored unless there are multiple languages and you don't specify the language parameter. |
legendDiv |
a Javascript DOM object |
the DOM object corresponding
to the DIV in which you'd like to have the tag legend
rendered. Optional. |
callbacks |
a Javascript object |
Each key is the name of a
callback, and each value is a function. Use this object to
customize the behavior of the viewer when certain events
occur. These function names and their arglists are:
|
editorContainer |
a Javascript object |
Optional. A Javascript object which manages
an editor div. You might want this if, e.g., you want the
object to do something when the annotation is changed or
deleted. This object should implement the methods
getAnnotationDisplayDiv(), which should return a div into
which the display is rendered, and
notifyVisualDisplay(annot, disp), which notifies the
container that a display is available. The container is now
responsible for implementing the display API, namely calling
annot.addVisualDisplay(disp) and
annot.removeVisualDisplay(disp) at the appropriate times,
and also forceDisplayResponse() and
forceRemoveRedisplayResponse(), which should at least call
those same methods on the disp. Only one of editorDiv and
editorContainer can be specified. Consult the code if you're curious about this parameter. |
editorDiv |
a Javascript DOM object |
an HTML element in which any annotation editors/viewers
can be rendered. They will be popped up otherwise. Optional. |
annotationTableDiv |
a Javascript DOM object |
an HTML element in which any annotation
tables can be rendered. This is equivalent to enabling
annotation tables in the UI. Optional. |
uiSettings |
a Javascript object |
Optional. A Javascript object where each key
is the name of a UI setting,
and each value is a value appropriate for that setting. Note:
not all UI settings are respected by the standalone viewer;
consult the "Javascript values in standalone UI" in the settings
table for details. |
extraGestures |
an array of Javascript objects |
If you want to take advantage of the new
ability to add gestures
to the annotation popup menu, you can pass them in here.
Each object in the array should have a label attribute, and
either a url_link or a function attribute, e.g.: [{label: "Search Google", url_link: "http://www.google.com/search?q=$(_text)"}] |
For instance, let's say that you have a tag table in the variable
"Tags", as above; a div with the ID "docDiv", as above; a div with
the ID "legDiv", where you want the legend rendered; and a div
with the ID "updateDiv", where you want to display the annotation
that's being hovered over. You'd instantiate the viewer as
follows:
var viewer = new MAT.DocDisplay.StandaloneViewer({
tags: Tags,
taskName: "Named Entity",
div: document.getElementByID("docDiv"),
legendDiv: document.getElementByID("legDiv"),
callbacks: {
mouseOverAnnotations: function(contentObj) {
document.getElementByID("updateDiv").innerHTML = contentObj.labels.join(", ") + (contentObj.suffix || "");
},
cancelMouseOverAnnotations: function() {
document.getElementByID("updateDiv").innerHTML = "";
}
}
});
enableHandAnnotation() |
If the annotatable key is
provided during configuration, you can turn on hand
annotation with this method. Hand annotation will only be
available with single documents, never with comparisons. |
disableHandAnnotation() |
Turn off hand annotation
using this method. |
enableLegendMenuControls() |
Modify the legend, if displayed, to include
menus to control visible/active/selected, as in the full MAT
UI. |
disableLegendMenuControls() |
Modify the legend so it doesn't have the menu
controls. |
newDocument(signal) |
Create a new document with
the specified signal. The result will be of type
MAT.Annotation.AnnotatedDoc. See mat_core.js for how to
interact with this object. |
renderSingleDocument(doc) |
Render a single document to
the DIV configured for the viewer. The doc can either be the
result of newDocument() above, or a Javascript object in
MAT-JSON format, or a JSON string in that format. |
renderDocumentAlignment(comps) |
Render an alignment of
multiple documents to the DIV configured for the viewer. See
here for more
details. |
renderDocumentComparison(doc) renderDocumentComparison(doc, details) |
Render a comparison of multiple documents to
the DIV configured for the viewer. See here for
details. |
getBareDocument() |
Retrieve a document which has
been displayed using renderSingleDocument(). You might want
to use this method to retrieve the results of annotation, if
you rendered the document using MAT-JSON instead of by
creating a new document using the newDocument() method. |
styleAnnotation(annot, params) |
Allows you to assign special styling to
particular annotations. If properly configured, it returns
an undo function, which can be combined with other
functionality to style and unstyle annotations in order, for
instance. See the source code for details. |
The tag table is a list of annotations which will be recognized
and displayed. It is a Javascript array of objects with the
following keys and values:
key |
value |
description |
---|---|---|
label |
a string |
an annotation label in the
MAT JSON document. Required. |
attrs |
an array of two-element
arrays |
if you want to associate a
visible label with an annotation label plus some
attribute-value pairs (e.g., if you want ENAMEX
TYPE="PERSON" to show up as PERSON in your display), you can
do this by specifying the attribute-value pairs here as an
array of two-element arrays, e.g., [["TYPE", "PERSON"]], and
then specifying the effectiveLabel key. |
effectiveLabel |
a string |
see the description of attrs
immediately above. The visible label for a combination of an
annotation label plus some attribute-value pairs. |
css |
a string |
a CSS specification for your
label (e.g., "background-color: blue"). Required. |
If you choose to display an annotation legend (see below), the elements in the legend will appear in the same order you listed them in the tag table. Remember, the CSS will apply to every subspan of the marked text, and the text may be divided into subspans if annotations overlap, so using left and right borders is not recommended.