A chrome extension for tagging words with semantic information.
Find a file
Nils Norman Haukås c6c1fbfe54 Squashed commit of the following:
commit 5cce0dbf60781b759f998a01546a759cbdea6bb7
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Sat Jun 25 12:50:15 2016 +0200

    Add comment

commit b4e241f9845ff4e5ce3a1f4d295bab714f061ce7
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Sat Jun 25 12:48:30 2016 +0200

    Update how menu is loaded when distributed as a plugin. Seems to load properly now.

commit ca28432c4717ebc035c754cca7b5fc691ee269d6
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Sat Jun 25 12:46:28 2016 +0200

    remove uneeded deps from typings

commit 3ec733feaf82930d96b2d19d1cd40a95e0c0aab7
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Sat Jun 25 11:40:02 2016 +0200

    removed gulp dependencies

commit 5a21e118a59c184f52c971fa2a9f023676372867
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Wed Jun 22 23:15:36 2016 +0200

    added clean and build scripts to package.json which builds a dist folder

commit e755176a13005fc907617148c418dec793bc4c4a
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Wed Jun 22 21:13:51 2016 +0200

    Added 'npm run server', which will fire up a test page that runs the existing plugin code.

commit 4fccd07c2ed9308c42d97f47837464a180e40f8d
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Wed Jun 22 20:08:14 2016 +0200

    delete files that are no longer needed. Add comments to explain styling setup.

commit 227163df0834eb9b2d57270f2460263837a14212
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Wed Jun 15 00:34:37 2016 +0200

    got test setup up and running. Fixed uuid and rangy import statements.

commit 41b73d35f6e8b12ab04fb04f312e524443689554
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Wed Jun 8 23:03:32 2016 +0200

    kinda working. Still working on starting the application in test mode.

commit cd929b0acd71c486dd7a0ca0b18723f98faa401f
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Sun May 29 22:44:45 2016 +0200

    added pageRebuilder for preparin the page when app is used as a chrome plugin. Still not quite working yet.

commit 722759ae5f5c93fea08570ad14155d741e8f8b63
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Sun May 22 01:23:52 2016 +0200

    Managed to add a basic jspm setup.

commit 7b99c2ed8647f54b8d77d69d37d5f6d05b7f63cc
Author: Nils Norman Haukås <nils@thunki.com>
Date:   Sat May 21 13:13:10 2016 +0200

    Lots of rearranging code. Split up gulpfile for clarity. Updated typescript and gulp dependencies.
2016-06-25 20:16:17 +02:00
src Squashed commit of the following: 2016-06-25 20:16:17 +02:00
test Squashed commit of the following: 2016-06-25 20:16:17 +02:00
typings Squashed commit of the following: 2016-06-25 20:16:17 +02:00
.gitignore Squashed commit of the following: 2016-06-25 20:16:17 +02:00
build.sh Squashed commit of the following: 2016-06-25 20:16:17 +02:00
config.js Squashed commit of the following: 2016-06-25 20:16:17 +02:00
package.json Squashed commit of the following: 2016-06-25 20:16:17 +02:00
README.md Update README.md 2016-01-31 15:42:09 +01:00
tsconfig.json Squashed commit of the following: 2016-06-25 20:16:17 +02:00
typings.json Squashed commit of the following: 2016-06-25 20:16:17 +02:00

tag-youre-it

A chrome extension for tagging words with semantic information.

Development

  1. To do active development, just download this plugin.
  2. You'll need to have installed node.js.
  3. Go inside the unzipped folder and run npm install && npm install -g gulp. In addition to installing development dependencies it will also install Gulp which is useful for active development.
  4. Run gulp serve to serve up the prototype for live development.
  5. Run gulp dist to build the chrome plugin in the dist/ folder.

Chrome testing

  1. Inside chrome go to settings -> Extensions.
  2. Select Load unpacked extension and select the project's dist/ folder.
  3. You should now see a new browser icon. Go to a page and start tagging.
  4. In case of error: Press "f12" and have a look at the console log output.

Important A workaround for CORS is currently needed to communicate with the server.

What's happening under the hood?

Technology stack (roughly): Angular.js, Typescript, Lodash and Rangy.js.

How is the plugin loaded? Manifest.json adds an icon and defines an event page called background.js. The event page adds a click listener to the plugin's browser icon. When triggered it will first load jquery and then inject the html menu in an iframe as well as create an iframe for housing the page content. The plugin is in fact reloading the page inside an iframe on the page. It will then continue loading dependencies before finally calling tagit.init() on the plugin which makes angular initialize itself making it possible to interact with the injected menu. When loading the plugin it will check localstorage for previously made tags and add them to the page. The plugin will also add click listeners to the iframe(s) containing the content to be tagged.

Why iframes? I originally tried to just inject the menu into the page to tag. This was the source of a number of issues. Tags need to be related to the original page structure but was disturbed by the injected non-static plugin menu. CSS was also quite unmanageable as the original page's css would disturb the plugin menu and vice versa. In really bad cases the content to be tagged would seep out of its containing <div></div> element and overlap the plugin menu. All things considered iframes seem like a decent approach since they shield our menu and the taggable content from each other.

How does tagging happen? After the plugin has been loaded it will have added click listeners to the iframe(s) containing the taggable content. When a click is registered the plugin will check if a word was selected. If a new word has been selected it will query a backend service (url endpoint) for possible definitions to tag the word with and display them in the menu. When the user selects a definition the plugin tags the word, saves the tag in localstorage and posts the result back to the backend service.

Particularities to tagging: When tagging a selection the plugin must always relate the tag position to the original DOM object (original web page structure). Thus the plugin will remove all tags and selections before saving a word selection or saving a tag. Tags also need to be loaded in a bottom up order so that their range.startOffset is always in relation to the original DOM. StartOffset is simply a position number of where the node (html element etc.) is located within the DOM tree-structure that starts with 0 (document root).

Even more particularities to tagging: When a word is selected rangy.js adds invisible selection markers (spans) to the page which safeguards against accidentally unselecting the word we are trying to tag or accidentally tagging the wrong word. The selection markers will be removed when loading the selection again (making the right word selected in blue on the page). After loading the selection we tag the word by wrapping it in a span that contains tagging information and style information which highlights the tagged word. A button element is also added inside the span for removing the tag.