Added feature to morphtable: Legend now fixed
diff --git a/public/css/matchinfo.css b/public/css/matchinfo.css
new file mode 100644
index 0000000..cbdc02a
--- /dev/null
+++ b/public/css/matchinfo.css
@@ -0,0 +1,86 @@
+div.matchinfo {
+  position: relative;
+  width: 100%;
+  height: auto;
+  font-size: 10pt;
+}
+
+div.matchinfo div.matchtable {
+  z-index: 20;
+  margin-left: 122pt;
+  overflow-x: scroll;
+  overflow-y: visible;
+  width: auto;
+}
+
+div.matchtable table {
+  border-spacing: 2pt;
+  border-collapse: separate;
+}
+
+div.matchtable th {
+  color: white;
+}
+
+div.matchtable thead th {
+  background-color: #ff8000;
+}
+
+div.matchtable tbody th {
+  text-overflow: ellipsis;
+}
+
+div.matchtable tr > th:nth-of-type(1),
+div.matchtable tr > th:nth-of-type(2) {
+  position: absolute;
+  z-index: 80;
+  vertical-align: middle;
+  border-top: 2pt solid #ffa500;
+  margin-top: -2pt; /* minus the border*/
+  left: 0;
+  width: 60pt;
+  padding: 0 !important;
+}
+
+div.matchtable tr > th:nth-of-type(2) {
+  left: 62pt;
+}
+
+div.matchtable thead tr:nth-of-type(1) > th:nth-of-type(1),
+div.matchtable thead tr:nth-of-type(1) > th:nth-of-type(2) {
+  background-color: #ff8000;
+  height: 100%;
+}
+
+tbody tr:focus {
+  outline: none;
+}
+
+div.matchtable tbody tr:focus {
+  outline: 4px solid #7ba400;
+  -moz-outline-radius: 4px;
+  outline-radius: 4px;
+}
+
+div.matchtable tbody tr:focus td {
+  background-color: #7ba400;
+  color: white;
+  border-color: white;
+}
+
+div.matchtable tr > * {
+  padding: 0pt 6pt;
+  margin: 0;
+  line-height: 150%;
+}
+
+div.matchtable tr > td {
+  background-color: #ffd080;
+  white-space: nowrap;
+  vertical-align: top;
+  text-align: center;
+}
+
+div.matchtable tr:nth-child(odd) > td {
+  background-color: #f4eebb;
+}
diff --git a/public/js/demo/matchInfo.html b/public/js/demo/matchInfo.html
new file mode 100644
index 0000000..accb304
--- /dev/null
+++ b/public/js/demo/matchInfo.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>MatchInfo demo</title>
+    <meta charset="utf-8" />
+    <script src="../src/matchInfo.js"></script>
+    <link type="text/css" rel="stylesheet"
+	  href="../../css/matchinfo.css"></link>
+    <style type="text/css" rel="stylesheet">
+
+body {
+  background-color: #ffa500;
+  font-family: tahoma, verdana, arial;
+}
+
+    </style>
+  </head>
+  <body>
+
+    <div class="matchinfo">
+      <div class="matchtable"></div>
+    </div>
+
+    <script>
+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>";
+
+      // Override getMatchInfo API call
+      KorAP.API.getMatchInfo = function() {
+        return { "snippet": snippet };
+      };
+
+var info = KorAP.MatchInfo.create({
+  'corpusID' : 'WPD',
+  'docID' : 'UUU',
+  'textID' : '01912',
+  'pos' : 'p121-122'
+},
+[
+  '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 t = info.getTable();
+      document.getElementsByClassName('matchtable')[0]
+        .appendChild(t.element());
+    </script>
+
+
+
+    <div class="matchinfo">
+      <div class="matchtable">
+	<table>
+	  <thead>
+            <tr>
+	      <th>Foundry</th>
+	      <th>Layer</th>
+	      <th>Ich</th>
+	      <th>Du</th>
+	      <th>Er</th>
+	    </tr>
+	  </thead>
+	  <tbody>
+	    <tr tabindex="0">
+	      <th>Hallo</th>
+	      <th>X</th>
+	      <td>ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ</td>
+	      <td>ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ<br />ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ</td>
+	      <td>ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ</td>
+	    </tr>
+	    <tr tabindex="0">
+	      <th>geht</th>
+	      <th>y</th>
+	      <td>ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ</td>
+	      <td>ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ</td>
+	      <td>ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ<br />ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ<br />ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ</td>
+	    </tr>
+	    <tr tabindex="0">
+	      <th>es</th>
+	      <th>z</th>
+	      <td>ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ</td>
+	  <td>ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ</td>
+	  <td>ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ<br />ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ<br />ABC DEF GHI JKL MNO PQR STU VWX YZ ABC DEF GHI JKL MNO PQR STU VWX YZ</td>
+	</tr>
+      </tbody>
+    </table>
+  </div>
+</div>
+
+  </body>
+</html>
diff --git a/public/js/spec/matchInfoSpec.js b/public/js/spec/matchInfoSpec.js
index dc0d4a1..4af3764 100644
--- a/public/js/spec/matchInfoSpec.js
+++ b/public/js/spec/matchInfoSpec.js
@@ -1,3 +1,67 @@
+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'
+};
+
+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>";
+
 describe('KorAP.InfoLayer', function () {
   it('should be initializable', function () {
     expect(
@@ -37,71 +101,6 @@
 });
 
 describe('KorAP.MatchInfo', function () {
-  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'
-  };
-
-  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>";
-
-
   it('should be initializable', function () {
     expect(function() {
       KorAP.MatchInfo.create()
@@ -168,7 +167,33 @@
     expect(table.getValue(2, "cnx", "l")[0]).toBe("fähig");
     expect(table.getValue(2, "cnx", "l")[1]).toBe("leistung");
   });
+});
 
+describe('KorAP.MatchTable', function () {
+  it('should be rendered', function () {
+    var info = KorAP.MatchInfo.create(match, available);
+
+    // Override getMatchInfo API call
+    KorAP.API.getMatchInfo = function() {
+      return { "snippet": snippet };
+    };
+
+    var table = info.getTable();
+
+    var e = table.element();
+
+    expect(e.nodeName).toBe('TABLE');
+    expect(e.children[0].nodeName).toBe('THEAD');
+    var tr = e.children[0].children[0];
+    expect(tr.nodeName).toBe('TR');
+    expect(tr.children[0].nodeName).toBe('TH');
+
+    expect(tr.children[0].firstChild.nodeValue).toBe('Foundry');
+    expect(tr.children[1].firstChild.nodeValue).toBe('Layer');
+    expect(tr.children[2].firstChild.nodeValue).toBe('meist');
+    expect(tr.children[3].firstChild.nodeValue).toBe('deutlich');
+    expect(tr.children[4].firstChild.nodeValue).toBe('leistungsfähiger');
+  });
 });
 
 // table = view.toTable();
diff --git a/public/js/src/matchInfo.js b/public/js/src/matchInfo.js
index 515a78f..45f24f5 100644
--- a/public/js/src/matchInfo.js
+++ b/public/js/src/matchInfo.js
@@ -19,6 +19,7 @@
 
   // API requests
   KorAP.API = KorAP.API || {};
+  // TODO: Make this async
   KorAP.API.getMatchInfo = KorAP.API.getMatchInfo || function () { return {} };
 
   KorAP.MatchInfo = {
@@ -81,6 +82,9 @@
     },
 
 
+    /**
+     * Get table object.
+     */
     getTable : function (tokens) {
       var focus = [];
 
@@ -119,7 +123,7 @@
 
       // Get snippet from match info
       if (matchResponse["snippet"] !== undefined) {
-	this._table = KorAP.InfoTable.create(matchResponse["snippet"]);
+	this._table = KorAP.MatchTable.create(matchResponse["snippet"]);
 	return this._table;
       };
 
@@ -129,7 +133,7 @@
     /*
     // Parse snippet for table visualization
     getTree : function (foundry, layer) {
-    },
+    }
     */
   };
 
@@ -189,9 +193,9 @@
   };
 
 
-  KorAP.InfoTable = {
+  KorAP.MatchTable = {
     create : function (snippet) {
-      return Object.create(KorAP.InfoTable)._init(snippet);
+      return Object.create(KorAP.MatchTable)._init(snippet);
     },
     _init : function (snippet) {
       // Create html for traversal
@@ -201,15 +205,12 @@
       this._pos = 0;
       this._token = [];
       this._info = [];
-      this._foundry = [];
-      this._layer = [];
+      this._foundry = {};
+      this._layer = {};
 
       // Parse the snippet
       this._parse(html.childNodes);      
 
-      this._layer = undefined;
-      this._foundry = undefined;
-
       html.innerHTML = '';
       return this;
     },
@@ -275,12 +276,12 @@
 	    found[foundry + "/" + layer].push(RegExp.$3);
 
 	    // Set foundry
-	    if (!this._foundry[foundry])
+	    if (this._foundry[foundry] === undefined)
 	      this._foundry[foundry] = {};
 	    this._foundry[foundry][layer] = 1;
 
 	    // Set layer
-	    if (!this._layer[layer])
+	    if (this._layer[layer] === undefined)
 	      this._layer[layer] = {};
 	    this._layer[layer][foundry] = 1;
 	  };
@@ -290,7 +291,8 @@
 	    this._parse(c.childNodes);
 	}
 
-	// Leaf node - store string on position and go to next string
+	// Leaf node
+	// store string on position and go to next string
 	else if (c.nodeType === 3) {
 	  if (c.nodeValue.match(/[a-z0-9]/i))
 	    this._token[this._pos++] = c.nodeValue;
@@ -300,13 +302,75 @@
       delete this._info[this._pos];
     },
     element : function () {
-      var ce = document.createElement;
       // First the legend table
-      /*
-      var table = ce('table');
-      var row = ce('tr');
-      table.appendChild(tr);
-      */      
+      var d = document;
+      var table = d.createElement('table');
+      var tr = table.appendChild(d.createElement('thead'))
+	.appendChild(
+	  d.createElement('tr')
+	);
+
+      var addCell = function (type, name) {
+	var c = this.appendChild(d.createElement(type))
+	if (name === undefined)
+	  return c;
+
+	if (name instanceof Array) {
+	  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));
+	};
+      };
+
+      tr.addCell = addCell;
+
+      // Add header information
+      tr.addCell('th', 'Foundry');
+      tr.addCell('th', 'Layer');
+
+      // Add tokens
+      for (var i in this._token) {
+	tr.addCell('th', this.getToken(i));
+      };
+
+      var tbody = table.appendChild(
+	d.createElement('tbody')
+      );
+
+      var foundryList = Object.keys(this._foundry).sort();
+
+      for (var f = 0; f < foundryList.length; f++) {
+	var foundry = foundryList[f];
+	var layerList =
+	  Object.keys(this._foundry[foundry]).sort();
+
+	for (var l = 0; l < layerList.length; l++) {
+	  var layer = layerList[l];
+	  tr = tbody.appendChild(
+	    d.createElement('tr')
+	  );
+	  tr.setAttribute('tabindex', 0);
+	  tr.addCell = addCell;
+
+	  tr.addCell('th', foundry);
+	  tr.addCell('th', layer);
+
+	  for (var v = 0; v < this.length(); v++) {
+	    tr.addCell(
+	      'td',
+	      this.getValue(v, foundry, layer) 
+	    );
+	  };
+	};
+      };
+
+      return table;
     }
   };
 
@@ -314,6 +378,6 @@
   /*
     KorAP.InfoFoundryLayer = {};
     KorAP.InfoTree = {};
-    KorAP.InfoTable = {};
+    KorAP.MatchTable = {};
   */
 }(this.KorAP));