diff --git a/public/js/src/hint.js b/public/js/src/hint.js
new file mode 100644
index 0000000..3c2e3ca
--- /dev/null
+++ b/public/js/src/hint.js
@@ -0,0 +1,840 @@
+/**
+ * Context aware drop down menu
+ * for annotation related query hints.
+ *
+ * @author Nils Diewald
+ */
+
+// - http://www.cryer.co.uk/resources/javascript/script20_respond_to_keypress.htm
+// - https://developers.google.com/closure/compiler/docs/js-for-compiler
+// TODO:
+// - Add help option that opens the tutorial, e.g. to the foundry
+// - http://en.wikipedia.org/wiki/JSDoc
+
+/**
+ * The KorAP namespace for project related scripts
+ * @namespace
+ */
+var KorAP = KorAP || {};
+
+/*
+    this._search.addEventListener(
+      "keyup",
+      function () {
+	that.update();
+      },
+      false
+    );
+*/
+
+(function (KorAP) {
+  "use strict";
+
+  // Don't let events bubble up
+  if (Event.halt !== undefined) {
+    Event.prototype.halt = function () {
+      this.stopPropagation();
+      this.preventDefault();
+    };
+  };
+
+  // Default log message
+  KorAP.log = function (type, msg) {
+    console.log(type + ": " + msg);
+  };
+
+  /* TODO: Add event listener on windows resize to change that! */
+
+  /** @define {number} Limited view of menu items */
+  KorAP.limit = 8;
+
+  /**
+   * @define {regex} Regular expression for context
+   */
+  KorAP.context =
+    "(?:^|[^-_a-zA-Z0-9])" +   // Anchor
+    "((?:[-_a-zA-Z0-9]+?)\/" + // Foundry
+    "(?:" +
+    "(?:[-_a-zA-Z0-9]+?)=" +   // Layer
+    "(?:(?:[^:=\/ ]+?):)?" +   // Key
+    ")?" +
+    ")$";
+
+  // Initialize hint array
+  KorAP.hintArray = KorAP.hintArray || {};
+
+
+  KorAP.updateKeyDown = function (event) {
+  };
+
+  KorAP.InputField = {
+    create : function (element) {
+      return Object.create(KorAP.InputField)._init(element);
+    },
+    _init : function (element) {
+      this._element = element;
+
+      // Create mirror for searchField
+      if ((this._mirror = document.getElementById("searchMirror")) === null) {
+	this._mirror = document.createElement("div");
+	this._mirror.setAttribute("id", "searchMirror");
+	this._mirror.appendChild(document.createElement("span"));
+	this._mirror.style.height = "1px";
+	document.getElementsByTagName("body")[0].appendChild(this._mirror);
+      };
+
+      // Update position of the mirror
+      var that = this;
+      window.resize = function () {
+	that.reposition();
+      };
+/*
+      // Add event listener for key down
+      element.addEventListener(
+	"keydown",
+	function (e) {
+//	  KorAP.updateKeyDown(e).bind(that)
+	},
+	false
+      );
+*/
+      return this;
+    },
+    get mirror () {
+      return this._mirror;
+    },
+    get element () {
+      return this._element;
+    },
+    get value () {
+      return this._element.value;
+    },
+    update : function () {
+      this._mirror.firstChild.textContent = this.split()[0];
+    },
+    insert : function (text) {
+      var splittedText = this.split();
+      var s = this.element;
+      s.value = splittedText[0] + text + splittedText[1];
+      s.selectionStart = (splittedText[0] + text).length;
+      s.selectionEnd = s.selectionStart;
+      this._mirror.firstChild.textContent = splittedText[0] + text;
+    },
+    // Return two substrings, splitted at current position
+    split : function () {
+      var s = this._element;
+      var value = s.value;
+      var start = s.selectionStart;
+      return new Array(
+	value.substring(0, start),
+	value.substring(start, value.length)
+      );
+    },
+    // Position the input mirror directly below the input box
+    reposition : function () {
+      var inputClientRect = this._element.getBoundingClientRect();
+      var inputStyle = window.getComputedStyle(this._element, null);
+      var mirrorStyle = this._mirror.style;
+      mirrorStyle.left = inputClientRect.left + "px";
+      mirrorStyle.top = inputClientRect.bottom + "px";
+
+      // These may be relevant in case of media depending css
+      mirrorStyle.paddingLeft     = inputStyle.getPropertyValue("padding-left");
+      mirrorStyle.marginLeft      = inputStyle.getPropertyValue("margin-left");
+      mirrorStyle.borderLeftWidth = inputStyle.getPropertyValue("border-left-width");
+      mirrorStyle.borderLeftStyle = inputStyle.getPropertyValue("border-left-style");
+      mirrorStyle.fontSize        = inputStyle.getPropertyValue("font-size");
+      mirrorStyle.fontFamily      = inputStyle.getPropertyValue("font-family");
+    },
+    get context () {
+      return this.split()[0];
+    }
+  };
+
+  KorAP.Hint = {
+    _firstTry : true,
+    create : function (param) {
+      return Object.create(KorAP.Hint)._init(param);
+    },
+    _init : function (param) {
+      param = param || {};
+      this._menu = {};
+
+      // Get input field
+      this._inputField = KorAP.InputField.create(
+	param["inputField"] || document.getElementById("q-field")
+      );
+
+      var that = this;
+      var inputFieldElement = this._inputField.element;
+
+      // Add event listener for key pressed down
+      inputFieldElement.addEventListener(
+	"keypress", function (e) {that.updateKeyPress(e)}, false
+      );
+
+      // Set Analyzer for context
+      this._analyzer = KorAP.ContextAnalyzer.create(
+	param["context"]|| KorAP.context
+      );
+
+      return this;
+    },
+    _codeFromEvent : function (e) {
+      if ((e.charCode) && (e.keyCode==0))
+	return e.charCode
+      return e.keyCode;
+    },
+    updateKeyPress : function (e) {
+      if (!this._active)
+	return;
+
+      var character = String.fromCharCode(
+	this._codeFromEvent(e)
+      );
+
+      e.halt(); // No event propagation
+
+      console.log("TODO: filter view");
+    },
+    updateKeyDown : function (e) {
+      var code = this._codeFromEvent(e)
+      
+      /*
+       * keyCodes:
+       * - Down  = 40
+       * - Esc   = 27
+       * - Up    = 38
+       * - Enter = 13
+       * - shift = 16
+       * for characters use e.key
+       */
+      switch (code) {
+      case 27: // 'Esc'
+	// TODO: menu.hide();
+	break;
+      case 40: // 'Down'
+	e.halt(); // No event propagation
+	
+	// Menu is not active
+	if (!this._active)
+	  this.popUp();
+	// Menu is active
+	else {
+	  // TODO: that.removePrefix();
+	  // TODO: menu.next();
+	};
+
+	break;
+      case 38: // "Up"
+	if (!this._active)
+	  break;
+	e.halt(); // No event propagation
+	// TODO: that.removePrefix();
+	// TODO: menu.prev();
+	break;
+      case 13: // "Enter"
+	if (!this._active)
+	  break;
+	e.halt(); // No event propagation
+	// TODO: that.insertText(menu.getActiveItem().getAction());
+	// TODO: that.removePrefix();
+    
+	// Remove menu
+	// TODO: menu.hide();
+
+	// Fill this with the correct value
+	// Todo: This is redundant with click function
+	/*
+	var show;
+	if ((show = that.analyzeContext()) != "-") {
+	  menu.show(show);
+	  menu.update(
+            e.target.getBoundingClientRect().right
+	  );
+	};
+	*/
+    
+	break;
+      default:
+	if (!this._active)
+	  return;
+
+	// Surpress propagation in firefox
+	/*
+	if (e.key !== undefined && e.key.length != 1) {
+	  menu.hide();
+	};
+	*/
+      };
+    },
+
+    getMenuByContext : function () {
+      var context = this._inputField.context;
+      if (context === undefined || context.length == 0)
+	return this.menu("-");
+
+      context = this._analyzer.analyze(context);
+      if (context === undefined || context.length == 0)
+	return this.menu("-");
+
+      return this.menu(context);
+    },
+    // Return and probably init a menu based on an action
+    menu : function (action) {
+      if (this._menu[action] === undefined) {
+	if (KorAP.hintArray[action] === undefined)
+	  return;
+	this._menu[action] = KorAP.menu.create(action, KorAP.hintArray[action]);
+      };
+      return this._menu[action];
+    },
+    get inputField () {
+      return this._inputField;
+    },
+    get active () {
+      return this._active;
+    },
+    popUp : function () {
+      if (this.active)
+	return;
+
+      if (this._firstTry) {
+	this._inputField.reposition();
+	this._firstTry = false;
+      };
+
+      // update
+
+      var menu;
+      if (menu = this.getMenuByContext()) {
+	menu.show();
+// Update bounding box
+      }
+      else {
+//	this.hide();
+      };
+
+      // Focus on input field
+      this.inputField.element.focus();
+    }
+  };
+
+  /**
+     Regex object for checking the context of the hint
+   */
+  KorAP.ContextAnalyzer = {
+    create : function (regex) {
+      return Object.create(KorAP.ContextAnalyzer)._init(regex);
+    },
+    _init : function (regex) {
+      try {
+	this._regex = new RegExp(regex);
+      }
+      catch (e) {
+	KorAP.log("error", e);
+	return;
+      };
+      return this;
+    },
+    test : function (text) {
+      if (!this._regex.exec(text))
+	return;
+      return RegExp.$1;
+    }
+  };
+
+
+  /**
+   * List of items for drop down menu (complete).
+   * Only a sublist of the menu is filtered (live).
+   * Only a sublist of the filtered menu is visible (shown).
+   */
+  KorAP.Menu = {
+    _position : 0,  // position in the active list
+    _active   : -1, // active item in the item list
+
+    /**
+     * Create new Menu based on the action prefix
+     * and a list of menu items.
+     *
+     * @this {Menu}
+     * @constructor
+     * @param {string} Context prefix
+     * @param {Array.<Array.<string>>} List of menu items
+     */
+    create : function (context, items) {
+      return Object.create(KorAP.Menu)._init(context, items);
+    },
+
+    /*
+     * Make the previous item in the menu active
+     */
+    prev : function () {
+      if (this._position == -1)
+	return;
+
+      // Set new live item
+      var oldItem = this.liveItem(this._position--);
+      oldItem.active(false);
+      var newItem = this.liveItem(this._position);
+
+      // The previous element is undefined - roll to bottom
+      if (newItem === undefined) {
+	this._position = this.liveLength - 1;
+	newItem = this.liveItem(this._position);
+	this._offset = this.liveLength - this.limit;
+	this._showItems(this._offset);
+      }
+
+      // The previous element is outside the view - roll up
+      else if (this._position < this._offset) {
+	this._removeLast();
+	this._offset--;
+	this._prepend(this._list[this._position]);
+      };
+      newItem.active(true);
+    },
+
+    /*
+     * Make the next item in the menu active
+     */
+    next : function () {
+      // No active element set
+      if (this._position == -1)
+	return;
+
+      // Set new live item
+      var oldItem = this.liveItem(this._position++);
+      oldItem.active(false);
+      var newItem = this.liveItem(this._position);
+
+      // The next element is undefined - roll to top
+      if (newItem === undefined) {
+	this._offset = 0;
+	this._position = 0;
+	newItem = this.liveItem(0);
+	this._showItems(0);
+      }
+
+      // The next element is outside the view - roll down
+      else if (this._position >= (this.limit + this._offset)) {
+	this._removeFirst();
+	this._offset++;
+	this._append(this._list[this._position]);
+      };
+      newItem.active(true);
+    },
+
+    /**
+     * Delete all visible items from the menu element
+     */
+    delete : function () {
+      var child;
+      for (var i = 0; i <= this.limit; i++)
+	if (child = this.shownItem(i))
+	  child.lowlight();
+      while (child = this._element.firstChild)
+	this._element.removeChild(child);
+    },
+
+    /**
+     * Filter the list and make it visible
+     *
+     * @param {string} Prefix for filtering the list
+     */
+    show : function (prefix) {
+      this._prefix = prefix;
+
+      // Initialize the list
+      if (!this._initList())
+	return;
+
+      // show based on offset
+      this._showItems(0);
+
+      // Set the first element to active
+      this.liveItem(0).active(true);
+      this._position = 0;
+      this._active = this._list[0];
+
+      // Add classes for rolling menus
+      this._boundary(true);
+    },
+
+    /**
+     * Get the prefix for filtering,
+     * e.g. &quot;ve"&quot; for &quot;verb&quot;
+     */
+    get prefix () {
+      return this._prefix || '';
+    },
+
+    /**
+     * Get the numerical value for limit
+     */
+    get limit () {
+      return KorAP.limit;
+    },
+
+    /**
+     * Get the context of the menue,
+     * e.g. &quot;tt/&quot; for the tree tagger menu
+     */
+    get context () {
+      return this._context;
+    },
+
+    /**
+     * Get a specific item from the complete list
+     *
+     * @param {number} index of the list item
+     */
+    item : function (index) {
+      return this._items[index]
+    },
+
+    /**
+     * Get a specific item from the filtered list
+     *
+     * @param {number} index of the list item
+     */
+    liveItem : function (index) {
+      if (this._list === undefined)
+	if (!this._initList())
+	  return;
+
+      return this._items[this._list[index]];
+    },
+    /*
+     * Get a specific item from the visible list
+     *
+     * @param {number} index of the list item
+     */
+    shownItem : function (index) {
+      if (index >= this.limit)
+	return;
+      return this.liveItem(this._offset + index);
+    },
+    get element () {
+      return this._element;
+    },
+    get length () {
+      return this._items.length;
+    },
+    get liveLength () {
+      if (this._list === undefined)
+	this._initList();
+      return this._list.length;
+    },
+    chooseHint : function (e) {
+/*
+      var element = e.target;
+      while (element.nodeName == "STRONG" || element.nodeName == "SPAN")
+	element = element.parentNode;
+
+      if (element === undefined || element.nodeName != "LI")
+	return;
+
+      var action = element.getAttribute('data-action');
+      hint.insertText(action);
+      var menu = hint.menu();
+      menu.hide();
+
+      // Fill this with the correct value
+      var show;
+      if ((show = hint.analyzeContext()) != "-") {
+	menu.show(show);
+	menu.update(
+	  hint._search.getBoundingClientRect().right
+	);
+      };
+
+      hint._search.focus();
+*/
+    },
+
+    _reset : function () {
+      this._offset = 0;
+      this._pos = 0;
+      this._prefix = undefined;
+    },
+    _boundary : function (bool) {
+      this.item(this._list[0]).noMore(bool);
+      this.item(this._list[this._list.length - 1]).noMore(bool);
+    },
+    _initList : function () {
+      if (this._list === undefined)
+	this._list = [];
+      else if (this._list.length != 0) {
+	this._boundary(false);
+	this._list.length = 0;
+      };
+
+      this._offset = 0;
+
+      if (this.prefix.length <= 0) {
+	for (var i = 0; i < this._items.length; i++)
+	  this._list.push(i);
+	return true;
+      };
+
+      var pos;
+      var paddedPrefix = " " + this.prefix;
+      for (pos = 0; pos < this._items.length; pos++) {
+	if ((this.item(pos).lcfield.indexOf(paddedPrefix)) >= 0)
+	  this._list.push(pos);
+      };
+      if (this._list.length == 0) {
+	for (pos = 0; pos < this._items.length; pos++) {
+	  if ((this.item(pos).lcfield.indexOf(this.prefix)) >= 0)
+	    this._list.push(pos);
+	};
+      };
+
+      // Filter was successful
+      return this._list.length > 0 ? true : false;
+    },
+
+    _removeFirst : function () {
+      this.item(this._list[this._offset]).lowlight();
+      this._element.removeChild(this._element.firstChild);
+    },
+
+    _removeLast : function () {
+      this.item(this._list[this._offset + this.limit - 1]).lowlight();
+      this._element.removeChild(this._element.lastChild);
+    },
+
+    // Append item to the shown list based on index
+    _append : function (i) {
+      var item = this.item(i);
+
+      // Highlight based on prefix
+      if (this.prefix.length > 0)
+	item.highlight(this.prefix);
+
+      // Append element
+      this.element.appendChild(item.element);
+    },
+
+    // Prepend item to the shown list based on index
+    _prepend : function (i) {
+      var item = this.item(i);
+
+      // Highlight based on prefix
+      if (this.prefix.length > 0)
+	item.highlight(this.prefix);
+
+      // Append element
+      this.element.insertBefore(
+	item.element,
+	this.element.firstChild
+      );
+    },
+    _init : function (context, items) {
+      this._context = context;
+      this._element = document.createElement("ul");
+      this._element.style.opacity = 0;
+      this.active = false;
+/*
+  Todo:
+      this._element.addEventListener("click", chooseHint, false);
+*/
+      this._items = new Array();
+      var i;
+      for (i in items)
+	this._items.push(KorAP.MenuItem.create(items[i]));
+
+      this._reset();
+      return this;
+    },
+
+    _showItems : function (offset) {
+      this.delete();
+
+      // Use list
+      var shown = 0;
+      var i;
+      for (i in this._list) {
+
+	// Don't show - it's before offset
+	if (shown++ < offset)
+	  continue;
+
+	this._append(this._list[i]);
+
+	if (shown >= (this.limit + this._offset))
+	  break;
+      };
+    }
+  };
+
+
+  /**
+   * Item in the Dropdown menu
+   */
+  KorAP.MenuItem = {
+
+    /**
+     * Create a new MenuItem object.
+     *
+     * @constructor
+     * @this {MenuItem}
+     * @param {Array.<string>} An array object of name, action and
+     *   optionally a description
+     */
+    create : function (params) {
+      return Object.create(KorAP.MenuItem)._init(params);
+    },
+
+    /**
+     * Get the name of the item
+     */
+    get name () {
+      return this._name;
+    },
+
+    /**
+     * Get the action string
+     */
+    get action () {
+      return this._action;
+    },
+
+    /**
+     * Get the description of the item
+     */
+    get desc () {
+      return this._desc;
+    },
+
+    /**
+     * Get the lower case field
+     */
+    get lcfield () {
+      return this._lcfield;
+    },
+
+    /**
+     * Check or set if the item is active
+     *
+     * @param {boolean|null} State of activity
+     */
+    active : function (bool) {
+      var cl = this.element.classList;
+      if (bool === undefined)
+	return cl.contains("active");
+      else if (bool)
+	cl.add("active");
+      else
+	cl.remove("active");
+    },
+
+    /**
+     * Check or set if the item is
+     * at the boundary of the menu
+     * list
+     *
+     * @param {boolean|null} State of activity
+     */
+    noMore : function (bool) {
+      var cl = this.element.classList;
+      if (bool === undefined)
+	return cl.contains("no-more");
+      else if (bool)
+	cl.add("no-more");
+      else
+	cl.remove("no-more");
+    },
+
+    /**
+     * Get the document element of the menu item
+     */
+    get element () {
+      // already defined
+      if (this._element !== undefined)
+	return this._element;
+
+      // Create list item
+      var li = document.createElement("li");
+      li.setAttribute("data-action", this._action);
+
+      // Create title
+      var name =  document.createElement("strong");
+      name.appendChild(document.createTextNode(this._name));
+
+      li.appendChild(name);
+
+      // Create description
+      if (this._desc !== undefined) {
+	var desc = document.createElement("span");
+	desc.appendChild(document.createTextNode(this._desc));
+	li.appendChild(desc);
+      };
+      return this._element = li;
+    },
+
+    /**
+     * Highlight parts of the item
+     *
+     * @param {string} Prefix string for highlights
+     */
+    highlight : function (prefix) {
+      var e = this.element;
+      this._highlight(e.firstChild, prefix);
+      if (this._desc !== undefined)
+	this._highlight(e.lastChild, prefix);
+    },
+
+    /**
+     * Remove highlight of the menu item
+     */
+    lowlight : function () {
+      var e = this.element;
+      e.firstChild.innerHTML = this._name;
+      if (this._desc !== undefined)
+	e.lastChild.innerHTML = this._desc;
+    },
+
+    // Initialize menu item
+    _init : function (params) {
+      if (params[0] === undefined || params[1] === undefined)
+	throw new Error("Missing parameters");
+
+      this._name   = params[0];
+      this._action = params[1];
+      this._lcfield = " " + this._name.toLowerCase();
+
+      if (params.length > 2) {
+	this._desc = params[2];
+	this._lcfield += " " + this._desc.toLowerCase();
+      };
+      return this;
+    },
+
+    // Highlight a certain element of the menu item
+    _highlight : function (elem, prefix) {
+      var text   = elem.firstChild.nodeValue;
+      var textlc = text.toLowerCase();
+      var pos    = textlc.indexOf(prefix);
+      if (pos >= 0) {
+
+	// First element
+	elem.firstChild.nodeValue = pos > 0 ? text.substr(0, pos) : "";
+
+	// Second element
+	var hl = document.createElement("em");
+	hl.appendChild(
+	  document.createTextNode(text.substr(pos, prefix.length))
+	);
+	elem.appendChild(hl);
+
+	// Third element
+	elem.appendChild(
+	  document.createTextNode(text.substr(pos + prefix.length))
+	);
+      };
+    }
+  };
+}(this.KorAP));
