Added hint and vc to collected kalamar assets
diff --git a/public/js/demo/all.html b/public/js/demo/all.html
index aba76c4..26337fa 100644
--- a/public/js/demo/all.html
+++ b/public/js/demo/all.html
@@ -1,16 +1,15 @@
-<!DOCTYPE html>
+ <!DOCTYPE html>
 <html>
   <head>
     <title>CSS demo</title>
     <meta charset="utf-8" />
     <script src="../lib/dagre/dagre.min.js"></script>
     <script src="../src/util.js"></script>
+    <script src="../src/hint.js"></script>
     <script src="../src/match.js"></script>
     <script src="../src/menu.js"></script>
-    <script src="../src/matchInfo.js"></script>
-
+    <script src="../src/vc.js"></script>
     <script src="./all.js"></script>
-
     <link type="text/css" rel="stylesheet" href="../../css/build/kalamar.css" />
   </head>
   <body>
@@ -29,6 +28,8 @@
 	  <i class="fa fa-arrow-circle-down show-hint" onclick="hint.popUp()"></i>
 -->
 	</div>
+	<div id="vc"></div>
+	in Wikipedia
 	with <span class="select">
 <!-- Change this to js-menu -->
 	  <select name="ql" id="ql-field">
diff --git a/public/js/demo/all.js b/public/js/demo/all.js
index b0871be..dc1e051 100644
--- a/public/js/demo/all.js
+++ b/public/js/demo/all.js
@@ -95,33 +95,6 @@
   "</span>" +
   "<span class=\"context-right\"></span>";
 
-/*
-var available =[
-  'base/s=spans',
-  'corenlp/c=spans',
-  'corenlp/ne=tokens',
-  'corenlp/p=tokens',
-  'corenlp/s=spans',
-  'glemm/l=tokens',
-  'mate/l=tokens',
-  'mate/m=tokens',
-  'mate/p=tokens',
-  'opennlp/p=tokens',
-  'opennlp/s=spans',
-  'tt/l=tokens',
-  'tt/p=tokens',
-  'tt/s=spans'
-];
-*/
-/*
-var match = {
-  'corpusID' : 'WPD',
-  'docID' : 'UUU',
-  'textID' : '01912',
-  'matchID' : 'p121-122'
-};
-*/
-
 var menuContent = [
     ['cnx/c', 'cnx', 'c'],
     ['mate/c', 'mate', 'c'],
@@ -130,6 +103,280 @@
     ['tt/c', 'tt', 'c']
 ];
 
+var namedEntities = [
+  ["I-LOC",  "I-LOC ",  "Location"],
+  ["I-MISC", "I-MISC ", "Miscellaneous"],
+  ["I-ORG",  "I-ORG ",  "Organization"],
+  ["I-PER",  "I-PER ",  "Person"]
+];
+
+// http://www.ids-mannheim.de/cosmas2/projekt/referenz/stts/morph.html
+// http://nachhalt.sfb632.uni-potsdam.de/owl-docu/stts.html
+var sttsArray = [
+  // "$.", "$(", "$,"
+  ["ADJA","ADJA ", "Attributive Adjective"],
+  ["ADJD","ADJD ", "Predicative Adjective"],
+  ["ADV","ADV ", "Adverb"],
+  ["APPO","APPO ", "Postposition"],
+  ["APPR","APPR ", "Preposition"],
+  ["APPRART","APPRART ", "Preposition with Determiner"],
+  ["APZR","APZR ","Right Circumposition"],
+  ["ART","ART ", "Determiner"],
+  ["CARD","CARD ", "Cardinal Number"],
+  ["FM","FM ", "Foreign Material"],
+  ["ITJ","ITJ ", "Interjection"],
+  ["KOKOM","KOKOM ", "Comparison Particle"],
+  ["KON","KON ", "Coordinating Conjuncion"],
+  ["KOUI","KOUI ", "Subordinating Conjunction with 'zu'"],
+  ["KOUS","KOUS ", "Subordinating Conjunction with Sentence"],
+  ["NE","NE ", "Named Entity"],
+  ["NN","NN ", "Normal Nomina"],
+  ["PAV", "PAV ", "Pronominal Adverb"],
+  ["PDAT","PDAT ","Attributive Demonstrative Pronoun"],
+  ["PDS","PDS ", "Substitutive Demonstrative Pronoun"],
+  ["PIAT","PIAT ", "Attributive Indefinite Pronoun without Determiner"],
+  ["PIDAT","PIDAT ", "Attributive Indefinite Pronoun with Determiner"],
+  ["PIS","PIS ", "Substitutive Indefinite Pronoun"],
+  ["PPER","PPER ", "Personal Pronoun"],
+  ["PPOSAT","PPOSAT ", "Attributive Possessive Pronoun"],
+  ["PPOSS","PPOSS ", "Substitutive Possessive Pronoun"],
+  ["PRELAT","PRELAT ", "Attributive Relative Pronoun"],
+  ["PRELS","PRELS ", "Substitutive Relative Pronoun"],
+  ["PRF","PRF ", "Reflexive Pronoun"],
+  ["PROAV","PROAV ", "Pronominal Adverb"],
+  ["PTKA","PTKA ","Particle with Adjective"],
+  ["PTKANT","PTKANT ", "Answering Particle"],
+  ["PTKNEG","PTKNEG ", "Negation Particle"],
+  ["PTKVZ","PTKVZ ", "Separated Verbal Particle"],
+  ["PTKZU","PTKZU ", "'zu' Particle"],
+  ["PWAT","PWAT ", "Attributive Interrogative Pronoun"],
+  ["PWAV","PWAV ", "Adverbial Interrogative Pronoun"],
+  ["PWS","PWS ", "Substitutive Interrogative Pronoun"],
+  ["TRUNC","TRUNC ","Truncated"],
+  ["VAFIN","VAFIN ", "Auxiliary Finite Verb"],
+  ["VAINF","VAINF ", "Auxiliary Infinite Verb"],
+  ["VAIMP","VAIMP ", "Auxiliary Finite Imperative Verb"],
+  ["VAPP","VAPP ", "Auxiliary Perfect Participle"],
+  ["VMFIN","VMFIN ", "Modal Finite Verb"],
+  ["VMINF","VMINF ", "Modal Infinite Verb"],
+  ["VMPP","VMPP ", "Modal Perfect Participle"],
+  ["VVFIN","VVFIN ","Finite Verb"],
+  ["VVIMP","VVIMP ", "Finite Imperative Verb"],
+  ["VVINF","VVINF ", "Infinite Verb"],
+  ["VVIZU","VVIZU ", "Infinite Verb with 'zu'"],
+  ["VVPP","VVPP ", "Perfect Participle"],
+  ["XY", "XY ", "Non-Word"]
+];
+
+var mateSttsArray = sttsArray.slice(0);
+mateSttsArray.push(
+  ["<root-POS>","<root-POS>","Root Part of Speech"]
+);
+
+
+var vcExample = {
+  "@type":"koral:docGroup",
+  "operation":"operation:or",
+  "operands":[
+    {
+      "@type":"koral:docGroup",
+      "operation":"operation:and",
+      "operands":[
+        {
+          "@type":"koral:doc",
+          "key":"Titel",
+          "value":"Der Birnbaum",
+          "match":"match:eq"
+        },
+        {
+          "@type":"koral:doc",
+          "key":"Veröffentlichungsort",
+          "value":"Mannheim",
+          "match":"match:eq"
+        },
+        {
+          "@type":"koral:docGroup",
+          "operation":"operation:or",
+          "operands":[
+            {
+              "@type":"koral:doc",
+              "key":"Untertitel",
+              "value":"Aufzucht und Pflege",
+              "match":"match:eq"
+            },
+            {
+              "@type":"koral:doc",
+              "key":"Untertitel",
+              "value":"Gedichte",
+              "match":"match:eq",
+              "rewrites" : [
+                {
+                  "@type": "koral:rewrite",
+                  "src" : "policy",
+                  "operation" : "operation:injection",
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "@type":"koral:doc",
+      "key":"Veröffentlichungsdatum",
+      "type":"type:date",
+      "value":"2015-03-05",
+      "match":"match:geq"
+    }
+  ]
+};
+
+
+KorAP.hintArray = {
+  "-" : [
+    ["Connexor",   "cnx/",     "Constituency, Lemma, Morphology, Part-of-Speech, Syntax"],
+    ["CoreNLP",    "corenlp/", "Named Entities"],
+    ["Mate",       "mate/",     "Lemma, Morphology, Part-of-Speech"],
+    ["OpenNLP",    "opennlp/", "Part-of-Speech"],
+    ["TreeTagger", "tt/",      "Lemma, Part-of-Speech"],
+    ["Xerox Parser", "xip/",   "Constituency, Lemma, Part-of-Speech"]
+  ],
+  "corenlp/" : [
+    ["Named Entity", "ne=" , "Combined"],
+    ["Named Entity", "ne_dewac_175m_600=" , "ne_dewac_175m_600"],
+    ["Named Entity", "ne_hgc_175m_600=",    "ne_hgc_175m_600"]
+  ],
+  "corenlp/ne=" : namedEntities,
+  "corenlp/ne_dewac_175m_600=" : namedEntities,
+  "corenlp/ne_hgc_175m_600=" : namedEntities,
+  "cnx/" : [
+    ["Constituency", "c="],
+    ["Lemma", "l="],
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="],
+    ["Syntax", "syn="]
+  ],
+  "cnx/c=" : [
+    ["np", "np ", "Nominal Phrase"]
+  ],
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/morph.html
+  "cnx/m=" : [
+    ["Abbr","Abbr ", "Nouns: Abbreviation"],
+    ["CMP","CMP ", "Adjective: Comparative"],
+    ["IMP", "IMP ", "Mood: Imperative"],
+    ["IND", "IND ", "Mood: Indicative"],
+    ["INF", "INF ", "Infinitive"],
+    ["ORD","ORD ", "Numeral: Ordinal"],
+    ["PAST", "PAST ", "Tense: past"],
+    ["PCP", "PCP ", "Participle"],
+    ["PERF", "PERF ", "Perfective Participle"],
+    ["PL","PL ", "Nouns: Plural"],
+    ["PRES", "PRES ", "Tense: present"],
+    ["PROG", "PROG ", "Progressive Participle"],
+    ["Prop","Prop ", "Nouns: Proper Noun"],
+    ["SUB", "SUB ", "Mood: Subjunctive"],
+    ["SUP","SUP ", "Adjective: Superlative"]
+  ],
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/morph.html
+  "cnx/p=" : [
+    ["A", "A ", "Adjective"],
+    ["ADV", "ADV ", "Adverb"],
+    ["CC", "CC ", "Coordination Marker"],
+    ["CS", "CS ", "Clause Marker"],
+    ["DET", "DET ", "Determiner"],
+    ["INTERJ", "INTERJ ", "Interjection"],
+    ["N", "N ", "Noun"],
+    ["NUM", "NUM ", "Numeral"],
+    ["PREP", "PREP ", "Preposition"],
+    ["PRON", "PRON ", "Pro-Nominal"],
+    ["V", "V ", "Verb"]
+  ],
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/syntax.html
+  "cnx/syn=" : [
+    ["@ADVL", "@ADVL ", "Adverbial Head"],
+    ["@AUX", "@AUX ", "Auxiliary Verb"],
+    ["@CC", "@CC ", "Coordination"]
+    ["@MAIN", "@MAIN ", "Main Verb"],
+    ["@NH", "@NH ", "Nominal Head"],
+    ["@POSTMOD", "@POSTMOD ", "Postmodifier"],
+    ["@PREMARK", "@PREMARK ", "Preposed Marker"],
+    ["@PREMOD", "@POSTMOD ", "Premodifier"]
+  ],
+  "opennlp/" : [
+    ["Part-of-Speech", "p="]
+  ],
+  "opennlp/p=" : sttsArray,
+  "xip/" : [
+    ["Constituency", "c="],
+    // Inactive: ["Dependency", "d="],
+    ["Lemma", "l="],
+    ["Part-of-Speech", "p="],
+  ],
+  // "xip/c=" : [],
+  // Inactive: "xip/d=" : [],
+  // "xip/p=" : [],
+  "tt/" : [
+    ["Lemma", "l="],
+    ["Part-of-Speech", "p="]
+  ],
+  "tt/p=" : sttsArray,
+  "mate/" : [
+    // Inactive: "d" : ["d=", "Dependency"],
+    ["Lemma", "l="],
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="]
+  ],
+  // Inactive: mate/d=
+  "mate/p=" : mateSttsArray,
+  "mate/m=" : [
+    ["Case", "case:"],
+    ["Degree", "degree:"],
+    ["Gender", "gender:"],
+    ["Mood", "mood:"],
+    ["Number", "number:"],
+    ["Person", "person:"],
+    ["Tense","tense:"],
+    ["No type", "<no-type> "]
+  ],
+  "mate/m=case:" : [
+    ["acc", "acc ", "Accusative"],
+    ["dat","dat ", "Dative"],
+    ["gen", "gen ","Genitive"],
+    ["nom","nom ", "Nominative"],
+    ["*","* ", "Undefined"]
+  ],
+  "mate/m=degree:" : [
+    ["comp","comp ", "Comparative"],
+    ["pos","pos ", "Positive"],
+    ["sup","sup ", "Superative"]
+  ],
+  "mate/m=gender:" : [
+    ["fem", "fem ", "Feminium"],
+    ["masc", "masc ", "Masculinum"],
+    ["neut","neut ", "Neuter"],
+    ["*","* ","Undefined"]
+  ],
+  "mate/m=mood:" : [
+    ["imp","imp ", "Imperative"],
+    ["ind","ind ", "Indicative"],
+    ["subj","subj ", "Subjunctive"]
+  ],
+  "mate/m=number:" : [
+    ["pl","pl ","Plural"],
+    ["sg","sg ","Singular"],
+    ["*","* ","Undefined"]
+  ],
+  "mate/m=person:" : [
+    ["1","1 ", "First Person"],
+    ["2","2 ", "Second Person"],
+    ["3","3 ", "Third Person"]
+  ],
+  "mate/m=tense:" : [
+    ["past","past ", "Past"],
+    ["pres","pres ", "Present"]
+  ]
+};
+
 // Parse and show the table
 // Override getMatchInfo API call
 KorAP.API.getMatchInfo = function(match, callObj) {
@@ -141,6 +388,7 @@
   }
 };
 
+
 /**
  * Do some things at the beginning.
  */
@@ -154,15 +402,14 @@
     menuContent
   );
 
+  var vc = KorAP.VirtualCollection.render(vcExample);
+  document.getElementById('vc').appendChild(vc.element());
+
+
   // Don't hide!!!
   menu.hide = function () {};
   document.getElementById('menu').appendChild(menu.element());
   menu.limit(3);
   menu.show();
   menu.focus();
-  /*
-  var e = KorAP.MatchInfo.create(match, available);
-  document.getElementById('WPD-WWW.03313-p102-103').children[0].appendChild(e.element());
-  e.addTree('cnx', 'c');
-  */
 };
diff --git a/public/js/demo/hint.html b/public/js/demo/hint.html
new file mode 100644
index 0000000..154bcaf
--- /dev/null
+++ b/public/js/demo/hint.html
@@ -0,0 +1,248 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Hint demo</title>
+    <meta charset="utf-8" />
+    <script src="../src/menu.js"></script>
+    <script src="../src/hint.js"></script>
+    <link type="text/css" rel="stylesheet" href="../../css/build/kalamar.css" />
+    <script>
+// http://www.nlpado.de/~sebastian/software/ner_german.shtml
+// http://www.cnts.ua.ac.be/conll2003/ner/
+var namedEntities = [
+  ["I-LOC",  "I-LOC ",  "Location"],
+  ["I-MISC", "I-MISC ", "Miscellaneous"],
+  ["I-ORG",  "I-ORG ",  "Organization"],
+  ["I-PER",  "I-PER ",  "Person"]
+];
+
+// http://www.ids-mannheim.de/cosmas2/projekt/referenz/stts/morph.html
+// http://nachhalt.sfb632.uni-potsdam.de/owl-docu/stts.html
+var sttsArray = [
+  // "$.", "$(", "$,"
+  ["ADJA","ADJA ", "Attributive Adjective"],
+  ["ADJD","ADJD ", "Predicative Adjective"],
+  ["ADV","ADV ", "Adverb"],
+  ["APPO","APPO ", "Postposition"],
+  ["APPR","APPR ", "Preposition"],
+  ["APPRART","APPRART ", "Preposition with Determiner"],
+  ["APZR","APZR ","Right Circumposition"],
+  ["ART","ART ", "Determiner"],
+  ["CARD","CARD ", "Cardinal Number"],
+  ["FM","FM ", "Foreign Material"],
+  ["ITJ","ITJ ", "Interjection"],
+  ["KOKOM","KOKOM ", "Comparison Particle"],
+  ["KON","KON ", "Coordinating Conjuncion"],
+  ["KOUI","KOUI ", "Subordinating Conjunction with 'zu'"],
+  ["KOUS","KOUS ", "Subordinating Conjunction with Sentence"],
+  ["NE","NE ", "Named Entity"],
+  ["NN","NN ", "Normal Nomina"],
+  ["PAV", "PAV ", "Pronominal Adverb"],
+  ["PDAT","PDAT ","Attributive Demonstrative Pronoun"],
+  ["PDS","PDS ", "Substitutive Demonstrative Pronoun"],
+  ["PIAT","PIAT ", "Attributive Indefinite Pronoun without Determiner"],
+  ["PIDAT","PIDAT ", "Attributive Indefinite Pronoun with Determiner"],
+  ["PIS","PIS ", "Substitutive Indefinite Pronoun"],
+  ["PPER","PPER ", "Personal Pronoun"],
+  ["PPOSAT","PPOSAT ", "Attributive Possessive Pronoun"],
+  ["PPOSS","PPOSS ", "Substitutive Possessive Pronoun"],
+  ["PRELAT","PRELAT ", "Attributive Relative Pronoun"],
+  ["PRELS","PRELS ", "Substitutive Relative Pronoun"],
+  ["PRF","PRF ", "Reflexive Pronoun"],
+  ["PROAV","PROAV ", "Pronominal Adverb"],
+  ["PTKA","PTKA ","Particle with Adjective"],
+  ["PTKANT","PTKANT ", "Answering Particle"],
+  ["PTKNEG","PTKNEG ", "Negation Particle"],
+  ["PTKVZ","PTKVZ ", "Separated Verbal Particle"],
+  ["PTKZU","PTKZU ", "'zu' Particle"],
+  ["PWAT","PWAT ", "Attributive Interrogative Pronoun"],
+  ["PWAV","PWAV ", "Adverbial Interrogative Pronoun"],
+  ["PWS","PWS ", "Substitutive Interrogative Pronoun"],
+  ["TRUNC","TRUNC ","Truncated"],
+  ["VAFIN","VAFIN ", "Auxiliary Finite Verb"],
+  ["VAINF","VAINF ", "Auxiliary Infinite Verb"],
+  ["VAIMP","VAIMP ", "Auxiliary Finite Imperative Verb"],
+  ["VAPP","VAPP ", "Auxiliary Perfect Participle"],
+  ["VMFIN","VMFIN ", "Modal Finite Verb"],
+  ["VMINF","VMINF ", "Modal Infinite Verb"],
+  ["VMPP","VMPP ", "Modal Perfect Participle"],
+  ["VVFIN","VVFIN ","Finite Verb"],
+  ["VVIMP","VVIMP ", "Finite Imperative Verb"],
+  ["VVINF","VVINF ", "Infinite Verb"],
+  ["VVIZU","VVIZU ", "Infinite Verb with 'zu'"],
+  ["VVPP","VVPP ", "Perfect Participle"],
+  ["XY", "XY ", "Non-Word"]
+];
+
+var mateSttsArray = sttsArray.slice(0);
+mateSttsArray.push(
+  ["<root-POS>","<root-POS>","Root Part of Speech"]
+);
+
+
+var hintArray = {
+  "-" : [
+    ["Connexor",   "cnx/",     "Constituency, Lemma, Morphology, Part-of-Speech, Syntax"],
+    ["CoreNLP",    "corenlp/", "Named Entities"],
+    ["Mate",       "mate/",     "Lemma, Morphology, Part-of-Speech"],
+    ["OpenNLP",    "opennlp/", "Part-of-Speech"],
+    ["TreeTagger", "tt/",      "Lemma, Part-of-Speech"],
+    ["Xerox Parser", "xip/",   "Constituency, Lemma, Part-of-Speech"]
+  ],
+  "corenlp/" : [
+    ["Named Entity", "ne=" , "Combined"],
+    ["Named Entity", "ne_dewac_175m_600=" , "ne_dewac_175m_600"],
+    ["Named Entity", "ne_hgc_175m_600=",    "ne_hgc_175m_600"]
+  ],
+  "corenlp/ne=" : namedEntities,
+  "corenlp/ne_dewac_175m_600=" : namedEntities,
+  "corenlp/ne_hgc_175m_600=" : namedEntities,
+  "cnx/" : [
+    ["Constituency", "c="],
+    ["Lemma", "l="],
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="],
+    ["Syntax", "syn="]
+  ],
+  "cnx/c=" : [
+    ["np", "np ", "Nominal Phrase"]
+  ],
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/morph.html
+  "cnx/m=" : [
+    ["Abbr","Abbr ", "Nouns: Abbreviation"],
+    ["CMP","CMP ", "Adjective: Comparative"],
+    ["IMP", "IMP ", "Mood: Imperative"],
+    ["IND", "IND ", "Mood: Indicative"],
+    ["INF", "INF ", "Infinitive"],
+    ["ORD","ORD ", "Numeral: Ordinal"],
+    ["PAST", "PAST ", "Tense: past"],
+    ["PCP", "PCP ", "Participle"],
+    ["PERF", "PERF ", "Perfective Participle"],
+    ["PL","PL ", "Nouns: Plural"],
+    ["PRES", "PRES ", "Tense: present"],
+    ["PROG", "PROG ", "Progressive Participle"],
+    ["Prop","Prop ", "Nouns: Proper Noun"],
+    ["SUB", "SUB ", "Mood: Subjunctive"],
+    ["SUP","SUP ", "Adjective: Superlative"]
+  ],
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/morph.html
+  "cnx/p=" : [
+    ["A", "A ", "Adjective"],
+    ["ADV", "ADV ", "Adverb"],
+    ["CC", "CC ", "Coordination Marker"],
+    ["CS", "CS ", "Clause Marker"],
+    ["DET", "DET ", "Determiner"],
+    ["INTERJ", "INTERJ ", "Interjection"],
+    ["N", "N ", "Noun"],
+    ["NUM", "NUM ", "Numeral"],
+    ["PREP", "PREP ", "Preposition"],
+    ["PRON", "PRON ", "Pro-Nominal"],
+    ["V", "V ", "Verb"]
+  ],
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/syntax.html
+  "cnx/syn=" : [
+    ["@ADVL", "@ADVL ", "Adverbial Head"],
+    ["@AUX", "@AUX ", "Auxiliary Verb"],
+    ["@CC", "@CC ", "Coordination"]
+    ["@MAIN", "@MAIN ", "Main Verb"],
+    ["@NH", "@NH ", "Nominal Head"],
+    ["@POSTMOD", "@POSTMOD ", "Postmodifier"],
+    ["@PREMARK", "@PREMARK ", "Preposed Marker"],
+    ["@PREMOD", "@POSTMOD ", "Premodifier"]
+  ],
+  "opennlp/" : [
+    ["Part-of-Speech", "p="]
+  ],
+  "opennlp/p=" : sttsArray,
+  "xip/" : [
+    ["Constituency", "c="],
+    // Inactive: ["Dependency", "d="],
+    ["Lemma", "l="],
+    ["Part-of-Speech", "p="],
+  ],
+  // "xip/c=" : [],
+  // Inactive: "xip/d=" : [],
+  // "xip/p=" : [],
+  "tt/" : [
+    ["Lemma", "l="],
+    ["Part-of-Speech", "p="]
+  ],
+  "tt/p=" : sttsArray,
+  "mate/" : [
+    // Inactive: "d" : ["d=", "Dependency"],
+    ["Lemma", "l="],
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="]
+  ],
+  // Inactive: mate/d=
+  "mate/p=" : mateSttsArray,
+  "mate/m=" : [
+    ["Case", "case:"],
+    ["Degree", "degree:"],
+    ["Gender", "gender:"],
+    ["Mood", "mood:"],
+    ["Number", "number:"],
+    ["Person", "person:"],
+    ["Tense","tense:"],
+    ["No type", "<no-type> "]
+  ],
+  "mate/m=case:" : [
+    ["acc", "acc ", "Accusative"],
+    ["dat","dat ", "Dative"],
+    ["gen", "gen ","Genitive"],
+    ["nom","nom ", "Nominative"],
+    ["*","* ", "Undefined"]
+  ],
+  "mate/m=degree:" : [
+    ["comp","comp ", "Comparative"],
+    ["pos","pos ", "Positive"],
+    ["sup","sup ", "Superative"]
+  ],
+  "mate/m=gender:" : [
+    ["fem", "fem ", "Feminium"],
+    ["masc", "masc ", "Masculinum"],
+    ["neut","neut ", "Neuter"],
+    ["*","* ","Undefined"]
+  ],
+  "mate/m=mood:" : [
+    ["imp","imp ", "Imperative"],
+    ["ind","ind ", "Indicative"],
+    ["subj","subj ", "Subjunctive"]
+  ],
+  "mate/m=number:" : [
+    ["pl","pl ","Plural"],
+    ["sg","sg ","Singular"],
+    ["*","* ","Undefined"]
+  ],
+  "mate/m=person:" : [
+    ["1","1 ", "First Person"],
+    ["2","2 ", "Second Person"],
+    ["3","3 ", "Third Person"]
+  ],
+  "mate/m=tense:" : [
+    ["past","past ", "Past"],
+    ["pres","pres ", "Present"]
+  ]
+};
+
+    </script>
+  </head>
+  <body>
+    <header>
+      <form autocomplete="off" action="/kalamar">
+	<div id="searchbar">
+	  <input type="search"
+		 placeholder="Find ..."
+		 name="q"
+		 id="q-field"
+		 autofocus="autofocus" />
+	  <button type="submit"><span>Go</span></button>
+	</div>
+      </form>
+    </header>
+    <script>
+KorAP.hintArray = hintArray;
+var input = KorAP.Hint.create();
+    </script>
+  </body>
+</html>
diff --git a/public/js/demo/match.html b/public/js/demo/match.html
index 373b0ee..7b51996 100644
--- a/public/js/demo/match.html
+++ b/public/js/demo/match.html
@@ -4,6 +4,7 @@
     <title>Match demo</title>
     <meta charset="utf-8" />
     <script src="../lib/dagre/dagre.min.js"></script>
+    <script src="../src/util.js"></script>
     <script src="../src/menu.js"></script>
     <script src="../src/match.js"></script>
     <link type="text/css"
@@ -31,6 +32,21 @@
     </style>
   </head>
   <body>
+    <div id="search">
+      <ol class="align-left">
+	<li data-corpus-id="WPD"
+	    data-doc-id="WWW"
+	    data-text-id="03313"
+	    data-match-id="p102-103"
+	    data-available-info="base/s=spans corenlp/c=spans corenlp/ne=tokens corenlp/p=tokens corenlp/s=spans glemm/l=tokens mate/l=tokens mate/m=tokens mate/p=tokens opennlp/p=tokens opennlp/s=spans tt/l=tokens tt/p=tokens tt/s=spans"
+	    id="WPD-WWW.03313-p102-103">
+	  <div>
+	    <div class="snippet startMore endMore"><span class="context-left">In diesem Beispiel ist zu sehen, dass die beiden Variablen a und b lediglich ihre Werte an die Funktion </span><span class="match">test</span><span class="context-right"> übergeben, aber im Gegensatz zu einem Referenzparamter dabei unverändert bleiben.</span></div>
+	  </div>
+	  <p class="ref"><strong>Wertparameter</strong> by Hubi,Zwobot,4; published on 2005-03-28 as WWW.03313 (WPD)</p>
+	</li>
+      </ol>
+    </div>
 
     <script>
 var snippet = "<span title=\"cnx/l:meist\">" +
@@ -130,31 +146,6 @@
   "</span>" +
   "<span class=\"context-right\"></span>";
 
-var available =[
-  'base/s=spans',
-  'corenlp/c=spans',
-  'corenlp/ne=tokens',
-  'corenlp/p=tokens',
-  'corenlp/s=spans',
-  'glemm/l=tokens',
-  'mate/l=tokens',
-  'mate/m=tokens',
-  'mate/p=tokens',
-  'opennlp/p=tokens',
-  'opennlp/s=spans',
-  'tt/l=tokens',
-  'tt/p=tokens',
-  'tt/s=spans'
-];
-
-var match = {
-  'corpusID' : 'WPD',
-  'docID' : 'UUU',
-  'textID' : '01912',
-  'pos' : 'p121-122',
-  'available' : available
-};
-
 // Parse and show the table
 // Override getMatchInfo API call
 KorAP.API.getMatchInfo = function(match, callObj) {
@@ -166,31 +157,7 @@
   }
 };
 
-var e = KorAP.Match.create(match).open();
-
-document.getElementsByTagName('body')[0].appendChild(e.element());
-
-e.addTree('cnx', 'c');
-
-
-
-/*
-var t = KorAP.MatchInfo.create(match, available).getTable();
-document.getElementsByClassName('matchtable')[0]
-.appendChild(t.element());
-
-// parse and show the tree
-KorAP.API.getMatchInfo = function() {
-  return { "snippet": treeSnippet };
-};
-
-var tree = KorAP.MatchInfo.create(match, available).getTree();
-document.getElementsByClassName('matchtree')[0]
-.getElementsByTagName('div')[0]
-.appendChild(tree.element());
-
-tree.center();
-*/
+KorAP.init();
     </script>
 
     <!--
diff --git a/public/js/demo/vc.html b/public/js/demo/vc.html
index 0a7efa9..ae6aef1 100644
--- a/public/js/demo/vc.html
+++ b/public/js/demo/vc.html
@@ -5,9 +5,17 @@
     <meta charset="utf-8" />
     <script src="../src/menu.js"></script>
     <script src="../src/vc.js"></script>
-    <link href="../../css/vc.css" rel="stylesheet" type="text/css"></link>
-    <link href="../../css/menu.css" rel="stylesheet" type="text/css"></link>
+    <link href="../../css/build/kalamar.css" rel="stylesheet" type="text/css"></link>
     <style type="text/css" rel="stylesheet">
+
+body {
+  background-color: #7ba400;
+  color: white;
+  font-family: tahoma, verdana, arial;
+  font-size: 10pt;
+  margin: 20px;
+}
+
 .info {
   background-color:white;
   color: black;
diff --git a/public/js/runner/hint.html b/public/js/runner/hint.html
index 36538fd..81f0422 100644
--- a/public/js/runner/hint.html
+++ b/public/js/runner/hint.html
@@ -8,6 +8,7 @@
   <script src="../lib/jasmine-2.1.1/jasmine.js"></script>
   <script src="../lib/jasmine-2.1.1/jasmine-html.js"></script>
   <script src="../lib/jasmine-2.1.1/boot.js"></script>
+  <script src="../src/menu.js"></script>
   <script src="../src/hint.js"></script>
   <script src="../spec/hintSpec.js"></script>
 </head>
diff --git a/public/js/spec/hintSpec.js b/public/js/spec/hintSpec.js
index a7232d4..66c831f 100644
--- a/public/js/spec/hintSpec.js
+++ b/public/js/spec/hintSpec.js
@@ -24,7 +24,146 @@
 };
 
 
-describe('KorAP.MenuItem', function () {
+describe('KorAP.InputField', function () {
+  var input;
+
+  beforeEach(function () {
+    input = document.createElement("input");
+    input.setAttribute("type", "text");
+    input.setAttribute("value", "abcdefghijklmno");
+    input.style.position = 'absolute';
+    input.style.top  = "20px";
+    input.style.left = "30px";
+    input.focus();
+    input.selectionStart = 5;
+  });
+
+  afterAll(function () {
+    try {
+      // document.getElementsByTagName("body")[0].removeChild(input);
+      document.getElementsByTagName("body")[0].removeChild(
+	document.getElementById("searchMirror")
+      );
+    }
+    catch (e) {};
+  });
+
+  it('should be initializable', function () {
+    // Supports: context, searchField
+    var inputField = KorAP.InputField.create(input);
+    expect(inputField._element).not.toBe(undefined);
+  });
+
+  it('should have text', function () {
+    expect(input.value).toEqual('abcdefghijklmno');
+    var inputField = KorAP.InputField.create(input);
+
+    expect(inputField.value()).toEqual("abcdefghijklmno");
+
+    expect(inputField.element().selectionStart).toEqual(5);
+    expect(inputField.split()[0]).toEqual("abcde");
+    expect(inputField.split()[1]).toEqual("fghijklmno");
+
+    inputField.insert("xyz");
+    expect(inputField.value()).toEqual('abcdexyzfghijklmno');
+    expect(inputField.split()[0]).toEqual("abcdexyz");
+    expect(inputField.split()[1]).toEqual("fghijklmno");
+  });
+
+  it('should be correctly positioned', function () {
+    expect(input.value).toEqual('abcdefghijklmno');
+    var inputField = KorAP.InputField.create(input);
+    document.getElementsByTagName("body")[0].appendChild(input);
+    inputField.reposition();
+    expect(inputField.mirror().style.left).toEqual("30px");
+    expect(inputField.mirror().style.top.match(/^(\d+)px$/)[1]).toBeGreaterThan(20);
+  });
+
+  it('should have a correct context', function () {
+    expect(input.value).toEqual('abcdefghijklmno');
+    var inputField = KorAP.InputField.create(input);
+
+    expect(inputField.value()).toEqual("abcdefghijklmno");
+
+    expect(inputField.element().selectionStart).toEqual(5);
+    expect(inputField.split()[0]).toEqual("abcde");
+    expect(inputField.context()).toEqual("abcde");
+  });
+
+/*
+  it('should be correctly triggerable', function () {
+    // https://developer.mozilla.org/samples/domref/dispatchEvent.html
+    var hint = KorAP.Hint.create({ "inputField" : input });
+    emitKeyboardEvent(hint.inputField.element, "keypress", 20);
+  });
+*/
+});
+
+
+describe('KorAP.ContextAnalyzer', function () {
+  it('should be initializable', function () {
+    var analyzer = KorAP.ContextAnalyzer.create(")");
+    expect(analyzer).toBe(undefined);
+
+    analyzer = KorAP.ContextAnalyzer.create(".+?");
+    expect(analyzer).not.toBe(undefined);
+
+  });
+
+  it('should check correctly', function () {
+    analyzer = KorAP.ContextAnalyzer.create(KorAP.context);
+    expect(analyzer.test("cnx/]cnx/c=")).toEqual("cnx/c=");
+    expect(analyzer.test("cnx/c=")).toEqual("cnx/c=");
+    expect(analyzer.test("cnx/c=np mate/m=mood:")).toEqual("mate/m=mood:");
+    expect(analyzer.test("impcnx/")).toEqual("impcnx/");
+    expect(analyzer.test("cnx/c=npcnx/")).toEqual("npcnx/");
+    expect(analyzer.test("mate/m=degree:pos corenlp/ne_dewac_175m_600="))
+      .toEqual("corenlp/ne_dewac_175m_600=");
+  });
+});
+
+
+describe('KorAP.Hint', function () {
+  KorAP.hintArray = {
+    "corenlp/" : [
+      ["Named Entity", "ne=" , "Combined"],
+      ["Named Entity", "ne_dewac_175m_600=" , "ne_dewac_175m_600"],
+      ["Named Entity", "ne_hgc_175m_600=",    "ne_hgc_175m_600"]
+    ]
+  };
+
+  beforeEach(function () {
+    input = document.createElement("input");
+    input.setAttribute("type", "text");
+    input.setAttribute("value", "abcdefghijklmno");
+    input.style.position = 'absolute';
+    input.style.top  = "20px";
+    input.style.left = "30px";
+    input.focus();
+    input.selectionStart = 5;
+  });
+
+  it('should be initializable', function () {
+    // Supports: context, searchField
+    var hint = KorAP.Hint.create({
+      inputField : input
+    });
+
+    expect(hint).toBeTruthy();
+  });
+});
+
+
+
+
+
+
+
+
+
+
+
+xdescribe('KorAP.MenuItem', function () {
   it('should be initializable', function () {
 
     expect(
@@ -237,7 +376,7 @@
 });
 
 
-describe('KorAP.Menu', function () {
+describe('KorAP.HintMenu', function () {
 
   var list = [
     ["Constituency", "c=", "Example 1"],
@@ -250,12 +389,12 @@
 
   it('should be initializable', function () {
 
-    var menu = KorAP.Menu.create("cnx/", list);
-    expect(menu.context).toEqual('cnx/');
-    expect(menu.element.nodeName).toEqual('UL');
-    expect(menu.element.style.opacity).toEqual("0");
+    var menu = KorAP.HintMenu.create("cnx/", list);
+    expect(menu.context()).toEqual('cnx/');
+    expect(menu.element().nodeName).toEqual('UL');
+    expect(menu.element().style.opacity).toEqual("0");
 
-    KorAP.limit = 8;
+    menu.limit(8);
 
     // view
     menu.show();
@@ -269,517 +408,7 @@
     expect(menu.item(2).noMore()).toBe(false);
 
     // Last element in list
-    expect(menu.item(menu.length - 1).active()).toBe(false);
-    expect(menu.item(menu.length - 1).noMore()).toBe(true);
-  });
-
-  it('should be visible', function () {
-    var menu = KorAP.Menu.create("cnx/", list);
-    expect(menu.delete()).toBe(undefined);
-
-    KorAP.limit = 3;
-
-    expect(menu.show()).toBe(undefined);
-    expect(menu.element.firstChild.innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.element.childNodes[1].getAttribute("data-action")).toEqual("l=");
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Check boundaries
-    expect(menu.element.childNodes[0].classList.contains("no-more")).toBe(true);
-    expect(menu.element.childNodes[1].classList.contains("no-more")).toBe(false);
-    expect(menu.element.childNodes[2].classList.contains("no-more")).toBe(false);
-  });
-
-
-  it('should be filterable', function () {
-    var menu = KorAP.Menu.create("cnx/", list);
-
-    KorAP.limit = 3;
-
-    expect(menu.show("o")).toBe(undefined);
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Part-<em>o</em>f-Speech</strong>");
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Check boundaries
-    expect(menu.element.childNodes[0].classList.contains("no-more")).toBe(true);
-    expect(menu.element.childNodes[1].classList.contains("no-more")).toBe(false);
-    expect(menu.element.childNodes[2].classList.contains("no-more")).toBe(true);
-
-
-    KorAP.limit = 2;
-
-    expect(menu.show("o")).toBe(undefined);
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
-    expect(menu.element.childNodes[2]).toBe(undefined);
-
-    // Check boundaries
-    expect(menu.element.childNodes[0].classList.contains("no-more")).toBe(true);
-    expect(menu.element.childNodes[1].classList.contains("no-more")).toBe(false);
-    expect(menu.element.childNodes[2]).toBe(undefined);
-  });
-
-  it('should be nextable', function () {
-    var menu = KorAP.Menu.create("cnx/", list);
-
-    KorAP.limit = 3;
-    expect(menu.show()).toBe(undefined);
-
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate next (1)
-    menu.next();
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate next (2)
-    menu.next();
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate next (3)
-    menu.next();
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate next (4)
-    menu.next();
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Syntax</strong>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate next (5) - ROLL
-    menu.next();
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Active next (6)
-    menu.next();
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-  });
-
-
-  it('should be prevable', function () {
-    var menu = KorAP.Menu.create("cnx/", list);
-
-    KorAP.limit = 3;
-    expect(menu.show()).toBe(undefined);
-
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate prev (1) - roll to bottom
-    menu.prev();
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Syntax</strong>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate prev (2)
-    menu.prev();
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Syntax</strong>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate prev (3)
-    menu.prev();
-    expect(menu.shownItem(0).name).toEqual("Morphology");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name).toEqual("Part-of-Speech");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name).toEqual("Syntax");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate prev (4)
-    menu.prev();
-    expect(menu.shownItem(0).name).toEqual("Lemma");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name).toEqual("Part-of-Speech");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate prev (5)
-    menu.prev();
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name).toEqual("Lemma");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name).toEqual("Morphology");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate next (1)
-    menu.next();
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name).toEqual("Lemma");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2).name).toEqual("Morphology");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-
-    // Activate prev (6)
-    menu.prev();
-
-    // Activate prev (7)
-    menu.prev();
-    expect(menu.shownItem(0).name).toEqual("Morphology");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name).toEqual("Part-of-Speech");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name).toEqual("Syntax");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.element.childNodes[3]).toBe(undefined);
-  });
-
-  it('should be navigatable and filterable (prefix = "o")', function () {
-    var menu = KorAP.Menu.create("cnx/", list);
-
-    KorAP.limit = 2;
-
-    expect(menu.show("o")).toBe(undefined);
-
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (1)
-    menu.next();
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-
-    // Next (2)
-    menu.next();
-    expect(menu.shownItem(0).name).toEqual("Morphology");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name).toEqual("Part-of-Speech");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Part-<em>o</em>f-Speech</strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (3)
-    menu.next();
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-  });
-
-  it('should be navigatable and filterable (prefix = "ex", "e")', function () {
-    var menu = KorAP.Menu.create("cnx/", list);
-
-    KorAP.limit = 2;
-
-    expect(menu.show("ex")).toBe(undefined);
-
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span><em>Ex</em>ample 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>Ex</em>ample 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (1)
-    menu.next();
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span><em>Ex</em>ample 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>Ex</em>ample 2</span>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (2)
-    menu.next();
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span><em>Ex</em>ample 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>Ex</em>ample 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Reset limit
-    KorAP.limit = 5;
-
-    // Change show
-    expect(menu.show("e")).toBe(undefined);
-
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constitu<em>e</em>ncy</strong><span><em>E</em>xample 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>E</em>xample 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (1)
-    menu.next();
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constitu<em>e</em>ncy</strong><span><em>E</em>xample 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>E</em>xample 2</span>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (2)
-    menu.next();
-    expect(menu.shownItem(0).name).toEqual("Constituency");
-    expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constitu<em>e</em>ncy</strong><span><em>E</em>xample 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name).toEqual("Morphology");
-    expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>E</em>xample 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
+    expect(menu.item(menu.length() - 1).active()).toBe(false);
+    expect(menu.item(menu.length() - 1).noMore()).toBe(true);
   });
 });
-
-describe('KorAP.ContextAnalyzer', function () {
-
-  it('should be initializable', function () {
-    var analyzer = KorAP.ContextAnalyzer.create(")");
-    expect(analyzer).toBe(undefined);
-
-    analyzer = KorAP.ContextAnalyzer.create(".+?");
-    expect(analyzer).not.toBe(undefined);
-
-  });
-
-  it('should check correctly', function () {
-    analyzer = KorAP.ContextAnalyzer.create(KorAP.context);
-    expect(analyzer.test("cnx/]cnx/c=")).toEqual("cnx/c=");
-    expect(analyzer.test("cnx/c=")).toEqual("cnx/c=");
-    expect(analyzer.test("cnx/c=np mate/m=mood:")).toEqual("mate/m=mood:");
-    expect(analyzer.test("impcnx/")).toEqual("impcnx/");
-    expect(analyzer.test("cnx/c=npcnx/")).toEqual("npcnx/");
-    expect(analyzer.test("mate/m=degree:pos corenlp/ne_dewac_175m_600="))
-      .toEqual("corenlp/ne_dewac_175m_600=");
-  });
-});
-
-describe('KorAP.InputField', function () {
-  var input;
-
-  beforeAll(function () {
-    input = document.createElement("input");
-    input.setAttribute("type", "text");
-    input.setAttribute("value", "abcdefghijklmno");
-    input.style.position = 'absolute';
-    input.style.top  = "20px";
-    input.style.left = "30px";
-    input.focus();
-    input.selectionStart = 5;
-  });
-
-  afterAll(function () {
-    document.getElementsByTagName("body")[0].removeChild(input);
-    document.getElementsByTagName("body")[0].removeChild(
-      document.getElementById("searchMirror")
-    );
-  });
-
-  it('should be initializable', function () {
-    // Supports: context, searchField
-    var inputField = KorAP.InputField.create(input);
-    expect(inputField._element).not.toBe(undefined);
-  });
-
-  it('should have text', function () {
-    var inputField = KorAP.InputField.create(input);
-
-    expect(inputField.value).toEqual("abcdefghijklmno");
-    expect(inputField.element.selectionStart).toEqual(5);
-    expect(inputField.split()[0]).toEqual("abcde");
-    expect(inputField.split()[1]).toEqual("fghijklmno");
-
-    inputField.insert("xyz");
-    expect(inputField.split()[0]).toEqual("abcdexyz");
-    expect(inputField.split()[1]).toEqual("fghijklmno");
-
-  });
-
-  it('should be correctly positioned', function () {
-    var inputField = KorAP.InputField.create(input);
-    document.getElementsByTagName("body")[0].appendChild(input);
-    inputField.reposition();
-    expect(inputField.mirror.style.left).toEqual("30px");
-    expect(inputField.mirror.style.top.match(/^(\d+)px$/)[1]).toBeGreaterThan(20);
-  });
-
-/*
-  it('should be correctly triggerable', function () {
-    // https://developer.mozilla.org/samples/domref/dispatchEvent.html
-    var hint = KorAP.Hint.create({ "inputField" : input });
-    emitKeyboardEvent(hint.inputField.element, "keypress", 20);
-  });
-*/
-
-});
-
-
-
-/*
-describe('KorAP.Hint', function () {
-  KorAP.hintArray = {
-    "corenlp/" : [
-      ["Named Entity", "ne=" , "Combined"],
-      ["Named Entity", "ne_dewac_175m_600=" , "ne_dewac_175m_600"],
-      ["Named Entity", "ne_hgc_175m_600=",    "ne_hgc_175m_600"]
-    ]
-  };
-
-  it('should be initializable', function () {
-    // Supports: context, searchField
-    var hint = KorAP.Hint.create();
-  });
-});
-
-
-describe('KorAP.ContextAnalyzer', function () {
-
-  it('should be initializable', function () {
-    var analyzer = KorAP.ContextAnalyzer.create(")");
-    expect(analyzer).toBe(undefined);
-
-    analyzer = KorAP.ContextAnalyzer.create(".+?");
-    expect(analyzer).not.toBe(undefined);
-
-  });
-
-  it('should check correctly', function () {
-    analyzer = KorAP.ContextAnalyzer.create(KorAP.context);
-    expect(analyzer.test("cnx/]cnx/c=")).toEqual("cnx/c=");
-    expect(analyzer.test("cnx/c=")).toEqual("cnx/c=");
-    expect(analyzer.test("cnx/c=np mate/m=mood:")).toEqual("mate/m=mood:");
-    expect(analyzer.test("impcnx/")).toEqual("impcnx/");
-    expect(analyzer.test("cnx/c=npcnx/")).toEqual("npcnx/");
-    expect(analyzer.test("mate/m=degree:pos corenlp/ne_dewac_175m_600="))
-      .toEqual("corenlp/ne_dewac_175m_600=");
-  });
-});
-
-describe('KorAP.InputField', function () {
-  var input;
-
-  beforeAll(function () {
-    input = document.createElement("input");
-    input.setAttribute("type", "text");
-    input.setAttribute("value", "abcdefghijklmno");
-    input.style.position = 'absolute';
-    input.style.top  = "20px";
-    input.style.left = "30px";
-    input.focus();
-    input.selectionStart = 5;
-  });
-
-  afterAll(function () {
-    document.getElementsByTagName("body")[0].removeChild(input);
-    document.getElementsByTagName("body")[0].removeChild(
-      document.getElementById("searchMirror")
-    );
-  });
-
-  it('should be initializable', function () {
-    // Supports: context, searchField
-    var inputField = KorAP.InputField.create(input);
-    expect(inputField._element).not.toBe(undefined);
-  });
-
-  it('should have text', function () {
-    var inputField = KorAP.InputField.create(input);
-
-    expect(inputField.value).toEqual("abcdefghijklmno");
-    expect(inputField.element.selectionStart).toEqual(5);
-    expect(inputField.split()[0]).toEqual("abcde");
-    expect(inputField.split()[1]).toEqual("fghijklmno");
-
-    inputField.insert("xyz");
-    expect(inputField.split()[0]).toEqual("abcdexyz");
-    expect(inputField.split()[1]).toEqual("fghijklmno");
-
-  });
-
-  it('should be correctly positioned', function () {
-    var inputField = KorAP.InputField.create(input);
-    document.getElementsByTagName("body")[0].appendChild(input);
-    inputField.reposition();
-    expect(inputField.mirror.style.left).toEqual("30px");
-    expect(inputField.mirror.style.top.match(/^(\d+)px$/)[1]).toBeGreaterThan(20);
-  });
-});
-
-
-
-*/
diff --git a/public/js/spec/matchSpec.js b/public/js/spec/matchSpec.js
index dc54dc6..0e638c4 100644
--- a/public/js/spec/matchSpec.js
+++ b/public/js/spec/matchSpec.js
@@ -329,6 +329,7 @@
     expect(matchElement.children[0].children[1]).toBe(undefined);
 
     var info = KorAP.Match.create(matchElement).info();
+    info.toggle();
 
     // Match
     expect(matchElement.children[0].tagName).toEqual('DIV');
@@ -371,6 +372,7 @@
     expect(matchElement.tagName).toEqual('LI');
 
     var info = KorAP.Match.create(matchElement).info();
+    info.toggle();
 
     // Match
     expect(matchElement.children[0].tagName).toEqual('DIV');
diff --git a/public/js/src/hint.js b/public/js/src/hint.js
index b5c2043..8011bee 100644
--- a/public/js/src/hint.js
+++ b/public/js/src/hint.js
@@ -1,64 +1,21 @@
 /**
- * Context aware drop down menu
- * for annotation related query hints.
+ * Hint menu for Kalamar.
  *
  * @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
+// requires menu.js
 
-// The last entry types (foundry, foundry/layer) is remembered and chosen by default
-
-// Show the context at the top as breadcrumbs
-// Highlight the context in the query (probably)
-// Support backspace for removing the last prefix
-
-/*
-Alternative: Use right arrow for temporary context switch and arrow back
-for temporary context removal
-*/
-
-/**
- * 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 = 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
    */
@@ -74,14 +31,12 @@
   // Initialize hint array
   KorAP.hintArray = KorAP.hintArray || {};
 
-
-  KorAP.updateKeyDown = function (event) {
-  };
-
+  // Input field for queries
   KorAP.InputField = {
     create : function (element) {
       return Object.create(KorAP.InputField)._init(element);
     },
+
     _init : function (element) {
       this._element = element;
 
@@ -90,6 +45,7 @@
 	this._mirror = document.createElement("div");
 	this._mirror.setAttribute("id", "searchMirror");
 	this._mirror.appendChild(document.createElement("span"));
+	this._container = this._mirror.appendChild(document.createElement("div"));
 	this._mirror.style.height = "1px";
 	document.getElementsByTagName("body")[0].appendChild(this._mirror);
       };
@@ -99,39 +55,47 @@
       window.resize = function () {
 	that.reposition();
       };
-/*
-      // Add event listener for key down
-      element.addEventListener(
-	"keydown",
-	function (e) {
-//	  KorAP.updateKeyDown(e).bind(that)
-	},
-	false
-      );
-*/
+
+      that.reposition();
+
       return this;
     },
-    get mirror () {
+
+    rightPos : function () {
+      var box = this._mirror.getBoundingClientRect();
+      return box.right - box.left;
+    },
+
+    mirror : function () {
       return this._mirror;
     },
-    get element () {
+
+    container : function () {
+      return this._container;
+    },
+
+    element : function () {
       return this._element;
     },
-    get value () {
+
+    value : function () {
       return this._element.value;
     },
+
     update : function () {
       this._mirror.firstChild.textContent = this.split()[0];
     },
+
     insert : function (text) {
       var splittedText = this.split();
-      var s = this.element;
+      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
+
+    // Return two substrings, splitted at current cursor position
     split : function () {
       var s = this._element;
       var value = s.value;
@@ -141,13 +105,16 @@
 	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);
+
+      // Reset position
       var mirrorStyle = this._mirror.style;
       mirrorStyle.left = inputClientRect.left + "px";
-      mirrorStyle.top = inputClientRect.bottom + "px";
+      mirrorStyle.top  = inputClientRect.bottom + "px";
 
       // These may be relevant in case of media depending css
       mirrorStyle.paddingLeft     = inputStyle.getPropertyValue("padding-left");
@@ -157,182 +124,14 @@
       mirrorStyle.fontSize        = inputStyle.getPropertyValue("font-size");
       mirrorStyle.fontFamily      = inputStyle.getPropertyValue("font-family");
     },
-    get context () {
+    context : function () {
       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
+   * Regex object for checking the context of the hint
    */
   KorAP.ContextAnalyzer = {
     create : function (regex) {
@@ -357,498 +156,295 @@
 
 
   /**
-   * 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).
+   * Hint menu item based on MenuItem
    */
-  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);
+  KorAP.HintMenuItem = {
+    create : function (params) {
+      return Object.create(KorAP.MenuItem)
+	.upgradeTo(KorAP.HintMenuItem)
+	._init(params);
     },
-
-    /*
-     * 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]);
+    content : function (content) {
+      if (arguments.length === 1) {
+	this._content = content;
       };
-      newItem.active(true);
+      return this._content;
     },
-
-    /*
-     * 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
-	);
+    _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();
       };
 
-      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 () {
-
-console.log("..." + this._items.length);
-
-      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;
     },
+    onclick : function () {
+      var m = this.menu();
+      var h = m.hint();
+      m.hide();
 
-    _showItems : function (offset) {
-      this.delete();
+      h.inputField().insert(this._action);
+      h.active = false;
 
-      // 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);
+      h.show(true);
     },
-
-    /**
-     * Get the name of the item
-     */
-    get name () {
+    name : function () {
       return this._name;
     },
-
-    /**
-     * Get the action string
-     */
-    get action () {
+    action : function () {
       return this._action;
     },
-
-    /**
-     * Get the description of the item
-     */
-    get desc () {
+    desc : function () {
       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 () {
+    element : function () {
       // already defined
       if (this._element !== undefined)
 	return this._element;
 
       // Create list item
       var li = document.createElement("li");
-      li.setAttribute("data-action", this._action);
+
+      if (this.onclick !== undefined) {
+	li["onclick"] = this.onclick.bind(this);
+      };
 
       // Create title
-      var name =  document.createElement("strong");
+      var name =  document.createElement("span");
       name.appendChild(document.createTextNode(this._name));
-
+      
       li.appendChild(name);
 
       // Create description
       if (this._desc !== undefined) {
 	var desc = document.createElement("span");
+	desc.classList.add('desc');
 	desc.appendChild(document.createTextNode(this._desc));
 	li.appendChild(desc);
       };
       return this._element = li;
+    }
+  };
+
+  KorAP.HintMenuPrefix = {
+    create : function (params) {
+      return Object.create(KorAP.MenuPrefix).upgradeTo(KorAP.HintMenuPrefix)._init(params);
     },
+    onclick : function () {
+      var m = this.menu();
+      var h = m.hint();
+      m.hide();
 
-    /**
-     * 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);
-    },
+      h.inputField().insert(this.value());
+      h.active = false;
+    }
+  };
 
-    /**
-     * 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;
-    },
+  KorAP.HintMenu = {
+    create : function (hint, context, params) {
+      var obj = Object.create(KorAP.Menu)
+	.upgradeTo(KorAP.HintMenu)
+	._init(KorAP.HintMenuItem, KorAP.HintMenuPrefix, params);
+      obj._context = context;
+      obj._element.classList.add('hint');
+      obj._hint = hint;
 
-    // Initialize menu item
-    _init : function (params) {
-      if (params[0] === undefined || params[1] === undefined)
-	throw new Error("Missing parameters");
+      // This is only domspecific
+      obj.element().addEventListener('blur', function (e) {
+	this.menu.hide();
+      });
 
-      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();
+      // Focus on input field on hide
+      obj.onHide = function () {
+	var input = this._hint.inputField();
+	input.element().focus();
       };
+
+      return obj;
+    },
+    // Todo: Is this necessary?
+    context : function () {
+      return this._context;
+    },
+    hint : function () {
+      return this._hint;
+    }
+  };
+
+
+  /**
+   * KorAP.Hint.create({
+   *   inputField : node,
+   *   context : context regex
+   * });
+   */
+  KorAP.Hint = {
+
+    // Some variables
+    // _firstTry : true,
+    active : false,
+
+    create : function (param) {
+      return Object.create(KorAP.Hint)._init(param);
+    },
+
+    _init : function (param) {
+      param = param || {};
+
+      // Holds all menus per prefix context
+      this._menu = {};
+
+      // Get input field
+      this._inputField = KorAP.InputField.create(
+	param["inputField"] || document.getElementById("q-field")
+      );
+
+      var inputFieldElement = this._inputField.element();
+
+      var that = this;
+
+      // Add event listener for key pressed down
+      inputFieldElement.addEventListener(
+	"keypress", function (e) {
+	  var code = _codeFromEvent(e);
+	  if (code === 40) {
+	    that.show(false);
+	    e.halt();
+	  };
+	}, false
+      );
+
+      // Move infobox 
+      inputFieldElement.addEventListener(
+	"keyup", function (e) {
+	  var input = that._inputField;
+	  input.update();
+	  input.container().style.left = input.rightPos() + 'px';
+	}
+      );
+
+      // Set Analyzer for context
+      this._analyzer = KorAP.ContextAnalyzer.create(
+	param["context"] || KorAP.context
+      );
       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) {
+    inputField : function () {
+      return this._inputField;
+    },
 
-	// First element
-	elem.firstChild.nodeValue = pos > 0 ? text.substr(0, pos) : "";
+    /**
+     * A new update by keypress
+     */
+    /*
+updateKeyPress : function (e) {
+      if (!this._active)
+	return;
 
-	// Second element
-	var hl = document.createElement("em");
-	hl.appendChild(
-	  document.createTextNode(text.substr(pos, prefix.length))
+      var character = String.fromCharCode(_codeFromEvent(e));
+
+      e.halt(); // No event propagation
+
+      // Only relevant for key down
+      console.log("TODO: filter view");
+    },
+    */
+
+    // updateKeyDown : function (e) {},
+
+    /**
+     * Return hint menu and probably init based on an action
+     */
+    menu : function (action) {
+
+      if (this._menu[action] === undefined) {
+
+	// No matching hint menu
+	if (KorAP.hintArray[action] === undefined)
+	  return;
+
+	// Create matching hint menu
+	this._menu[action] = KorAP.HintMenu.create(
+	  this, action, KorAP.hintArray[action]
 	);
-	elem.appendChild(hl);
 
-	// Third element
-	elem.appendChild(
-	  document.createTextNode(text.substr(pos + prefix.length))
-	);
+      };
+
+      // Return matching hint menu
+      return this._menu[action];
+    },
+
+    /**
+     * Get the correct menu based on the context
+     */
+    contextMenu : function (ifContext) {
+      var context = this._inputField.context();
+      if (context === undefined || context.length == 0)
+	return ifContext ? undefined : this.menu("-");
+
+      context = this._analyzer.test(context);
+      if (context === undefined || context.length == 0)
+	return ifContext ? undefined : this.menu("-");
+
+      return this.menu(context);
+    },
+
+
+    /**
+     * Show the menu
+     */
+    show : function (ifContext) {
+
+      // Menu is already active
+      if (this.active)
+	return;
+
+      // Initialize the menus position
+      /*
+      if (this._firstTry) {
+	this._inputField.reposition();
+	this._firstTry = false;
+      };
+      */
+
+      // update
+
+      // Get the menu
+      var menu;
+      if (menu = this.contextMenu(ifContext)) {
+	this._inputField.container().appendChild(menu.element());
+	menu.show('');
+	menu.focus();
+// Update bounding box
+/*
+      }
+      else if (!ifContext) {
+	//	this.hide();
+      };
+*/
+      // Focus on input field
+      // this.inputField.element.focus();
       };
     }
   };
+
+
+  /**
+   * Return keycode based on event
+   */
+  function _codeFromEvent (e) {
+    if ((e.charCode) && (e.keyCode==0))
+      return e.charCode
+    return e.keyCode;
+  };
+
 }(this.KorAP));
diff --git a/public/js/src/match.js b/public/js/src/match.js
index f8fdd91..b974031 100644
--- a/public/js/src/match.js
+++ b/public/js/src/match.js
@@ -195,7 +195,7 @@
       // Add information, unless it already exists
       info.addEventListener('click', function (e) {
 	e.halt();
-	that.info();
+	that.info().toggle();
       });
 
       ul.appendChild(close);
@@ -204,7 +204,6 @@
       return true;
     },
 
-
     /**
      * Close info view
      */
@@ -219,7 +218,6 @@
     },
 
 
-
     /**
      * Get and open associated match info.
      */
@@ -235,14 +233,9 @@
 	return this._info;
 
       // Info is already activated
-      if (this._info._elemet !== undefined)
+      if (this._info._element !== undefined)
 	return this._info;
 
-      // Append element to match
-      this._element.children[0].appendChild(
-	this._info.element()
-      );
-
       return this._info;
     },
 
@@ -276,10 +269,10 @@
      */
     _init : function (match) {
       this._match = match;
+      this.opened = false;
       return this;
     },
 
-
     /**
      * Get match object
      */
@@ -287,6 +280,24 @@
       return this._match;
     },
 
+    toggle : function () {
+      if (this.opened == true) {
+	this._match.element().children[0].removeChild(
+	  this.element()
+	);
+	this.opened = false;
+      }
+      else {
+	// Append element to match
+	this._match.element().children[0].appendChild(
+	  this.element()
+	);
+	this.opened = true;
+      };
+
+      return this.opened;
+    },
+
 
     /**
      * Retrieve and parse snippet for table representation
diff --git a/public/js/src/menu.js b/public/js/src/menu.js
index a7271c5..3267b69 100644
--- a/public/js/src/menu.js
+++ b/public/js/src/menu.js
@@ -52,7 +52,7 @@
       for (var i = 0; i < this._items.length; i++) {
 	delete this._items[i]["_menu"];
       };
-      
+      delete this._prefix['_menu'];
     },
 
     focus : function () {
@@ -147,11 +147,13 @@
       else
 	this._prefix = KorAP.MenuPrefix.create();
 
+      this._prefix._menu = this;
+
       var e = document.createElement("ul");
       e.style.opacity = 0;
       e.style.outline = 0;
       e.setAttribute('tabindex', 0);
-      e.setAttribute('class', 'menu');
+      e.classList.add('menu');
       e.appendChild(this._prefix.element());
 
       // This has to be cleaned up later on
@@ -274,9 +276,13 @@
       this.active = false;
       this.delete();
       this._element.style.opacity = 0;
+      this.onHide();
       /* this._element.blur(); */
     },
 
+    // To be override
+    onHide : function () {},
+
     // Initialize the list
     _initList : function () {
 
@@ -676,7 +682,6 @@
       return this;
     },
 
-
     content : function (content) {
       if (arguments.length === 1)
 	this._content = document.createTextNode(content);
@@ -737,8 +742,9 @@
       var li = document.createElement("li");
 
       // Connect action
-      if (this.onclick !== undefined)
+      if (this["onclick"] !== undefined) {
 	li["onclick"] = this.onclick.bind(this);
+      };
 
       // Append template
       li.appendChild(this.content());
@@ -866,7 +872,8 @@
       this._element = document.createElement('span');
       this._element.classList.add('pref');
       // Connect action
-      if (this.onclick !== undefined)
+
+      if (this["onclick"] !== undefined)
 	this._element["onclick"] = this.onclick.bind(this);
 
       return this;
@@ -898,13 +905,16 @@
       else
 	cl.remove("active");
     },
+
     element : function () {
       return this._element;
     },
+
     isSet : function () {
       return this._string.length > 0 ?
 	true : false;
     },
+
     value : function (string) {
       if (arguments.length === 1) {
 	this._string = string;
@@ -912,11 +922,14 @@
       };
       return this._string;
     },
+
     add : function (string) {
       this._string += string;
       this._update();
     },
-    onclick : function (e) {},
+
+    onclick : function () {},
+
     backspace : function () {
       if (this._string.length > 1) {
 	this._string = this._string.substring(
@@ -928,6 +941,13 @@
       };
 
       this._update();
+    },
+
+    /**
+     * Return menu list.
+     */
+    menu : function () {
+      return this._menu;
     }
   };
 
diff --git a/public/js/src/util.js b/public/js/src/util.js
index 0f0f114..3adf5a0 100644
--- a/public/js/src/util.js
+++ b/public/js/src/util.js
@@ -31,35 +31,36 @@
 (function (KorAP) {
   "use strict";
 
+
+  /**
+   * Initialize user interface elements
+   */
   KorAP.init = function () {
 
     /**
      * Add actions to match entries
      */
-    var inactiveLi = document.querySelectorAll('#search > ol > li:not(.active)');
+    var inactiveLi = document.querySelectorAll(
+      '#search > ol > li:not(.active)'
+    );
     var i = 0;
     for (i = 0; i < inactiveLi.length; i++) {
-      inactiveLi[i].addEventListener('click', function () {
-
-	if (this._match !== undefined) {
+      inactiveLi[i].addEventListener('click', function (e) {
+	if (this._match !== undefined)
 	  this._match.open();
-	  console.log('already open');
-	}
-	else {
+	else
 	  KorAP.Match.create(this).open();
-	  console.log('newly open');
-	}
-
-	
+	e.halt();
       });
     };
 
+
     /**
      * Toggle the alignment (left <=> right)
      */
     if (i > 0) {
       var br = document.getElementById('button-right');
-      if (br !== undefined) {
+      if (br !== null) {
 	var toggle = document.createElement('a');
 	toggle.setAttribute('title', 'toggle Alignment');
 	// Todo: Reuse old alignment from cookie!
@@ -78,57 +79,11 @@
 	br.appendChild(toggle);
       };
     };
+
+    /**
+     * Init hint helper
+     */
+    KorAP.Hint.create();
   };
 
-  /*
-  function _openMatch (e) {
-    e.halt();
-    this.classList.add("active");
-    var matchElement = this;
-
-    // Todo: Add object to element
-    var ul = document.createElement('ul');
-    ul.classList.add('action', 'right');
-    matchElement.appendChild(ul);
-
-    // Todo:: Localize!
-    var close = document.createElement('li');
-    close.appendChild(document.createElement('span'))
-      .appendChild(document.createTextNode('Close'));
-    close.classList.add('close');
-    close.setAttribute('title', 'Close');
-
-    close.addEventListener('click', function (ie) {
-      ie.halt();
-      var match = matchElement['_match'];
-      match.destroy();
-      matchElement.classList.remove('active');
-      matchElement.removeChild(ul);
-    });
-
-    // Todo:: Localize!
-    var info = document.createElement('li');
-    info.appendChild(document.createElement('span'))
-      .appendChild(document.createTextNode('Info'));
-    info.classList.add('info');
-    info.setAttribute('title', 'Information');
-
-    // Add information, unless it already exists
-    info.addEventListener('click', function (ie) {
-      ie.halt();
-      KorAP.Match.create(matchElement).addInfo();
-    });
-
-    ul.appendChild(close);
-    ul.appendChild(info);
-  };
-*/
-
-  /**
-  function _closeMatch (e) {
-    e.halt();
-    this.parentNode.parentNode.classList.remove("active");
-  };
-  */
-
 }(this.KorAP));