Customize AnnotatorJS UI

Manoj Masakorala
4 min readJul 14, 2019

--

Customization of AnnotatorJS UI has been a hassle for many developers over the years and guidance is minimal. If you are new to annotatorJS or have a little idea about it please have a look into my introduction on Annotate HTML content with AnnotatorJS. It may be a good start for you to get an idea on its functionality and installation.

As you already know AnnotatorJS version 2 is modularize. Hence we can easily understand the library and readable. Though we can’t extend whole module we can use them as boilerplates and write our own implementation. We are going to use same approach in UI change of this library.

Getting Start

In module developing what we are going to do is to develop a function which will be later pass in to include() so we can extend the functionality of AnnotatorJS application.

Down below you can see how we normally load the basic annotator app into UI. We will normally load default ui module. default Storage, default authorization module etc. For all these modules we can give our own implementation and pass it to include()of defaults.

var app = new annotator.App();
app.include(annotator.ui.main);
app.include(annotator.storage.http);
app.start();

So Instead of default annotator.ui.main module we will give it our own implementation and use it as the customized UI module. So it would look like this;

function custom_ui_main(){
//module hooks can be used here.
}
var app = new annotator.App();
app.include(custom_ui_main);
app.include(annotator.storage.http);
app.start();

Module Hooks

so now you need to give a new functionality to the new module which is custom_ui_main. For that there are two approaches and we will be focusing on the latter, module hooks.

  1. component registration
  2. module hooks

The reason why we use that is, we won’t be replacing core functionality of Annotator. Hence Hooks will do our job with some boilerplates in default UI module. In AnnotatorJS 2.X Module Hooks play a very important role which are very handy when it comes to module development.

function custom_ui_main(){
return {
start: function (app) {
app.notify("Hello, geeks!");
}
};
}

In above example the application will give the notification “Hello, geeks!” when app starts. So module hooks can be identified as special functions that will run on different lifecycle events of the AnnotatorJS App.

following are the main hooks defined in Annotator App. Hooks will we called by App itself.

  • configure(registry)
  • start(app)
  • destroy()
  • annotationsLoaded(annotations)
  • beforeAnnotationCreated(annotation)
  • annotationCreated(annotation)
  • beforeAnnotationUpdated(annotation)
  • annotationUpdated(annotation)
  • beforeAnnotationDeleted(annotation)
  • annotationDeleted(annotation)

FYI: Apart from above mention default Hooks, you can define your own hook function by invoking runHook() method on app instance.

UI Customization

Please find the customized UI module in read only mode.

var custom_ui_main = function () {
var element = document.body
// Or whatever is your selector/element when you initialize the annotator
var ui = {}
return {
start: function () {
ui.highlighter = new annotator.ui.highlighter.Highlighter(element)
ui.viewer = new annotator.ui.viewer.Viewer({
permitEdit: function (ann) { return false },
permitDelete: function (ann) { return false },
autoViewHighlights: element
})
ui.viewer.attach()
},
destroy: function () {
ui.highlighter.destroy()
ui.viewer.destroy()
},
annotationsLoaded: function (anns) {
ui.highlighter.drawAll(anns)
}
}
}

If you wanna add a customized UI popup/ comment area; first you’ll have to design your own UI for that. Assume that I wanna use following UI instead of default UI by Annotator.

In that case you can sketch the HTML and Load the design on start and on onSelection. Its good idea that you go through the existing UI module as well so you can use it as a boilerplate.

In following example you can seen bit more advanced UI customization where we have used few Hooks and default UI module methods which would be available in App Load time.

var custom_ui_main = function () {
var element = document.querySelector("#relativeLocation");
var makeAnnotation = UtilityService.annotationFactory(element, ".annotator-hl");
var ui = { interactionPoint: null };
return {start: function start() {ui.highlighter = new annotator.ui.highlighter.Highlighter(element);ui.textselector = new annotator.ui.textselector.TextSelector(element, {onSelection: function onSelection(ranges, event) {if (ranges.length > 0) {annotation = makeAnnotation(ranges);var commentModalPosition = UtilityService.mousePosition(event);// document.getElementById("commentEditContainer").style.display = "block";} }});},destroy: function destroy() {ui.highlighter.destroy();ui.textselector.destroy();},annotationCreated: function annotationCreated(a) {ui.highlighter.draw(a);},annotationsLoaded: function annotationsLoaded(a) {ui.highlighter.drawAll(a).then(function () {},annotationDeleted: function annotationDeleted(a) {ui.highlighter.undraw(a);},annotationUpdated: function annotationUpdated(a) {ui.highlighter.redraw(a);}};}

So that is how you do a basic UI customization on Annotator App. Thats all we got as of now, If you have any issues or workarounds for any issues you faced with please add a comment and share your thoughts.

Please find GitHub Repo : https://github.com/openannotation/annotator/

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Responses (1)

Write a response