Offline storage for the Annotator
Switch branches/tags
Nothing to show
Clone or download

Offline Annotator Plugin

A plugin for the OKFN Annotator that stores all created annotations in local storage if it's supported by the current browser. The plugin will also fire "online" and "offline" events when the browsers connectivity changes.

There is a demo available online.


The plugin requires the annotator.js and annotator.css to be included on the page. See the annotator Getting Started guide for instructions then simply include the annotator.offline.js file in your page. This can be downloaded from the GitHub download page.

<link rel="stylesheet" href="./annotator.css" />
<script src="./jquery.js"></script>
<script src="./annotator.js"></script>
<script src="./annotator.offline.js"></script>

Then set up the annotator as usual calling "addPlugin".

jQuery('#content').annotator().annotator("addPlugin", "Offline", {
  online: function (plugin) {
    // Do something when the browser is online.
  offline: function (plugin) {
    // Do something when the browser goes offline.


  • online: A function that is called when the plugin goes online. Receives the offline plugin object as an argument.
  • offline: A function that is called when the plugin goes offline. Receives the plugin object as an argument.
  • getUniqueKey: A function that accepts an annotation and should return a unique value for it. By default it will return the id property (if no such property exists it will add one).
  • setAnnotationData: A function that receives an annotation. This should be used to add data (such as an id) to newly created annotations. It is also called when the annotation is loaded from the localStorage. It is the equivalent to subscribing to the "beforeAnnotationCreated" and "beforeAnnotationLoaded" events.
  • shouldLoadAnnotation: A function that should return true if the annotation should be loaded in this page. This should be used if you have many pages on your site being annotated to prevent the annotator trying to load them all each time.

Loading Annotations Conditionally

If you have a single page application (such as an ebook reader) you may wish for finer grained control over which annotations are loaded. To do this you can use a combination of setAnnotationData and shouldLoadAnnotation options:

jQuery('#content').annotator().annotator("addPlugin", "Offline", {
  setAnnotationData: function (ann) {
    // Add page specific data to the annotation on creation.
    if (! { = getCurrentPage(); // getCurrentPage() would return the current page number
  shouldLoadAnnotation: function (ann) {
    // Return true if the annotation should be loaded into the current view.
    return === getCurrentPage();


There are various events available on the Offline plugin that can be used in your own code.


Events can be subscribed to on the annotator or offline plugin object.

// Get the annotator by calling .data() on the selector it was called on.
var annotator = $("#content").data("annotator");

// Sync with server when online.
annotator.subscribe("online", function (plugin) {

// Convert timestamp to Date object on load.
annotator.subscribe("beforeAnnotationLoaded", function (annotation) {
  var date = new Date();
  annotation.timestamp = date;
  • "online": Called when the browser returns online. Receives the Offline plugin object as an argument.
  • "offline": Called when the browser goes offline. Receives the Offline plugin object as an argument.
  • "beforeAnnotationLoaded": Called when an annotation is extracted from localStorage. It can be used to de-serialise properties.
  • "annotationLoaded": Called after "beforeAnnotationLoaded" receives the annotation and the Offline plugin as arguments.


If you're interested in developing the plugin. You can install the developer dependancies by running the following command in the base directory:

$ npm install .

Development requires node and npm binaries to be intalled on your system. It was developed with node --version 0.6.6 and npm --version 1.1.0 -beta-4. Details on installation can be found on the node website.

Then visit http://localhost:8000 in your browser.

There is a Cakefile containing useful commands included.

$ cake serve # serves the directory at http://localhost:8000 (requires python)
$ cake test  # opens the test suite in your browser
$ cake watch # compiles .coffee files into lib/*.js when they change
$ cake build # creates a production pkg/annotator.offline.js file
$ cake pkg   # creates a zip file of production files


The development branch should always contain the latest version of the plugin but it is not guaranteed to be in working order. The master branch should always have the latest stable code and each release can be found under an appropriately versioned tag.


Unit tests are located in the test/ directory and can be run by visiting http://localhost:8000/test/index.html in your browser.


The plugin uses the following libraries for development:

  • Mocha: As a BDD unit testing framework.
  • Sinon: Provides spies, stubs and mocks for methods and functions.
  • Chai: Provides all common assertions.


This plugin was commissioned and open sourced by Compendio.

Copyright 2012, Compendio Bildungsmedien AG Neunbrunnenstrasse 50 8050 Zürich

Released under the MIT license