Merge "Show tooltips for annotations in table view"
diff --git a/.gitignore b/.gitignore
index 87ea481..2dbe719 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
 public
 kalamar.*.conf
 kalamar.conf.json
+kalamar.conf.js
 script/hypnotoad.pid
 .sass-cache
 dev/css
diff --git a/Gruntfile.js b/Gruntfile.js
index 830a0eb..b556928 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -15,42 +15,29 @@
  */
 
 module.exports = function(grunt) {
-
   var config;
-
-  try {
-    config = grunt.file.readJSON('kalamar.conf.json');
-  }
-  catch(err) {
-    console.log("Error: " + err);
-    config = {};
-  };
-
-  if (config["include"] === undefined) {
-    config["include"] = [
-      'hint/foundries/base',
-      'hint/foundries/dereko'
-    ];
+  var includeFile = 'default';
+  if (grunt.file.exists('kalamar.conf.js')) {
+    includeFile = 'root/kalamar.conf';
   };
 
   // Generate requireJS files for l10n
   var reqTasks = [];
   for (var i in {'en' : 0, 'de' : 1}) {
 
-    var includeFiles = config["include"].slice();
-    includeFiles.push('app/' + i);
-
     reqTasks.push({
       options: {
+
         // optimize: "uglify",
         baseUrl: 'dev/js/src',
         paths : {
-	        'lib': '../lib'
+	        'lib': '../lib',
+          'root' : '../../..'
         },
-        wrap:true,
+        wrap: true,
         // dir : 'public/js',
         name: 'lib/almond',
-        include : includeFiles,
+        include : [includeFile, "app/" + i],
         out: 'public/js/kalamar-<%= pkg.version %>-' + i + '.js'
       }
     })
diff --git a/dev/demo/alldemo.js b/dev/demo/alldemo.js
index 226ee28..e2ce107 100644
--- a/dev/demo/alldemo.js
+++ b/dev/demo/alldemo.js
@@ -604,7 +604,7 @@
 
 KorAP.currentQuery = queryExample;
 
-require(['app/en', 'init'], function (lang, init) {
+require(['app/en', 'init', 'hint/foundries/cnx'], function (lang) {
   KorAP.hintArray = hintArray;
 
   // Set current virtual collection
diff --git a/dev/demo/match-table.html b/dev/demo/match-table.html
new file mode 100644
index 0000000..f687f68
--- /dev/null
+++ b/dev/demo/match-table.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Match table demo</title>
+    <meta charset="utf-8" />
+    <script data-main="match-tabledemo.js" src="../js/lib/require.js" async="async"></script>
+    <link type="text/css" rel="stylesheet" href="../css/kalamar.css" />
+  </head>
+  <body>
+    <main>
+      <div id="search">
+        <ol class="align-left">
+	        <li class="active">
+	          <div class="meta">xx</div>
+            <div class="match-main">
+              <div class="match-wrap">
+	              <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><mark><mark class="class-2 level-1">Dies </mark><mark class="class-1 level-0"><mark class="class-2 level-1"><mark class="class-3 level-2">ist</mark> ein</mark> Test</mark></mark><span class="context-right"> übergeben, aber im Gegensatz zu einem Referenzparamter dabei unverändert bleiben.</span></div>
+              </div>
+	          </div>
+	          <p class="ref"><strong>Wertparameter</strong> by Hubi,Zwobot,4; published on 2005-03-28 as WWW.03313 (WPD)</p>
+            <div class="matchinfo">
+              <div class="matchtable" id="matchtable"></div>
+            </div>
+	        </li>
+        </ol>
+      </div>
+    </main>
+  </body>
+</html>
diff --git a/dev/demo/match-tabledemo.js b/dev/demo/match-tabledemo.js
new file mode 100644
index 0000000..fe422ef
--- /dev/null
+++ b/dev/demo/match-tabledemo.js
@@ -0,0 +1,62 @@
+requirejs.config({
+  baseUrl: '../js/src',
+  paths : {
+    'lib': '../lib'
+  }
+});
+
+window.KorAP = window.KorAP || {};
+
+require(['match/table',
+         'lib/domReady',
+         'hint/foundries/opennlp',
+         'hint/foundries/cnx',
+         'hint/foundries/mate'
+        ], function (matchTableClass, domReady) {
+
+  var snippet = "<span title=\"cnx/l:meist\">" +
+  "  <span title=\"cnx/p:ADV\">" +
+  "    <span title=\"cnx/syn:@PREMOD\">" +
+  "      <span title=\"mate/l:meist\">" +
+  "        <span title=\"mate/p:ADV\">" +
+  "          <span title=\"opennlp/p:ADV\">meist</span>" +
+  "        </span>" +
+  "      </span>" +
+  "    </span>" +
+  "  </span>" +
+  "</span>" +
+  "<span title=\"cnx/l:deutlich\">" +
+  "  <span title=\"cnx/p:A\">" +
+  "    <span title=\"cnx/syn:@PREMOD\">" +
+  "      <span title=\"mate/l:deutlich\">" +
+  "        <span title=\"mate/m:degree:pos\">" +
+  "          <span title=\"mate/p:ADJD\">" +
+  "            <span title=\"opennlp/p:ADJD\">deutlich</span>" +
+  "          </span>" +
+  "        </span>" +
+  "      </span>" +
+  "    </span>" +
+  "  </span>" +
+  "</span>" +
+  "<span title=\"cnx/l:fähig\">" +
+  "  <span title=\"cnx/l:leistung\">" +
+  "    <span title=\"cnx/p:A\">" +
+  "      <span title=\"cnx/syn:@NH\">" +
+  "        <span title=\"mate/l:leistungsfähig\">" +
+  "          <span title=\"mate/m:degree:comp\">" +
+  "            <span title=\"mate/p:ADJD\">" +
+  "              <span title=\"opennlp/p:ADJD\">leistungsfähiger</span>" +
+  "            </span>" +
+  "          </span>" +
+  "        </span>" +
+  "      </span>" +
+  "    </span>" +
+  "  </span>" +
+  "</span>";
+
+  
+  domReady(function () {
+    var mt = matchTableClass.create(snippet);
+    document.getElementById('matchtable').appendChild(mt.element());
+  });
+});
diff --git a/dev/js/src/default.js b/dev/js/src/default.js
new file mode 100644
index 0000000..905751c
--- /dev/null
+++ b/dev/js/src/default.js
@@ -0,0 +1,4 @@
+require([
+  "hint/foundries/base",
+  "hint/foundries/dereko"
+]);
diff --git a/dev/js/src/hint.js b/dev/js/src/hint.js
index 2ebc395..19c360f 100644
--- a/dev/js/src/hint.js
+++ b/dev/js/src/hint.js
@@ -42,7 +42,7 @@
     ")?" +
     ")?" +
     ")$";
-  KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
+  // KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
 
   /**
    * Return keycode based on event
@@ -78,6 +78,12 @@
       this._alert  = alertClass.create();
       this._active = null;
 
+      // No annotation helper available
+      if (!KorAP.annotationHelper) {
+        console.log("No annotationhelper defined");
+        return;
+      };
+
       // Get input field
       var qfield = param["inputField"] || document.getElementById("q-field");
       if (!qfield)
diff --git a/dev/js/src/hint/foundries.js b/dev/js/src/hint/foundries.js
new file mode 100644
index 0000000..6f2ac02
--- /dev/null
+++ b/dev/js/src/hint/foundries.js
@@ -0,0 +1,3 @@
+define(function () {
+  return (KorAP.annotationHelper = KorAP.annotationHelper || { '-' : [] });
+});
diff --git a/dev/js/src/hint/foundries/base.js b/dev/js/src/hint/foundries/base.js
index 0bb26fc..29dc414 100644
--- a/dev/js/src/hint/foundries/base.js
+++ b/dev/js/src/hint/foundries/base.js
@@ -1,11 +1,11 @@
-var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["Base Annotation", "base/s=", "Structure"]
+  );
 
-ah["-"].push(
-  ["Base Annotation", "base/s=", "Structure"]
-);
-
-ah["base/s="] = [
-  ["s", "s", "Sentence"],
-  ["p", "p", "Paragraph"],
-  ["t", "t", "Text"]
-];
+  ah["base/s="] = [
+    ["s", "s", "Sentence"],
+    ["p", "p", "Paragraph"],
+    ["t", "t", "Text"]
+  ];
+});
diff --git a/dev/js/src/hint/foundries/cnx.js b/dev/js/src/hint/foundries/cnx.js
index 0c6f8cb..608d4e6 100644
--- a/dev/js/src/hint/foundries/cnx.js
+++ b/dev/js/src/hint/foundries/cnx.js
@@ -1,63 +1,63 @@
-var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["Connexor", "cnx/", "Constituency, Lemma, Morphology, Part-of-Speech, Syntax"]
+  );
 
-ah["-"].push(
-  ["Connexor", "cnx/", "Constituency, Lemma, Morphology, Part-of-Speech, Syntax"]
-);
+  ah["cnx/"] = [
+    ["Constituency", "c="],
+    ["Lemma", "l="],
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="],
+    ["Syntax", "syn="]
+  ];
 
-ah["cnx/"] = [
-  ["Constituency", "c="],
-  ["Lemma", "l="],
-  ["Morphology", "m="],
-  ["Part-of-Speech", "p="],
-  ["Syntax", "syn="]
-];
+  ah["cnx/c="] = [
+    ["np", "np ", "Nominal Phrase"]
+  ];
 
-ah["cnx/c="] = [
-  ["np", "np ", "Nominal Phrase"]
-];
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/morph.html
+  ah["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
-ah["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
+  ah["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/morph.html
-ah["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
-ah["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"]
-];
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/syntax.html
+  ah["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"]
+  ];
+});
diff --git a/dev/js/src/hint/foundries/corenlp.js b/dev/js/src/hint/foundries/corenlp.js
index b591c62..b3c931c 100644
--- a/dev/js/src/hint/foundries/corenlp.js
+++ b/dev/js/src/hint/foundries/corenlp.js
@@ -1,6 +1,4 @@
-require(["hint/foundries/stts"], function (sttsArray) {
-  var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
-
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
   var namedEntities = [
     ["I-LOC",  "I-LOC ",  "Location"],
     ["I-MISC", "I-MISC ", "Miscellaneous"],
diff --git a/dev/js/src/hint/foundries/dereko.js b/dev/js/src/hint/foundries/dereko.js
index c8afe08..939fade 100644
--- a/dev/js/src/hint/foundries/dereko.js
+++ b/dev/js/src/hint/foundries/dereko.js
@@ -1,5 +1,5 @@
-var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
-
-ah["-"].push(
-  ["DeReKo", "dereko/s=", "Structure"]
-);
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["DeReKo", "dereko/s=", "Structure"]
+  );
+});
diff --git a/dev/js/src/hint/foundries/drukola.js b/dev/js/src/hint/foundries/drukola.js
index 2fec26d..1850fc3 100644
--- a/dev/js/src/hint/foundries/drukola.js
+++ b/dev/js/src/hint/foundries/drukola.js
@@ -1,105 +1,105 @@
-var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["DRuKoLa", "drukola/", "Lemma, Morphology, Part-of-Speech"]
+  );
 
-ah["-"].push(
-  ["DRuKoLa", "drukola/", "Lemma, Morphology, Part-of-Speech"]
-);
+  ah["drukola/"] = [
+    ["Lemma", "l="],
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="]      
+  ];
 
-ah["drukola/"] = [
-  ["Lemma", "l="],
-  ["Morphology", "m="],
-  ["Part-of-Speech", "p="]      
-];
+  ah["drukola/m="] =  [
+    ["CTAG", "ctag:"]
+  ];
 
-ah["drukola/m="] =  [
-  ["CTAG", "ctag:"]
-];
+  ah["drukola/m=ctag:"] = [
+    ["A","A ","Adjective"],
+    ["Y","Y ","Abbreviation"],
+    ["AN","AN ","Adjective, Indefinite"],
+    ["APRY","APRY ","Adjective, Plural, Direct, Definite"],
+    ["APN","APN ","Adjective, Plural, Indefinite"],
+    ["APOY","APOY ","Adjective, Plural, Oblique, Definite"],
+    ["APON","APON ","Adjective, Plural, Oblique, Indefinite"],
+    ["ASRY","ASRY ","Adjective, Singular, Direct, Definite"],
+    ["ASN","ASN ","Adjective, Singular, Indefinite"],
+    ["ASOY","ASOY ","Adjective, Singular, Oblique, Definite"],
+    ["ASON","ASON ","Adjective, Singular, Oblique, Indefinite"],
+    ["ASVY","ASVY ","Adjective, Singular, Vocative, Definite"],
+    ["ASVN","ASVN ","Adjective, Singular, Vocative, Indefinite"],
+    ["R","R ","Adverb"],
+    ["RC","RC ","Adverb, Portmanteau"],
+    ["TS","TS ","Article, Definite or Possessive, Singular"],
+    ["TP","TP ","Article, Indefinite or Possessive, Plural"],
+    ["TPR","TPR ","Article, non-Possessive, Plural, Direct"],
+    ["TPO","TPO ","Article, non-Possessive, Plural, Oblique"],
+    ["TSR","TSR ","Article, non-Possessive, Singular, Direct"],
+    ["TSO","TSO ","Article, non-Possessive, Singular, Oblique"],
+    ["NPRY","NPRY ","Common Noun, Plural, Direct, Definite"],
+    ["NPN","NPN ","Common Noun, Plural, Indefinite"],
+    ["NPOY","NPOY ","Common Noun, Plural, Oblique, Definite"],
+    ["NPVY","NPVY ","Common Noun, Plural, Vocative, Definite"],
+    ["NN","NN ","Common Noun, singular"],
+    ["NSY","NSY ","Common Noun, Singular, Definite"],
+    ["NSRY","NSRY ","Common Noun, Singular, Direct, Definite"],
+    ["NSRN","NSRN ","Common Noun, Singular, Direct, Indefinite"],
+    ["NSN","NSN ","Common Noun, Singular, Indefinite"],
+    ["NSOY","NSOY ","Common Noun, Singular, Oblique, Definite"],
+    ["NSON","NSON ","Common Noun, Singular, Oblique, Indefinite"],
+    ["NSVY","NSVY ","Common Noun, Singular, Vocative, Definite"],
+    ["NSVN","NSVN ","Common Noun, Singular, Vocative, Indefinite"],
+    ["CR","CR ","Conjunctio, portmanteau"],
+    ["C","C ","Conjunction"],
+    ["QF","QF ","Future Particle"],
+    ["QN","QN ","Infinitival Particle"],
+    ["I","I ","Interjection"],
+    ["QZ","QZ ","Negative Particle"],
+    ["M","M ","Numeral"],
+    ["PP","PP ","Personal Pronoun"],
+    ["PPP","PPP ","Personal Pronoun, Plural"],
+    ["PPPA","PPPA ","Personal Pronoun, Plural, Acc."],
+    ["PPPD","PPPD ","Personal Pronoun, Plural, Dative"],
+    ["PPPR","PPPR ","Personal Pronoun, Plural, Direct"],
+    ["PPPO","PPPO ","Personal Pronoun, Plural, Oblique"],
+    ["PPS","PPS ","Personal Pronoun, Singular"],
+    ["PPSA","PPSA ","Personal Pronoun, Singular, Accusative"],
+    ["PPSD","PPSD ","Personal Pronoun, Singular, Dative"],
+    ["PPSR","PPSR ","Personal Pronoun, Singular, Direct"],
+    ["PPSN","PPSN ","Personal Pronoun, Singular, Nominative"],
+    ["PPSO","PPSO ","Personal Pronoun, Singular, Oblique"],
+    ["S","S ","Preposition"],
+    ["DMPR","DMPR ","Pronoun or Determiner, Demonstrative, Plural, Direct"],
+    ["DMPO","DMPO ","Pronoun or Determiner, Demonstrative, Plural, Oblique"],
+    ["DMSR","DMSR ","Pronoun or Determiner, Demonstrative, Singular, Direct"],
+    ["DMSO","DMSO ","Pronoun or Determiner, Demonstrative, Singular, Oblique"],
+    ["PS","PS ","Pronoun or Determiner, Poss or Emph"],
+    ["PSS","PSS ","Pronoun or Determiner, Poss or Emph, Singular"],
+    ["RELR","RELR ","Pronoun or Determiner, Relative, Direct"],
+    ["RELO","RELO ","Pronoun or Determiner, Relative, Oblique"],
+    ["NP","NP ","Proper Noun"],
+    ["PI","PI ","Quantifier Pronoun or Determiner"],
+    ["PXA","PXA ","Reflexive Pronoun, Accusative"],
+    ["PXD","PXD ","Reflexive Pronoun, Dative"],
+    ["X","X ","Residual"],
+    ["QS","QS ","Subjunctive Particle"],
+    ["VA","VA ","Verb, Auxiliary"],
+    ["VA1","VA1 ","Verb, Auxiliary, 1st person"],
+    ["VA2P","VA2P ","Verb, Auxiliary, 2nd person, Plural"],
+    ["VA2S","VA2S ","Verb, Auxiliary, 2nd person, Singular"],
+    ["VA3","VA3 ","Verb, Auxiliary, 3rd person"],
+    ["VA3P","VA3P ","Verb, Auxiliary, 3rd person, Plural"],
+    ["VA3S","VA3S ","Verb, Auxiliary, 3rd person, Singular"],
+    ["VA1P","VA1P ","Verb, Auxiliary,1st person, Plural"],
+    ["VA1S","VA1S ","Verb, Auxiliary,1st person, Singular"],
+    ["VG","VG ","Verb, Gerund"],
+    ["VN","VN ","Verb, Infinitive"],
+    ["V1","V1 ","Verb, Main, 1st person"],
+    ["V2","V2 ","Verb, Main, 2nd person"],
+    ["V3","V3 ","Verb, Main, 3rd person"],
+    ["VPPF","VPPF ","Verb, Participle, Plural, Feminine"],
+    ["VPPM","VPPM ","Verb, Participle, Plural, Masculine"],
+    ["VPSF","VPSF ","Verb, Participle, Singular, Feminine"],
+    ["VPSM","VPSM ","Verb, Participle, Singular, Masculine"]
+  ];
 
-ah["drukola/m=ctag:"] = [
-  ["A","A ","Adjective"],
-  ["Y","Y ","Abbreviation"],
-  ["AN","AN ","Adjective, Indefinite"],
-  ["APRY","APRY ","Adjective, Plural, Direct, Definite"],
-  ["APN","APN ","Adjective, Plural, Indefinite"],
-  ["APOY","APOY ","Adjective, Plural, Oblique, Definite"],
-  ["APON","APON ","Adjective, Plural, Oblique, Indefinite"],
-  ["ASRY","ASRY ","Adjective, Singular, Direct, Definite"],
-  ["ASN","ASN ","Adjective, Singular, Indefinite"],
-  ["ASOY","ASOY ","Adjective, Singular, Oblique, Definite"],
-  ["ASON","ASON ","Adjective, Singular, Oblique, Indefinite"],
-  ["ASVY","ASVY ","Adjective, Singular, Vocative, Definite"],
-  ["ASVN","ASVN ","Adjective, Singular, Vocative, Indefinite"],
-  ["R","R ","Adverb"],
-  ["RC","RC ","Adverb, Portmanteau"],
-  ["TS","TS ","Article, Definite or Possessive, Singular"],
-  ["TP","TP ","Article, Indefinite or Possessive, Plural"],
-  ["TPR","TPR ","Article, non-Possessive, Plural, Direct"],
-  ["TPO","TPO ","Article, non-Possessive, Plural, Oblique"],
-  ["TSR","TSR ","Article, non-Possessive, Singular, Direct"],
-  ["TSO","TSO ","Article, non-Possessive, Singular, Oblique"],
-  ["NPRY","NPRY ","Common Noun, Plural, Direct, Definite"],
-  ["NPN","NPN ","Common Noun, Plural, Indefinite"],
-  ["NPOY","NPOY ","Common Noun, Plural, Oblique, Definite"],
-  ["NPVY","NPVY ","Common Noun, Plural, Vocative, Definite"],
-  ["NN","NN ","Common Noun, singular"],
-  ["NSY","NSY ","Common Noun, Singular, Definite"],
-  ["NSRY","NSRY ","Common Noun, Singular, Direct, Definite"],
-  ["NSRN","NSRN ","Common Noun, Singular, Direct, Indefinite"],
-  ["NSN","NSN ","Common Noun, Singular, Indefinite"],
-  ["NSOY","NSOY ","Common Noun, Singular, Oblique, Definite"],
-  ["NSON","NSON ","Common Noun, Singular, Oblique, Indefinite"],
-  ["NSVY","NSVY ","Common Noun, Singular, Vocative, Definite"],
-  ["NSVN","NSVN ","Common Noun, Singular, Vocative, Indefinite"],
-  ["CR","CR ","Conjunctio, portmanteau"],
-  ["C","C ","Conjunction"],
-  ["QF","QF ","Future Particle"],
-  ["QN","QN ","Infinitival Particle"],
-  ["I","I ","Interjection"],
-  ["QZ","QZ ","Negative Particle"],
-  ["M","M ","Numeral"],
-  ["PP","PP ","Personal Pronoun"],
-  ["PPP","PPP ","Personal Pronoun, Plural"],
-  ["PPPA","PPPA ","Personal Pronoun, Plural, Acc."],
-  ["PPPD","PPPD ","Personal Pronoun, Plural, Dative"],
-  ["PPPR","PPPR ","Personal Pronoun, Plural, Direct"],
-  ["PPPO","PPPO ","Personal Pronoun, Plural, Oblique"],
-  ["PPS","PPS ","Personal Pronoun, Singular"],
-  ["PPSA","PPSA ","Personal Pronoun, Singular, Accusative"],
-  ["PPSD","PPSD ","Personal Pronoun, Singular, Dative"],
-  ["PPSR","PPSR ","Personal Pronoun, Singular, Direct"],
-  ["PPSN","PPSN ","Personal Pronoun, Singular, Nominative"],
-  ["PPSO","PPSO ","Personal Pronoun, Singular, Oblique"],
-  ["S","S ","Preposition"],
-  ["DMPR","DMPR ","Pronoun or Determiner, Demonstrative, Plural, Direct"],
-  ["DMPO","DMPO ","Pronoun or Determiner, Demonstrative, Plural, Oblique"],
-  ["DMSR","DMSR ","Pronoun or Determiner, Demonstrative, Singular, Direct"],
-  ["DMSO","DMSO ","Pronoun or Determiner, Demonstrative, Singular, Oblique"],
-  ["PS","PS ","Pronoun or Determiner, Poss or Emph"],
-  ["PSS","PSS ","Pronoun or Determiner, Poss or Emph, Singular"],
-  ["RELR","RELR ","Pronoun or Determiner, Relative, Direct"],
-  ["RELO","RELO ","Pronoun or Determiner, Relative, Oblique"],
-  ["NP","NP ","Proper Noun"],
-  ["PI","PI ","Quantifier Pronoun or Determiner"],
-  ["PXA","PXA ","Reflexive Pronoun, Accusative"],
-  ["PXD","PXD ","Reflexive Pronoun, Dative"],
-  ["X","X ","Residual"],
-  ["QS","QS ","Subjunctive Particle"],
-  ["VA","VA ","Verb, Auxiliary"],
-  ["VA1","VA1 ","Verb, Auxiliary, 1st person"],
-  ["VA2P","VA2P ","Verb, Auxiliary, 2nd person, Plural"],
-  ["VA2S","VA2S ","Verb, Auxiliary, 2nd person, Singular"],
-  ["VA3","VA3 ","Verb, Auxiliary, 3rd person"],
-  ["VA3P","VA3P ","Verb, Auxiliary, 3rd person, Plural"],
-  ["VA3S","VA3S ","Verb, Auxiliary, 3rd person, Singular"],
-  ["VA1P","VA1P ","Verb, Auxiliary,1st person, Plural"],
-  ["VA1S","VA1S ","Verb, Auxiliary,1st person, Singular"],
-  ["VG","VG ","Verb, Gerund"],
-  ["VN","VN ","Verb, Infinitive"],
-  ["V1","V1 ","Verb, Main, 1st person"],
-  ["V2","V2 ","Verb, Main, 2nd person"],
-  ["V3","V3 ","Verb, Main, 3rd person"],
-  ["VPPF","VPPF ","Verb, Participle, Plural, Feminine"],
-  ["VPPM","VPPM ","Verb, Participle, Plural, Masculine"],
-  ["VPSF","VPSF ","Verb, Participle, Singular, Feminine"],
-  ["VPSM","VPSM ","Verb, Participle, Singular, Masculine"]
-];
-
+});
diff --git a/dev/js/src/hint/foundries/malt.js b/dev/js/src/hint/foundries/malt.js
index c81df9e..aa632b6 100644
--- a/dev/js/src/hint/foundries/malt.js
+++ b/dev/js/src/hint/foundries/malt.js
@@ -1,47 +1,47 @@
-var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["Malt", "malt/", "Dependency"]
+  );
 
-ah["-"].push(
-  ["Malt", "malt/", "Dependency"]
-);
+  ah["malt/"] = [
+    ["Dependency", "d="]
+  ];
 
-ah["malt/"] = [
-  ["Dependency", "d="]
-];
-
-ah["malt/d="] = [
-  ["-PUNCT-", "-PUNCT- "],
-  ["-UNKNOWN-","-UNKNOWN- "],
-  ["ADV","ADV "],
-  ["APP","APP "],
-  ["ATTR","ATTR "],
-  ["AUX","AUX "],
-  ["AVZ","AVZ "],
-  ["CJ","CJ "],
-  ["DET","DET "],
-  ["EXPL","EXPL "],
-  ["GMOD","GMOD "],
-  ["GRAD","GRAD "],
-  ["KOM","KOM "],
-  ["KON","KON "],
-  ["KONJ","KONJ "],
-  ["NEB","NEB "],
-  ["OBJA","OBJA "],
-  ["OBJC","OBJC "],
-  ["OBJD","OBJD "],
-  ["OBJG","OBJG "],
-  ["OBJI","OBJI "],
-  ["OBJP","OBJP "],
-  ["PAR","PAR "],
-  ["PART","PART "],
-  ["PN","PN "],
-  ["PP","PP "],
-  ["PRED","PRED "],
-  ["REL","REL "],
-  ["ROOT","ROOT "],
-  ["S","S "],
-  ["SUBJ","SUBJ "],
-  ["SUBJC","SUBJC "],
-  ["ZEIT","ZEIT "],
-  ["gmod-app","gmod-app "],
-  ["koord","koord "]
-];
+  ah["malt/d="] = [
+    ["-PUNCT-", "-PUNCT- "],
+    ["-UNKNOWN-","-UNKNOWN- "],
+    ["ADV","ADV "],
+    ["APP","APP "],
+    ["ATTR","ATTR "],
+    ["AUX","AUX "],
+    ["AVZ","AVZ "],
+    ["CJ","CJ "],
+    ["DET","DET "],
+    ["EXPL","EXPL "],
+    ["GMOD","GMOD "],
+    ["GRAD","GRAD "],
+    ["KOM","KOM "],
+    ["KON","KON "],
+    ["KONJ","KONJ "],
+    ["NEB","NEB "],
+    ["OBJA","OBJA "],
+    ["OBJC","OBJC "],
+    ["OBJD","OBJD "],
+    ["OBJG","OBJG "],
+    ["OBJI","OBJI "],
+    ["OBJP","OBJP "],
+    ["PAR","PAR "],
+    ["PART","PART "],
+    ["PN","PN "],
+    ["PP","PP "],
+    ["PRED","PRED "],
+    ["REL","REL "],
+    ["ROOT","ROOT "],
+    ["S","S "],
+    ["SUBJ","SUBJ "],
+    ["SUBJC","SUBJC "],
+    ["ZEIT","ZEIT "],
+    ["gmod-app","gmod-app "],
+    ["koord","koord "]
+  ];
+});
diff --git a/dev/js/src/hint/foundries/marmot.js b/dev/js/src/hint/foundries/marmot.js
index 0b80292..ca434dc 100644
--- a/dev/js/src/hint/foundries/marmot.js
+++ b/dev/js/src/hint/foundries/marmot.js
@@ -1,6 +1,4 @@
-require(["hint/foundries/stts"], function () {
-  var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
-
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
   ah["-"].push(
     ["MarMoT", "marmot/", "Morphology, Part-of-Speech"]
   );
diff --git a/dev/js/src/hint/foundries/mate.js b/dev/js/src/hint/foundries/mate.js
index d837fd7..c7cd2e9 100644
--- a/dev/js/src/hint/foundries/mate.js
+++ b/dev/js/src/hint/foundries/mate.js
@@ -1,4 +1,4 @@
-require(["hint/foundries/stts"], function (sttsArray) {
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
   var mateSttsArray = sttsArray.slice(0);
   mateSttsArray.push(
     ["<root-POS>","<root-POS>","Root Part of Speech"]
diff --git a/dev/js/src/hint/foundries/opennlp.js b/dev/js/src/hint/foundries/opennlp.js
index 267bf8d..dc10dc9 100644
--- a/dev/js/src/hint/foundries/opennlp.js
+++ b/dev/js/src/hint/foundries/opennlp.js
@@ -1,7 +1,4 @@
-require(["hint/foundries/stts"], function (sttsArray) {
-  
-  var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
-
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
   ah["-"].push(
     ["OpenNLP", "opennlp/", "Part-of-Speech"]
   );
diff --git a/dev/js/src/hint/foundries/schreibgebrauch.js b/dev/js/src/hint/foundries/schreibgebrauch.js
index 7cce57e..29eed70 100644
--- a/dev/js/src/hint/foundries/schreibgebrauch.js
+++ b/dev/js/src/hint/foundries/schreibgebrauch.js
@@ -1,6 +1,4 @@
-require(["hint/foundries/stts"], function (sttsArray) {
-  var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
-
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
   var sgbrSttsArray = sttsArray.slice(0);
 
   // Push specific information for Schreibgebrauch
diff --git a/dev/js/src/hint/foundries/treetagger.js b/dev/js/src/hint/foundries/treetagger.js
index 35fcfcc..3f94ebd 100644
--- a/dev/js/src/hint/foundries/treetagger.js
+++ b/dev/js/src/hint/foundries/treetagger.js
@@ -1,6 +1,4 @@
-require(["hint/foundries/stts"], function (sttsArray) {
-  var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
-
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
   ah["-"].push(
     ["TreeTagger", "tt/", "Lemma, Part-of-Speech"]
   );
diff --git a/dev/js/src/hint/foundries/xip.js b/dev/js/src/hint/foundries/xip.js
index cd9fc8a..ff7ac5e 100644
--- a/dev/js/src/hint/foundries/xip.js
+++ b/dev/js/src/hint/foundries/xip.js
@@ -1,12 +1,12 @@
-var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["Xerox Parser", "xip/", "Constituency, Lemma, Part-of-Speech"]
+  );
 
-ah["-"].push(
-  ["Xerox Parser", "xip/", "Constituency, Lemma, Part-of-Speech"]
-);
-
-ah["xip/"] = [
-  ["Constituency", "c="],
-  // Inactive: ["Dependency", "d="],
-  ["Lemma", "l="],
-  ["Part-of-Speech", "p="]
-];
+  ah["xip/"] = [
+    ["Constituency", "c="],
+    // Inactive: ["Dependency", "d="],
+    ["Lemma", "l="],
+    ["Part-of-Speech", "p="]
+  ];
+});
diff --git a/dev/js/src/match/table.js b/dev/js/src/match/table.js
index f55dc6f..481e60a 100644
--- a/dev/js/src/match/table.js
+++ b/dev/js/src/match/table.js
@@ -170,32 +170,12 @@
             var e = c.appendChild(d.createElement('div'));
             e.appendChild(text);
           };
-
-          // These are andgroups
-          /*
-          if (name.some(function (item) { return item.indexOf(':') == -1 ? false : true})) {
-            c.classList.add('matchkeyvalues');
-            for (var n = 0; n < name.length; n++) {
-              var text = d.createTextNode(name[n]);
-              var e = c.appendChild(d.createElement('div'));
-              e.appendChild(text);
-            };
-          }
-
-          // Add alternatives
-          else {
-            for (var n = 0; n < name.length; n++) {
-              c.appendChild(d.createTextNode(name[n]));
-              if (n !== name.length - 1) {
-                c.appendChild(d.createElement('br'));
-              };
-            };
-          };
-          */
         }
         else {
           c.appendChild(d.createTextNode(name));
         };
+
+        return c;
       };
 
       tr.addCell = addCell;
@@ -215,6 +195,8 @@
 
       var foundryList = Object.keys(this._foundry).sort();
 
+      var ah = KorAP.annotationHelper || {};
+
       for (var f = 0; f < foundryList.length; f++) {
         var foundry = foundryList[f];
         var layerList =
@@ -231,11 +213,35 @@
           tr.addCell('th', foundry);
           tr.addCell('th', layer);
 
+          var key = foundry + '/' + layer + '=';
+          var anno = ah[key];
+
           for (var v = 0; v < this.length(); v++) {
-            tr.addCell(
+
+            // Get the cell value
+            var value = this.getValue(v, foundry, layer);
+
+            // Add cell to row
+            var cell = tr.addCell(
               'td',
-              this.getValue(v, foundry, layer) 
+              value 
             );
+
+            // Iterate over all annotations and add the descriptions
+            if (anno) {
+
+              // This is a classic hash-lookup-case, but we have
+              // to deal with lists ...
+              for (var i = 0; i < anno.length; i++) {
+                if (anno[i] &&
+                    anno[i][0] &&
+                    anno[i][2] &&
+                    anno[i][0] == value) {
+                  cell.setAttribute('title', anno[i][2]);
+                  break;
+                };
+              };
+            };
           };
         };
       };