Annotating content with Annotatorjs in webpages

Manish Gopal Singh
YoungInnovations' Blog
3 min readJan 11, 2016

--

Annotatorjs is an open-source JavaScript library to add annotation feature easily into your application. The library is very extensible and have more than twenty plugins already developed by the community. You can easily add new functionality by writing plugins with the help of API provided by the library.

Currently, we are using Annotator library in ResourceContract.org project for annotation functionality. A user can annotate on both text and pdf. To enable annotation on PDF, we are using annotorious plugin. You can check the front-end work here.

In this tutorial, you will learn how to add annotation on text, store annotation on a database and populate annotation when a user hovers the annotated text.

Let’s get started with annotator

First of all, you need to download annotation js and include jQuery, annotator JavaScript and CSS in html page. Your page will look like below:

<html>
<head>
<link rel=”stylesheet” href=”http://assets.annotateit.org/annotator/v1.2.7/annotator.min.css">
</head>
<body>
<script src=”http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script src=”http://assets.annotateit.org/annotator/v1.2.7/annotator-full.min.js"></script>
</body>
</html>

To enable annotator on the page, you just need to select an element, that you want to annotate with jQuery and apply annotator method.

...<body>
<div id=”content”>
Add some content here...
</div>
...<script>
$(function(){
$(‘#content’).annotator();
});
</script>
</body>
...

Annotator will be enabled on #content element. Now you can select the text in a browser to see the action.

Save annotation

We are going to use Store plugin to save annotated text on a database. The plugin sends annotations data as JSON to the server so we just need to specify the API endpoint to store the data.

As we are using annotator-full.min.js so core plugins are already added. If you are using annotator.min.js file then you need to add annotator.store.min.js file.

Let’s update the script to attach store functionality.

...
<script>
$(function(){

var annotation = $('#content').annotator();

annotation.annotator('addPlugin', 'Store', {
prefix: '/annotation',
loadFromSearch : {
page : current_page_id
},
annotationData : {
page : current_page_id
},
urls: {
create: '/store',
update: '/update/:id',
destroy: '/delete/:id',
search: '/search'
}
});
});
</script>
...

We’ve options ‘prefix’ for storing endpoint which is ‘/annotation’ , ‘loadFromSearch’ for loading annotations from search action with page query for fetching annotation having current page id, annotationData is for attaching id of the current page to all annotation search. Here page is unique identifier for distinguishing annotations.

Registering Routes

I am using lumen, micro-framework by Laravel to demonstrate server-side coding. You can use any framework or even core php. Let’s register necessary routes in ‘routes.php’.

$app->get('/', 'Controller@index');
$app->get('/annotation/search', 'ApiController@search');
$app->post('/annotation/store', 'ApiController@store');
$app->put('/annotation/update/{id}', 'ApiController@update');
$app->delete('/annotation/delete/{id}', 'ApiController@delete');

Load Annotations

Annotator issue an request to ‘annotation/search?page=current_page_id’ on page load. It’ll initialize annotations on the annotated text.

public function search(Request $request)
{
$annotations = Annotation::where('page_id', $request->get('page'))->get();

return response()->json(['total' => count($annotations), 'rows' => $annotations]);
}

Creating an annotation

The library sends annotation data in post JSON when user submit an annotation. Below is the code to receive post JSON data and store in database.

public function store(Request $request)
{
$data = json_decode($request->getContent(), true);
$annotation = [
'ranges' => $data['ranges'],
'quote' => $data['quote'],
'text' => $data['text'],
'page_id' => $request->get('page')
];

if($id = Annotation::create($annotation)) {
return response()->json(['status' => 'success', 'id' => $id]);
} else {
return response()->json(['status' => 'error']);
}
}

Updating an annotation

It sends put request to ‘/annotation/update/:id’ where :id is id key return when creating an annotation and loading annotations. In most of the case primary key of the table. Update code looks like below.

public function update($id, Request $request)
{
$annotation = Annotation::find($id);
if($annotation) {
$data = json_decode($request->getContent(), true);
$annotation->ranges = $data['ranges'];
$annotation->quote = $data['quote'];
$annotation->text = $data['text'];
$annotation->page_id = $data['page_id'];

if($annotation->save()) {
return response()->json(['status' => 'success']);
}
}

return response()->json(['status' => 'error']);
}

Delete an annotation

It sends delete request to ‘/annotation/delete/:id’.

public function delete($id)
{
if(Annotation::destroy($id)) {
return response()->json(['status' => 'success']);
}

return response()->json(['status' => 'error']);
}

Conclusion

Annotator library is easy to setup with few lines of Javascript code. By now you should have a decent understanding of how to setup annotatorjs, storing annotation in a database, updating and deleting annotations. If you like to see working example then you can find here in my Github account.

--

--