Test suite now relies on requirejs as well
diff --git a/dev/demo/all.html b/dev/demo/all.html
index fcd72a5..85d4d2e 100644
--- a/dev/demo/all.html
+++ b/dev/demo/all.html
@@ -4,15 +4,16 @@
     <title>Complete Demo</title>
     <meta charset="utf-8" />
     <link type="text/css" rel="stylesheet" href="../css/kalamar.css" />
-    <script data-main="all.js" src="../js/lib/require.js" async="async"></script>
+    <script data-main="alldemo.js" src="../js/lib/require.js" async="async"></script>
   </head>
   <body>
     <div id="kalamar-bg"></div>
     <header>
       <a href="/" class="logo"><h1><span>KorAP - Corpus Analysis Platform</span></h1></a>
 
-      <a href="#">Feedback</a>
-      <a href="#">Login</a>
+      <div class="button top">
+	<a href="#" class="login"><span>Login</span></a>
+      </div>
 
       <form autocomplete="off" action="/kalamar">
 	<div id="searchbar">
@@ -36,7 +37,7 @@
 	    <option value="cql">CQL v1.2</option>
 	  </select>
 	</span>
-	<div id="button-right">
+	<div class="button right">
 	  <input type="checkbox"
 		 value="1"
 		 name="cutoff"
@@ -45,19 +46,20 @@
 	  <label for="q-cutoff-field"><span></span>Glimpse</label>
 
 	  <!-- Todo: open tutorial - like openTutorial() -->
+	  <a href="doc/faq" class="question"><span>Question</span></a>
 	  <a href="about.html" title="Tutorial" class="tutorial" id="view-tutorial"><span>Tutorial</span></a>
 	</div>
       </form>
     </header>
 
-    <div id="sidebar" tabindex="0">
+    <aside tabindex="0">
       <h2>Einstellungen</h2>
       <p>Anzahl Treffer pro Seite</p>
       <p>Kontext:</p>
       <p>200 Zeichen/Token - 200 Zeichen/Token</p>
       <p>1 Satz 1 Paragraph</p>
       <a>Deutsch|Englisch</a>
-    </div>
+    </aside>
 
     <main>
       <div class="resultinfo">
@@ -87,13 +89,6 @@
 	    </div>
 	    <p class="ref"><strong>Wertparameter</strong> by Hubi,Zwobot,4; published on 2005-03-28 as WWW.03313 (WPD)</p>
 	    <!-- only inject via javascript! -->
-	    <!--
-	    <ul class="action right">
-	      <li class="close" title="Close"><a href="#">Close hit<i class="fa fa-toggle-up"></i></a></li>
-	      <li class="open" title="Open in new tab"><a href="#WPD-WWW.03313-p102-103" target="_blank"><i class="fa fa-external-link-square"></i></a></li>
-	      <li onclick="showTable(this)" title="Annotations"><i class="fa fa-info-circle"></i></li>
-	    </ul>
--->
 	  </li>
 	  <li data-corpus-id="WPD"
 	      data-doc-id="FFF"
@@ -106,11 +101,6 @@
 	      <div class="tokenInfo"></div>
 	    </div>
 	    <p class="ref"><strong>Fehlbezogenes Adjektiv</strong> by Joni2,Peterlustig,BWBot; published on 2005-03-28 as FFF.01460 (WPD)</p>
-	    <ul class="action right">
-	      <li class="close" title="Close"><a href="#"><i class="fa fa-toggle-up"></i></a></li>
-	      <li class="open" title="Open in new tab"><a href="#WPD-FFF.01460-p119-120" target="_blank"><i class="fa fa-external-link-square"></i></a></li>
-	      <li onclick="showTable(this)" title="Annotations"><i class="fa fa-info-circle"></i></li>
-	    </ul>
 	  </li>
 
 	  <li data-corpus-id="WPD"
@@ -124,11 +114,6 @@
 	      <div class="tokenInfo"></div>
 	    </div>
 	    <p class="ref"><strong>High Definition Television</strong> by ArtMechanic,TheK,Andreas -horn- Hornig; published on 2005-03-28 as HHH.06056 (WPD)</p>
-	    <ul class="action right">
-	      <li class="close" title="Close"><a href="#"><i class="fa fa-toggle-up"></i></a></li>
-	      <li class="open" title="Open in new tab"><a href="#WPD-HHH.06056-p2564-2565" target="_blank"><i class="fa fa-external-link-square"></i></a></li>
-	      <li onclick="showTable(this)" title="Annotations"><i class="fa fa-info-circle"></i></li>
-	    </ul>
 	  </li>
       </div>
       <div id="menu"></div>
diff --git a/dev/demo/all.js b/dev/demo/alldemo.js
similarity index 100%
rename from dev/demo/all.js
rename to dev/demo/alldemo.js
diff --git a/dev/demo/build.html b/dev/demo/build.html
new file mode 100644
index 0000000..1a7a86d
--- /dev/null
+++ b/dev/demo/build.html
@@ -0,0 +1,163 @@
+ <!DOCTYPE html>
+<html>
+  <head>
+    <title>Complete Demo</title>
+    <meta charset="utf-8" />
+    <link type="text/css" rel="stylesheet" href="../css/kalamar.css" />
+    <script src="../../public/js/kalamar-0.14.1.js" async="async"></script>
+  </head>
+  <body>
+    <div id="kalamar-bg"></div>
+    <header>
+      <a href="/" class="logo"><h1><span>KorAP - Corpus Analysis Platform</span></h1></a>
+
+      <a href="#">Feedback</a>
+      <a href="#">Login</a>
+
+      <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>
+	  <!-- <i class="fa fa-arrow-circle-down show-hint" onclick="hint.popUp()"></i> -->
+	</div>
+	<div id="vc-view"></div>
+	in <input type="hidden" id="vc-name" name="vc-name" value="Wikipedia" />
+	<input type="text" name="vc" id="vc" value="corpusID = Wikipedia" />
+	with <span class="select">
+	  <!-- Change this to js-menu -->
+	  <select name="ql" id="ql-field">
+	    <option value="poliqarp">Poliqarp</option>
+	    <option value="cosmas2">Cosmas II</option>
+	    <option value="annis">Annis</option>
+	    <option value="cql">CQL v1.2</option>
+	  </select>
+	</span>
+	<div id="button-right">
+	  <input type="checkbox"
+		 value="1"
+		 name="cutoff"
+		 class="checkbox"
+		 id="q-cutoff-field" />
+	  <label for="q-cutoff-field"><span></span>Glimpse</label>
+
+	  <!-- Todo: open tutorial - like openTutorial() -->
+	  <a href="about.html" title="Tutorial" class="tutorial" id="view-tutorial"><span>Tutorial</span></a>
+	</div>
+      </form>
+    </header>
+
+    <div id="sidebar" tabindex="0">
+      <h2>Einstellungen</h2>
+      <p>Anzahl Treffer pro Seite</p>
+      <p>Kontext:</p>
+      <p>200 Zeichen/Token - 200 Zeichen/Token</p>
+      <p>1 Satz 1 Paragraph</p>
+      <a>Deutsch|Englisch</a>
+    </div>
+
+    <main>
+      <div class="resultinfo">
+	<div id="pagination">
+	  <a rel="prev"><span><span>&lt;</span></span></a>
+	  <a rel="self"><span>1</span></a>
+	  <a href="#2"><span>2</span></a>
+	  <a href="#3"><span>3</span></a>
+	  <a class="ellipsis"><span><span>...</span></span></a>
+	  <a href="#52230"><span>52230</span></a>
+	  <a rel="next" href="#2"><span><span>&gt;</span></span></a>
+	</div>
+	<p class="found">Found <span id="total-results">unknown amount of matches</span> in 59.93ms</p>
+      </div>
+
+      <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 xip/c=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><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>
+	      <!-- only inject via javascript! -->
+	    </div>
+	    <p class="ref"><strong>Wertparameter</strong> by Hubi,Zwobot,4; published on 2005-03-28 as WWW.03313 (WPD)</p>
+	    <!-- only inject via javascript! -->
+	    <!--
+	    <ul class="action right">
+	      <li class="close" title="Close"><a href="#">Close hit<i class="fa fa-toggle-up"></i></a></li>
+	      <li class="open" title="Open in new tab"><a href="#WPD-WWW.03313-p102-103" target="_blank"><i class="fa fa-external-link-square"></i></a></li>
+	      <li onclick="showTable(this)" title="Annotations"><i class="fa fa-info-circle"></i></li>
+	    </ul>
+-->
+	  </li>
+	  <li data-corpus-id="WPD"
+	      data-doc-id="FFF"
+	      data-text-id="01460"
+	      data-match-id="p119-120"
+	      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 xip/c=spans"
+	      id="WPD-FFF.01460-p119-120">
+	    <div>
+	      <div class="snippet startMore endMore"><span class="context-left">Der Fehler unterläuft häufig bei der direkten Übersetzung aus dem Englischen, wenn im originalen Ausdruck die beiden Wortteile verschiedene Wörter sind und sich das Adjektiv wahlweise auf das erste oder zweite Wort bezieht. Ein Beispiel ist multiples Testproblem für multiple </span><span class="match">test</span><span class="context-right"> problem.</span></div>
+	      <div class="tokenInfo"></div>
+	    </div>
+	    <p class="ref"><strong>Fehlbezogenes Adjektiv</strong> by Joni2,Peterlustig,BWBot; published on 2005-03-28 as FFF.01460 (WPD)</p>
+	    <ul class="action right">
+	      <li class="close" title="Close"><a href="#"><i class="fa fa-toggle-up"></i></a></li>
+	      <li class="open" title="Open in new tab"><a href="#WPD-FFF.01460-p119-120" target="_blank"><i class="fa fa-external-link-square"></i></a></li>
+	      <li onclick="showTable(this)" title="Annotations"><i class="fa fa-info-circle"></i></li>
+	    </ul>
+	  </li>
+
+	  <li data-corpus-id="WPD"
+	      data-doc-id="HHH"
+	      data-text-id="06056"
+	      data-match-id="p2564-2565"
+	      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 xip/c=spans"
+	      id="WPD-HHH.06056-p2564-2565">
+	    <div>
+	      <div class="snippet startMore endMore"><span class="context-left">HDTV Samples from European (and other) broadcasters and </span><span class="match">test</span><span class="context-right"> transmissions in Europe</span></div>
+	      <div class="tokenInfo"></div>
+	    </div>
+	    <p class="ref"><strong>High Definition Television</strong> by ArtMechanic,TheK,Andreas -horn- Hornig; published on 2005-03-28 as HHH.06056 (WPD)</p>
+	    <ul class="action right">
+	      <li class="close" title="Close"><a href="#"><i class="fa fa-toggle-up"></i></a></li>
+	      <li class="open" title="Open in new tab"><a href="#WPD-HHH.06056-p2564-2565" target="_blank"><i class="fa fa-external-link-square"></i></a></li>
+	      <li onclick="showTable(this)" title="Annotations"><i class="fa fa-info-circle"></i></li>
+	    </ul>
+	  </li>
+      </div>
+      <div id="menu"></div>
+
+      <div class="intro">
+	<p><strong>KorAP</strong> is a new Corpus Analysis Platform, suited for large, multiple annotated corpora and complex search queries independent of particular research questions.</p>
+	<p>This is the new frontend for KorAP, with currently no access to restricted corpora. For full access, please visit the <a href="http://korap.ids-mannheim.de/app">first frontend</a>.</p>
+
+	<p><strong>New to KorAP?</strong> Please check out our <a href="#">tutorial</a>!</p>
+
+	<p>KorAP is developed at the <a href="http://www.ids-mannheim.de">Institute for the German Language</a> and funded by the <a href="http://www.leibniz-gemeinschaft.de/en/about-us/leibniz-competition/projekte-2011/2011-funding-line-2/">Leibniz Association</a>. The separated modules are being published as open source at <a href="http://github.com/KorAP">GitHub</a>.</p>
+      </div>
+      <div id="logos">
+	<div>
+	  <a href="http://www.ids-mannheim.de/" class="logo"><p id="ids-logo"><span>Developed at the Institute for the German Language (IDS)</span></p></a>
+	  <a href="http://www.leibniz-gemeinschaft.de/" class="logo"><p id="leibniz-logo"><span>Member of the Leibniz Association</span></p></a>
+	</div>
+      </div>
+    </main>
+
+    <footer>
+      <a href="/doc/KorAP">About</a>
+      <a href="http://korap.ids-mannheim.de/">About</a>
+      <a href="#">V 0.14</a>
+    </footer>
+
+    <script>
+      var KorAP = KorAP || {};
+      KorAP.URL = 'http://localhost:3000';
+    </script>
+  </body>
+</html>
diff --git a/dev/demo/about.html b/dev/demo/tutorial.html
similarity index 98%
rename from dev/demo/about.html
rename to dev/demo/tutorial.html
index ee41571..c7aea38 100644
--- a/dev/demo/about.html
+++ b/dev/demo/tutorial.html
@@ -6,7 +6,7 @@
     <script data-main="all.js" src="../js/lib/require.js" async="async"></script>
   </head>
   <body class="embedded">
-    <div id="sidebar" tabindex="0" class="active">
+    <aside tabindex="0" class="active">
       <div>
 <!-- Not embedded:
 	<h2>Tutorial</h2>
@@ -58,11 +58,11 @@
 	      </ul>
 -->
 	    </li>
-	    <li><a href="/doc/faq">FAQ</a>
+	    <li><a href="/doc/faq">FAQ (mit Mail)</a>
 	  </ul>
 	</nav>
       </div>
-    </div>
+    </aside>
     <main class="tutorial">
       <h2>KorAP</h2>
 
diff --git a/dev/img/korap-bg-kalamar.svg b/dev/img/korap-bg-kalamar.svg
index 7ec3c0a..6e591f4 100644
--- a/dev/img/korap-bg-kalamar.svg
+++ b/dev/img/korap-bg-kalamar.svg
@@ -10,12 +10,12 @@
   stroke:none;
 }
 .kalamar-shade {
-  fill: #9bad0b;
+  fill:rgb(217, 218, 219); /* #9bad0b; */
   fill-opacity:1;
   stroke:none
 }
 .kalamar-contour {
-  fill:#636f07;
+  fill: rgb(135, 136, 138); /* #636f07; */
   stroke:none;
 }
     </style>
diff --git a/dev/js/runner/hint.html b/dev/js/runner/hint.html
index b9028b9..2ec1c9a 100644
--- a/dev/js/runner/hint.html
+++ b/dev/js/runner/hint.html
@@ -5,13 +5,28 @@
   <title>Spec Runner for Hint Helper</title>
   <link rel="shortcut icon" type="image/png" href="../lib/jasmine-2.1.1/jasmine_favicon.png">
   <link rel="stylesheet" href="../lib/jasmine-2.1.1/jasmine.css">
+  <script src="../lib/require.js"></script>
   <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>
+    require.config({
+      baseUrl: "../src",
+      paths: {
+        "lib" : "../lib",
+        "spec" : "../spec"
+      }
+    });
+    require([
+      'lib/domReady!',
+      'spec/hintSpec'
+    ],
+    function () {
+      if (jsApiReporter.finished === true)
+        jasmine.getEnv().execute();
+    });
+    </script>
 </head>
 <body>
 </body>
-  <script src="../spec/hintSpec.js"></script>
 </html>
diff --git a/dev/js/runner/match.html b/dev/js/runner/match.html
index 553fae7..564acab 100644
--- a/dev/js/runner/match.html
+++ b/dev/js/runner/match.html
@@ -5,13 +5,27 @@
   <title>Spec Runner for Morph Table View</title>
   <link rel="shortcut icon" type="image/png" href="../lib/jasmine-2.1.1/jasmine_favicon.png">
   <link rel="stylesheet" href="../lib/jasmine-2.1.1/jasmine.css">
+  <script src="../lib/require.js"></script>
   <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="../lib/dagre/dagre.min.js"></script>
-  <script src="../src/menu.js"></script>
-  <script src="../src/match.js"></script>
-  <script src="../spec/matchSpec.js"></script>
+  <script>
+    require.config({
+      baseUrl: "../src",
+      paths: {
+        "lib" : "../lib",
+        "spec" : "../spec"
+      }
+    });
+    require([
+      'lib/domReady!',
+      'spec/matchSpec'
+    ],
+    function () {
+      if (jsApiReporter.finished === true)
+        jasmine.getEnv().execute();
+    });
+  </script>
 </head>
 <body>
 </body>
diff --git a/dev/js/runner/menu.html b/dev/js/runner/menu.html
index 2b05abc..acf96d4 100644
--- a/dev/js/runner/menu.html
+++ b/dev/js/runner/menu.html
@@ -5,11 +5,27 @@
   <title>Spec Runner for Menu Helper</title>
   <link rel="shortcut icon" type="image/png" href="../lib/jasmine-2.1.1/jasmine_favicon.png">
   <link rel="stylesheet" href="../lib/jasmine-2.1.1/jasmine.css">
+  <script src="../lib/require.js"></script>
   <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="../spec/menuSpec.js"></script>
+  <script>
+    require.config({
+      baseUrl: "../src",
+      paths: {
+        "lib" : "../lib",
+        "spec" : "../spec"
+      }
+    });
+    require([
+      'lib/domReady!',
+      'spec/menuSpec'
+    ],
+    function () {
+      if (jsApiReporter.finished === true)
+        jasmine.getEnv().execute();
+    });
+  </script>
 </head>
 <body>
 </body>
diff --git a/dev/js/runner/vc.html b/dev/js/runner/vc.html
index f0e8179..2653bb4 100644
--- a/dev/js/runner/vc.html
+++ b/dev/js/runner/vc.html
@@ -1,17 +1,32 @@
 <!DOCTYPE html>
 <html>
-<head>
-  <meta charset="utf-8">
-  <title>Spec Runner for Virtual Collection Builder</title>
-  <link rel="shortcut icon" type="image/png" href="../lib/jasmine-2.1.1/jasmine_favicon.png">
-  <link rel="stylesheet" href="../lib/jasmine-2.1.1/jasmine.css">
-  <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/vc.js"></script>
-  <script src="../spec/vcSpec.js"></script>
-</head>
-<body>
-</body>
+  <head>
+    <meta charset="utf-8">
+    <title>Spec Runner for Virtual Collection Builder</title>
+    <link rel="shortcut icon" type="image/png" href="../lib/jasmine-2.1.1/jasmine_favicon.png">
+    <link rel="stylesheet" href="../lib/jasmine-2.1.1/jasmine.css">
+    <script src="../lib/require.js"></script>
+    <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>
+    require.config({
+      baseUrl: "../src",
+      paths: {
+        "lib" : "../lib",
+        "spec" : "../spec"
+      }
+    });
+    require([
+      'lib/domReady!',
+      'spec/vcSpec'
+    ],
+    function () {
+      if (jsApiReporter.finished === true)
+        jasmine.getEnv().execute();
+    });
+    </script>
+  </head>
+  <body>
+  </body>
 </html>
diff --git a/dev/js/spec/hintSpec.js b/dev/js/spec/hintSpec.js
index 45457b4..20935e1 100644
--- a/dev/js/spec/hintSpec.js
+++ b/dev/js/spec/hintSpec.js
@@ -5,7 +5,6 @@
   var keyboardEvent = document.createEvent("KeyboardEvent");
   var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ?
     "initKeyboardEvent" : "initKeyEvent";
-
   keyboardEvent[initMethod](
     type, 
     true, // bubbles
@@ -19,394 +18,393 @@
     0 // charCodeArgs : unsigned long the Unicode character
       // associated with the depressed key, else 0
   );
-
   element.dispatchEvent(keyboardEvent);
 };
 
 
-describe('KorAP.InputField', function () {
-  var input;
+define(['hint'], function () {
 
-  beforeEach(function () {
-    input = document.createElement("input");
-    input.setAttribute('type', "text");
-    input.setAttribute("value", "abcdefghijklmno");
-    input.style.position = 'absolute';
-    document.getElementsByTagName('body')[0].appendChild(input);
-    input.style.top  = "20px";
-    input.style.left = "30px";
-    input.focus();
-    input.selectionStart = 5;
-  });
+  var hintClass =     require("hint");
+  var inputClass =    require("hint/input");
+  var contextClass =  require("hint/contextanalyzer");
+  var menuClass =     require("hint/menu");
+  var menuItemClass = require("hint/item");
 
-  afterEach(function () {
-    document.getElementsByTagName("body")[0].removeChild(
-      input
-    );    
-  });
+  describe('KorAP.InputField', function () {
+    var input;
 
-  afterAll(function () {
-    try {
-      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(input.selectionStart).toEqual(5);
-    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(input.style.left).toEqual("30px");
-    expect(inputField.mirror().style.left.match(/^(\d+)px$/)[1]).toBeGreaterThan(29);
-    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
+    beforeEach(function () {
+      input = document.createElement("input");
+      input.setAttribute('type', "text");
+      input.setAttribute("value", "abcdefghijklmno");
+      input.style.position = 'absolute';
+      document.getElementsByTagName('body')[0].appendChild(input);
+      input.style.top  = "20px";
+      input.style.left = "30px";
+      input.focus();
+      input.selectionStart = 5;
     });
 
-    expect(hint).toBeTruthy();
-  });
-});
+    afterEach(function () {
+      document.getElementsByTagName("body")[0].removeChild(
+	input
+      );    
+    });
 
-describe('KorAP.HintMenuItem', function () {
-  it('should be initializable', function () {
-    expect(
-      function() { KorAP.HintMenuItem.create([]) }
-    ).toThrow(new Error("Missing parameters"));
+    afterAll(function () {
+      try {
+	document.getElementsByTagName("body")[0].removeChild(
+	  document.getElementById("searchMirror")
+	);
+      }
+      catch (e) {};
+    });
 
-    expect(
-      function() { KorAP.HintMenuItem.create(['CoreNLP']) }
-    ).toThrow(new Error("Missing parameters"));
+    it('should be initializable', function () {
+      // Supports: context, searchField
+      var inputField = inputClass.create(input);
+      expect(inputField._element).not.toBe(undefined);
+    });
 
-    var menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    expect(menuItem.name()).toEqual('CoreNLP');
-    expect(menuItem.action()).toEqual('corenlp/');
-    expect(menuItem.desc()).toBeUndefined();
+    it('should have text', function () {
+      expect(input.value).toEqual('abcdefghijklmno');
+      var inputField = inputClass.create(input);
 
-    menuItem = KorAP.HintMenuItem.create(
-      ['CoreNLP', 'corenlp/', 'It\'s funny']
-    );
-    expect(menuItem.name()).toEqual('CoreNLP');
-    expect(menuItem.action()).toEqual('corenlp/');
-    expect(menuItem.desc()).not.toBeUndefined();
-    expect(menuItem.desc()).toEqual('It\'s funny');
-  });
+      expect(inputField.value()).toEqual("abcdefghijklmno");
 
-  it('should have an element', function () {
-    var menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    expect(menuItem.element()).not.toBe(undefined);
-    expect(menuItem.element().nodeName).toEqual("LI");
+      expect(input.selectionStart).toEqual(5);
+      expect(inputField.element().selectionStart).toEqual(5);
+      expect(inputField.split()[0]).toEqual("abcde");
+      expect(inputField.split()[1]).toEqual("fghijklmno");
 
-    var title = menuItem.element().firstChild;
-    expect(title.nodeName).toEqual("SPAN");
-    expect(title.firstChild.nodeType).toEqual(3);
-    expect(title.firstChild.nodeValue).toEqual("CoreNLP");
-    expect(menuItem.element().childNodes[0]).not.toBe(undefined);
-    expect(menuItem.element().childNodes[1]).toBe(undefined);
+      inputField.insert("xyz");
+      expect(inputField.value()).toEqual('abcdexyzfghijklmno');
+      expect(inputField.split()[0]).toEqual("abcdexyz");
+      expect(inputField.split()[1]).toEqual("fghijklmno");
+    });
 
-    menuItem = KorAP.HintMenuItem.create(
-      ['CoreNLP', 'corenlp/', 'my DescRiption']
-    );
-    expect(menuItem.element()).not.toBe(undefined);
-    expect(menuItem.element().nodeName).toEqual("LI");
+    it('should be correctly positioned', function () {
+      expect(input.value).toEqual('abcdefghijklmno');
+      var inputField = inputClass.create(input);
+      document.getElementsByTagName("body")[0].appendChild(input);
+      inputField.reposition();
+      expect(input.style.left).toEqual("30px");
+      expect(inputField.mirror().style.left.match(/^(\d+)px$/)[1]).toBeGreaterThan(29);
+      expect(inputField.mirror().style.top.match(/^(\d+)px$/)[1]).toBeGreaterThan(20);
+    });
 
-    title = menuItem.element().firstChild;
-    expect(title.nodeName).toEqual("SPAN");
-    expect(title.firstChild.nodeType).toEqual(3); // TextNode
-    expect(title.firstChild.nodeValue).toEqual("CoreNLP");
+    it('should have a correct context', function () {
+      expect(input.value).toEqual('abcdefghijklmno');
+      var inputField = inputClass.create(input);
+      expect(inputField.value()).toEqual("abcdefghijklmno");
+      expect(inputField.element().selectionStart).toEqual(5);
+      expect(inputField.split()[0]).toEqual("abcde");
+      expect(inputField.context()).toEqual("abcde");
+    });
 
-    expect(menuItem.element().childNodes[0]).not.toBe(undefined);
-    expect(menuItem.element().childNodes[1]).not.toBe(undefined);
-
-    var desc = menuItem.element().lastChild;
-    expect(desc.nodeName).toEqual("SPAN");
-    expect(desc.firstChild.nodeType).toEqual(3); // TextNode
-    expect(desc.firstChild.nodeValue).toEqual("my DescRiption");
+    /*
+      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);
+      });
+    */
   });
 
 
-  it('should be activatable and deactivateable by class', function () {
-    var menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toBe(null);
-    menuItem.active(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("active");
-    menuItem.active(false); // Is active
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toEqual("");
-    menuItem.active(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("active");
+  describe('KorAP.ContextAnalyzer', function () {
+    it('should be initializable', function () {
+      var analyzer = contextClass.create(")");
+      expect(analyzer).toBe(undefined);
+      analyzer = contextClass.create(".+?");
+      expect(analyzer).not.toBe(undefined);
+    });
 
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toBe(null);
-    menuItem.active(false); // Is not active
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toBe(null);
+    it('should check correctly', function () {
+      analyzer = contextClass.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=");
+    });
   });
 
-  it('should be set to boundary', function () {
-    var menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toBe(null);
 
-    // Set active
-    menuItem.active(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.noMore()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toEqual("active");
+  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"]
+      ]
+    };
 
-    // Set no more
-    menuItem.noMore(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.noMore()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("active no-more");
+    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;
+    });
 
-    // No no more
-    menuItem.noMore(false);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.noMore()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toEqual("active");
+    it('should be initializable', function () {
+      // Supports: context, searchField
+      var hint = hintClass.create({
+	inputField : input
+      });
 
-    // Set no more, deactivate
-    menuItem.noMore(true);
-    menuItem.active(false);
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.noMore()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("no-more");
-
-    // Set active
-    menuItem.active(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.noMore()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("no-more active");
+      expect(hint).toBeTruthy();
+    });
   });
 
-  xit('should be highlightable', function () {
-    // Highlight in the middle
-    var menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("ren");
-    expect(menuItem.element().innerHTML).toEqual("<span>Co<mark>reN</mark>LP</span>");
+  describe('KorAP.HintMenuItem', function () {
+    it('should be initializable', function () {
+      expect(
+	function() { menuItemClass.create([]) }
+      ).toThrow(new Error("Missing parameters"));
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+      expect(
+	function() { menuItemClass.create(['CoreNLP']) }
+      ).toThrow(new Error("Missing parameters"));
 
-    // Starting highlight
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("cor");
-    expect(menuItem.element().innerHTML).toEqual("<span><mark>Cor</mark>eNLP</span>");
+      var menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      expect(menuItem.name()).toEqual('CoreNLP');
+      expect(menuItem.action()).toEqual('corenlp/');
+      expect(menuItem.desc()).toBeUndefined();
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
-/*
+      menuItem = menuItemClass.create(
+	['CoreNLP', 'corenlp/', 'It\'s funny']
+      );
+      expect(menuItem.name()).toEqual('CoreNLP');
+      expect(menuItem.action()).toEqual('corenlp/');
+      expect(menuItem.desc()).not.toBeUndefined();
+      expect(menuItem.desc()).toEqual('It\'s funny');
+    });
 
-    // Starting highlight - short
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("c");
-    expect(menuItem.element().innerHTML).toEqual("<span><mark>C</mark>oreNLP</span>");
+    it('should have an element', function () {
+      var menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      expect(menuItem.element()).not.toBe(undefined);
+      expect(menuItem.element().nodeName).toEqual("LI");
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+      var title = menuItem.element().firstChild;
+      expect(title.nodeName).toEqual("SPAN");
+      expect(title.firstChild.nodeType).toEqual(3);
+      expect(title.firstChild.nodeValue).toEqual("CoreNLP");
+      expect(menuItem.element().childNodes[0]).not.toBe(undefined);
+      expect(menuItem.element().childNodes[1]).toBe(undefined);
 
-    // Highlight at the end
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("nlp");
-    expect(menuItem.element().innerHTML).toEqual("<span>Core<mark>NLP</mark></span>");
+      menuItem = menuItemClass.create(
+	['CoreNLP', 'corenlp/', 'my DescRiption']
+      );
+      expect(menuItem.element()).not.toBe(undefined);
+      expect(menuItem.element().nodeName).toEqual("LI");
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+      title = menuItem.element().firstChild;
+      expect(title.nodeName).toEqual("SPAN");
+      expect(title.firstChild.nodeType).toEqual(3); // TextNode
+      expect(title.firstChild.nodeValue).toEqual("CoreNLP");
 
-    // Highlight at the end - short
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("p");
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNL<mark>P</mark></span>");
+      expect(menuItem.element().childNodes[0]).not.toBe(undefined);
+      expect(menuItem.element().childNodes[1]).not.toBe(undefined);
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
-
-    // No highlight
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("xp");
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+      var desc = menuItem.element().lastChild;
+      expect(desc.nodeName).toEqual("SPAN");
+      expect(desc.firstChild.nodeType).toEqual(3); // TextNode
+      expect(desc.firstChild.nodeValue).toEqual("my DescRiption");
+    });
 
 
-    // Highlight in the middle - first
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
-    menuItem.highlight("ren");
-    expect(menuItem.element().innerHTML).toEqual("<span>Co<mark>reN</mark>LP</span><span class=\"desc\">This is my Example</span>");
+    it('should be activatable and deactivateable by class', function () {
+      var menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toBe(null);
+      menuItem.active(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("active");
+      menuItem.active(false); // Is active
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toEqual("");
+      menuItem.active(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("active");
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual('<span>CoreNLP</span><span class="desc">This is my Example</span>');
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toBe(null);
+      menuItem.active(false); // Is not active
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toBe(null);
+    });
 
-    // Highlight in the middle - second
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
-    menuItem.highlight("ampl");
-    expect(menuItem.element().innerHTML).toEqual('<span>CoreNLP</span><span class="desc">This is my Ex<mark>ampl</mark>e</span>');
+    it('should be set to boundary', function () {
+      var menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toBe(null);
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual('<span>CoreNLP</span><span class="desc">This is my Example</span>');
+      // Set active
+      menuItem.active(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.noMore()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toEqual("active");
 
-    // Highlight in the middle - both
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+      // Set no more
+      menuItem.noMore(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.noMore()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("active no-more");
 
-    menuItem.highlight("e");
-    expect(menuItem.element().innerHTML).toEqual('<span>Cor<mark>e</mark>NLP</span><span class="desc">This is my <mark>E</mark>xampl<mark>e</mark></span>');
+      // No no more
+      menuItem.noMore(false);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.noMore()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toEqual("active");
 
+      // Set no more, deactivate
+      menuItem.noMore(true);
+      menuItem.active(false);
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.noMore()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("no-more");
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span>This is my Example</span>");
+      // Set active
+      menuItem.active(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.noMore()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("no-more active");
+    });
 
-    // Highlight in the end - second
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
-    menuItem.highlight("le");
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span>This is my Examp<mark>le</mark></span>");
+    it('should be highlightable', function () {
+      // Highlight in the middle
+      var menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("ren");
+      expect(menuItem.element().innerHTML).toEqual("<span>Co<mark>reN</mark>LP</span>");
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span>This is my Example</span>");
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
 
-    // Highlight at the beginning - second
-    menuItem = KorAP.HintMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
-    menuItem.highlight("this");
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span><mark>This</mark> is my Example</span>");
+      // Starting highlight
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("cor");
+      expect(menuItem.element().innerHTML).toEqual("<span><mark>Cor</mark>eNLP</span>");
 
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span>This is my Example</span>");
-*/
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+
+      // Starting highlight - short
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("c");
+      expect(menuItem.element().innerHTML).toEqual("<span><mark>C</mark>oreNLP</span>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+
+      // Highlight at the end
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("nlp");
+      expect(menuItem.element().innerHTML).toEqual("<span>Core<mark>NLP</mark></span>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+
+      // Highlight at the end - short
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("p");
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNL<mark>P</mark></span>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+
+      // No highlight
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("xp");
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span>");
+
+      // Highlight in the middle - first
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+
+      menuItem.highlight("ren");
+      expect(menuItem.element().innerHTML).toEqual("<span>Co<mark>reN</mark>LP</span><span class=\"desc\">This is my Example</span>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual('<span>CoreNLP</span><span class="desc">This is my Example</span>');
+
+      // Highlight in the middle - second
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+      menuItem.highlight("ampl");
+      expect(menuItem.element().innerHTML).toEqual('<span>CoreNLP</span><span class="desc">This is my Ex<mark>ampl</mark>e</span>');
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual('<span>CoreNLP</span><span class="desc">This is my Example</span>');
+
+      // Highlight in the middle - both
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+
+      menuItem.highlight("e");
+      expect(menuItem.element().innerHTML).toEqual('<span>Cor<mark>e</mark>NLP</span><span class="desc">This is my <mark>E</mark>xampl<mark>e</mark></span>');
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span class=\"desc\">This is my Example</span>");
+
+      // Highlight in the end - second
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+      menuItem.highlight("le");
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span class=\"desc\">This is my Examp<mark>le</mark></span>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span class=\"desc\">This is my Example</span>");
+
+      // Highlight at the beginning - second
+      menuItem = menuItemClass.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+      menuItem.highlight("this");
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span class=\"desc\"><mark>This</mark> is my Example</span>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("<span>CoreNLP</span><span class=\"desc\">This is my Example</span>");
+    });
   });
-});
 
+  describe('KorAP.HintMenu', function () {
 
-describe('KorAP.HintMenu', function () {
+    var list = [
+      ["Constituency", "c=", "Example 1"],
+      ["Lemma", "l="],
+      ["Morphology", "m=", "Example 2"],
+      ["Part-of-Speech", "p="],
+      ["Syntax", "syn="]
+    ];
 
-  var list = [
-    ["Constituency", "c=", "Example 1"],
-    ["Lemma", "l="],
-    ["Morphology", "m=", "Example 2"],
-    ["Part-of-Speech", "p="],
-    ["Syntax", "syn="]
-  ];
+    it('should be initializable', function () {
 
+      var menu = menuClass.create(null, "cnx/", list);
+      expect(menu.context()).toEqual('cnx/');
+      expect(menu.element().nodeName).toEqual('UL');
+      expect(menu.element().style.opacity).toEqual("0");
 
-  it('should be initializable', function () {
+      menu.limit(8);
 
-    var menu = KorAP.HintMenu.create(null, "cnx/", list);
-    expect(menu.context()).toEqual('cnx/');
-    expect(menu.element().nodeName).toEqual('UL');
-    expect(menu.element().style.opacity).toEqual("0");
+      // view
+      menu.show();
 
-    menu.limit(8);
+      // First element in list
+      expect(menu.item(0).active()).toBe(true);
+      expect(menu.item(0).noMore()).toBe(true);
+      
+      // Middle element in list
+      expect(menu.item(2).active()).toBe(false);
+      expect(menu.item(2).noMore()).toBe(false);
 
-    // view
-    menu.show();
-
-    // First element in list
-    expect(menu.item(0).active()).toBe(true);
-    expect(menu.item(0).noMore()).toBe(true);
-    
-    // Middle element in list
-    expect(menu.item(2).active()).toBe(false);
-    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);
+      // Last element in list
+      expect(menu.item(menu.length() - 1).active()).toBe(false);
+      expect(menu.item(menu.length() - 1).noMore()).toBe(true);
+    });
   });
 });
diff --git a/dev/js/spec/matchSpec.js b/dev/js/spec/matchSpec.js
index f520557..28eb844 100644
--- a/dev/js/spec/matchSpec.js
+++ b/dev/js/spec/matchSpec.js
@@ -1,3 +1,6 @@
+// Regarding async:
+// http://stackoverflow.com/questions/16423156/getting-requirejs-to-work-with-jasmine
+
 var available = [
   'base/s=spans',
   'corenlp/c=spans',
@@ -140,421 +143,435 @@
 };
 
 
-// Override getMatchInfo API call
-KorAP.API.getMatchInfo = function (x, param, cb) {
-  if (param['spans'] === undefined || param['spans'] === false)
-    cb({ "snippet": snippet });
-  else
-    cb({ "snippet": treeSnippet });
-};
+define(['match'], function () {
 
-
-describe('KorAP.InfoLayer', function () {
-
-  it('should be initializable', function () {
-    expect(
-      function() { KorAP.InfoLayer.create() }
-    ).toThrow(new Error("Missing parameters"));
-
-    expect(
-      function() { KorAP.InfoLayer.create("base") }
-    ).toThrow(new Error("Missing parameters"));
-
-    var layer = KorAP.InfoLayer.create("base", "s");
-    expect(layer).toBeTruthy();
-    expect(layer.foundry).toEqual("base");
-    expect(layer.layer).toEqual("s");
-    expect(layer.type).toEqual("tokens");
-
-    layer = KorAP.InfoLayer.create("cnx", "syn", "spans");
-    expect(layer).toBeTruthy();
-    expect(layer.foundry).toEqual("cnx");
-    expect(layer.layer).toEqual("syn");
-    expect(layer.type).toEqual("spans");
-  });
-});
-
-
-describe('KorAP.Match', function () {
-  var match = {
-    'corpusID'  : 'WPD',
-    'docID'     : 'UUU',
-    'textID'    : '01912',
-    'matchID'   : 'p121-122',
-    'available' : available
+  // Override getMatchInfo API call
+  KorAP.API.getMatchInfo = function (x, param, cb) {
+    if (param['spans'] === undefined || param['spans'] === false)
+      cb({ "snippet": snippet });
+    else
+      cb({ "snippet": treeSnippet });
   };
 
-  it('should be initializable by Object', function () {
-    expect(function() {
-      KorAP.Match.create()
-    }).toThrow(new Error('Missing parameters'));
+  describe('KorAP.InfoLayer', function () {
+    
+    var infoClass = require('match/infolayer');
 
-    expect(KorAP.Match.create(match)).toBeTruthy();
+    it('should be initializable', function () {
+      expect(
+	function() { infoClass.create() }
+      ).toThrow(new Error("Missing parameters"));
 
-    var m = KorAP.Match.create(match);
-    expect(m.corpusID).toEqual("WPD");
-    expect(m.docID).toEqual("UUU");
-    expect(m.textID).toEqual("01912");
-    expect(m.matchID).toEqual("p121-122");
+      expect(
+	function() { infoClass.create("base") }
+      ).toThrow(new Error("Missing parameters"));
 
-    // /corpus/WPD/UUU.01912/p121-122/matchInfo?spans=false&foundry=*
-    var m = KorAP.Match.create(match);
+      var layer = infoClass.create("base", "s");
+      expect(layer).toBeTruthy();
+      expect(layer.foundry).toEqual("base");
+      expect(layer.layer).toEqual("s");
+      expect(layer.type).toEqual("tokens");
 
-    // Spans:
-    var spans = m.getSpans();
-    expect(spans[0].foundry).toEqual("base");
-    expect(spans[0].layer).toEqual("s");
-
-    expect(spans[1].foundry).toEqual("corenlp");
-    expect(spans[1].layer).toEqual("c");
-
-    expect(spans[2].foundry).toEqual("corenlp");
-    expect(spans[2].layer).toEqual("s");
-
-    expect(spans[spans.length-1].foundry).toEqual("tt");
-    expect(spans[spans.length-1].layer).toEqual("s");
-
-    // Tokens:
-    var tokens = m.getTokens();
-    expect(tokens[0].foundry).toEqual("corenlp");
-    expect(tokens[0].layer).toEqual("ne");
-
-    expect(tokens[1].foundry).toEqual("corenlp");
-    expect(tokens[1].layer).toEqual("p");
-
-    expect(tokens[tokens.length-1].foundry).toEqual("tt");
-    expect(tokens[tokens.length-1].layer).toEqual("p");
-  });
-
-
-  it('should be initializable by Node', function () {
-    var m = KorAP.Match.create(matchElementFactory());
-    expect(m.corpusID).toEqual("WPD");
-    expect(m.docID).toEqual("FFF");
-    expect(m.textID).toEqual("01460");
-    expect(m.matchID).toEqual("p119-120");
-
-    // Spans:
-    var spans = m.getSpans();
-    expect(spans[0].foundry).toEqual("base");
-    expect(spans[0].layer).toEqual("s");
-
-    expect(spans[1].foundry).toEqual("corenlp");
-    expect(spans[1].layer).toEqual("c");
-
-    expect(spans[2].foundry).toEqual("corenlp");
-    expect(spans[2].layer).toEqual("s");
-
-    expect(spans[spans.length-1].foundry).toEqual("tt");
-    expect(spans[spans.length-1].layer).toEqual("s");
-
-    // Tokens:
-    var tokens = m.getTokens();
-    expect(tokens[0].foundry).toEqual("corenlp");
-    expect(tokens[0].layer).toEqual("ne");
-
-    expect(tokens[1].foundry).toEqual("corenlp");
-    expect(tokens[1].layer).toEqual("p");
-
-    expect(tokens[tokens.length-1].foundry).toEqual("tt");
-    expect(tokens[tokens.length-1].layer).toEqual("p");
-
-  });
-
-  it('should react to gui actions', function () {
-    var e = matchElementFactory();
-
-    expect(e.classList.contains('active')).toBe(false);
-    expect(e["_match"]).toBe(undefined);
-
-    var m = KorAP.Match.create(e);
-
-    expect(e.classList.contains('active')).toBe(false);
-    expect(e["_match"]).not.toBe(undefined);
-
-    // Open the match
-    m.open();
-
-    expect(e.classList.contains('active')).toBe(true);
-    expect(e["_match"]).not.toBe(undefined);
-
-    // Close the match
-    m.close();
-    expect(e.classList.contains('active')).toBe(false);
-    expect(e["_match"]).not.toBe(undefined);
-
-  });
-});
-
-
-describe('KorAP.MatchInfo', function () {
-
-  var m = KorAP.Match.create(match);
-  var info = m.info();
-
-  it('should contain a valid info', function () {
-    expect(m._info).toEqual(info);
-  });
-
-  var table1, table2;
-
-  // Async preparation
-  it('should fail to load a table async', function (done) {
-    expect(info).toBeTruthy();
-
-    info.getTable([], function (tablen) {
-      table1 = tablen;
-      done();
+      layer = infoClass.create("cnx", "syn", "spans");
+      expect(layer).toBeTruthy();
+      expect(layer.foundry).toEqual("cnx");
+      expect(layer.layer).toEqual("syn");
+      expect(layer.type).toEqual("spans");
     });
   });
 
-  it('should\'nt be parsable (async)', function () {
-    expect(table1).not.toBeTruthy();
-  });
 
-  it('should load a working table async', function(done) {
-    expect(info).toBeTruthy();
-    info.getTable(undefined, function (tablem) {
-      table2 = tablem;
-      done();
+  describe('KorAP.Match', function () {
+    var match = {
+      'corpusID'  : 'WPD',
+      'docID'     : 'UUU',
+      'textID'    : '01912',
+      'matchID'   : 'p121-122',
+      'available' : available
+    };
+
+    var matchClass = require('match');
+
+    it('should be initializable by Object', function () {
+      expect(function() {
+	matchClass.create()
+      }).toThrow(new Error('Missing parameters'));
+
+      expect(matchClass.create(match)).toBeTruthy();
+
+      var m = matchClass.create(match);
+      expect(m.corpusID).toEqual("WPD");
+      expect(m.docID).toEqual("UUU");
+      expect(m.textID).toEqual("01912");
+      expect(m.matchID).toEqual("p121-122");
+
+      // /corpus/WPD/UUU.01912/p121-122/matchInfo?spans=false&foundry=*
+      var m = matchClass.create(match);
+
+      // Spans:
+      var spans = m.getSpans();
+      expect(spans[0].foundry).toEqual("base");
+      expect(spans[0].layer).toEqual("s");
+
+      expect(spans[1].foundry).toEqual("corenlp");
+      expect(spans[1].layer).toEqual("c");
+
+      expect(spans[2].foundry).toEqual("corenlp");
+      expect(spans[2].layer).toEqual("s");
+
+      expect(spans[spans.length-1].foundry).toEqual("tt");
+      expect(spans[spans.length-1].layer).toEqual("s");
+
+      // Tokens:
+      var tokens = m.getTokens();
+      expect(tokens[0].foundry).toEqual("corenlp");
+      expect(tokens[0].layer).toEqual("ne");
+
+      expect(tokens[1].foundry).toEqual("corenlp");
+      expect(tokens[1].layer).toEqual("p");
+
+      expect(tokens[tokens.length-1].foundry).toEqual("tt");
+      expect(tokens[tokens.length-1].layer).toEqual("p");
     });
-  });
-  
-  it('should parse into a table (async)', function () {
-    expect(table2).toBeTruthy();
-
-    expect(table2.length()).toBe(3);
-
-    expect(table2.getToken(0)).toBe("meist");
-    expect(table2.getToken(1)).toBe("deutlich");
-    expect(table2.getToken(2)).toBe("leistungsfähiger");
-
-    expect(table2.getValue(0, "cnx", "p")[0]).toBe("ADV");
-    expect(table2.getValue(0, "cnx", "syn")[0]).toBe("@PREMOD");
-
-    expect(table2.getValue(2, "cnx", "l")[0]).toBe("fähig");
-    expect(table2.getValue(2, "cnx", "l")[1]).toBe("leistung");
-  });
 
 
-  it('should parse into a table view', function () {
-    var matchElement = matchElementFactory();
-    expect(matchElement.tagName).toEqual('LI');
+    it('should be initializable by Node', function () {
+      var m = matchClass.create(matchElementFactory());
+      expect(m.corpusID).toEqual("WPD");
+      expect(m.docID).toEqual("FFF");
+      expect(m.textID).toEqual("01460");
+      expect(m.matchID).toEqual("p119-120");
 
-    // Match
-    expect(matchElement.children[0].tagName).toEqual('DIV');
+      // Spans:
+      var spans = m.getSpans();
+      expect(spans[0].foundry).toEqual("base");
+      expect(spans[0].layer).toEqual("s");
 
-    // snippet
-    expect(matchElement.children[0].children[0].tagName).toEqual('DIV');
-    expect(matchElement.children[0].children[0].classList.contains('snippet')).toBeTruthy();
-    expect(matchElement.children[0].children[0].firstChild.nodeValue).toEqual('check');
+      expect(spans[1].foundry).toEqual("corenlp");
+      expect(spans[1].layer).toEqual("c");
 
-    // reference
-    expect(matchElement.children[1].classList.contains('ref')).toBeTruthy();
-    expect(matchElement.children[1].firstChild.nodeValue).toEqual('me');
+      expect(spans[2].foundry).toEqual("corenlp");
+      expect(spans[2].layer).toEqual("s");
 
-    // not yet
-    expect(matchElement.children[0].children[1]).toBe(undefined);
+      expect(spans[spans.length-1].foundry).toEqual("tt");
+      expect(spans[spans.length-1].layer).toEqual("s");
 
-    var info = KorAP.Match.create(matchElement).info();
-    info.toggle();
+      // Tokens:
+      var tokens = m.getTokens();
+      expect(tokens[0].foundry).toEqual("corenlp");
+      expect(tokens[0].layer).toEqual("ne");
 
-    // Match
-    expect(matchElement.children[0].tagName).toEqual('DIV');
+      expect(tokens[1].foundry).toEqual("corenlp");
+      expect(tokens[1].layer).toEqual("p");
 
-    // snippet
-    expect(matchElement.children[0].children[0].tagName).toEqual('DIV');
-    expect(matchElement.children[0].children[0].classList.contains('snippet')).toBeTruthy();
-    expect(matchElement.children[0].children[0].firstChild.nodeValue).toEqual('check');
+      expect(tokens[tokens.length-1].foundry).toEqual("tt");
+      expect(tokens[tokens.length-1].layer).toEqual("p");
 
-    // reference
-    expect(matchElement.children[1].classList.contains('ref')).toBeTruthy();
-    expect(matchElement.children[1].firstChild.nodeValue).toEqual('me');
+    });
 
-    // now
-    var infotable = matchElement.children[0].children[1];
-    expect(infotable.tagName).toEqual('DIV');
-    expect(infotable.classList.contains('matchinfo')).toBeTruthy();
+    it('should react to gui actions', function () {
+      var e = matchElementFactory();
 
-    expect(infotable.children[0].classList.contains('matchtable')).toBeTruthy();
-    expect(infotable.children[1].classList.contains('addtree')).toBeTruthy();
-  });
+      expect(e.classList.contains('active')).toBe(false);
+      expect(e["_match"]).toBe(undefined);
 
-  var tree;
-  it('should parse into a tree (async) 1', function (done) {
-    var info = KorAP.Match.create(match).info();
-    expect(info).toBeTruthy();
-    info.getTree(undefined, undefined, function (treem) {
-      tree = treem;
-      done();
+      var m = matchClass.create(e);
+
+      expect(e.classList.contains('active')).toBe(false);
+      expect(e["_match"]).not.toBe(undefined);
+
+      // Open the match
+      m.open();
+
+      expect(e.classList.contains('active')).toBe(true);
+      expect(e["_match"]).not.toBe(undefined);
+
+      // Close the match
+      m.close();
+      expect(e.classList.contains('active')).toBe(false);
+      expect(e["_match"]).not.toBe(undefined);
+
     });
   });
 
-  it('should parse into a tree (async) 2', function () {
-    expect(tree).toBeTruthy();
-    expect(tree.nodes()).toEqual(49);
-  });
+
+  describe('KorAP.MatchInfo', function () {
+
+    var matchClass = require('match');
+
+    var m = matchClass.create(match);
+    var info = m.info();
+
+    it('should contain a valid info', function () {
+      expect(m._info).toEqual(info);
+    });
+
+    var table1, table2;
+
+    // Async preparation
+    it('should fail to load a table async', function (done) {
+      expect(info).toBeTruthy();
+
+      info.getTable([], function (tablen) {
+	table1 = tablen;
+	done();
+      });
+    });
+
+    it('should\'nt be parsable (async)', function () {
+      expect(table1).not.toBeTruthy();
+    });
+
+    it('should load a working table async', function(done) {
+      expect(info).toBeTruthy();
+      info.getTable(undefined, function (tablem) {
+	table2 = tablem;
+	done();
+      });
+    });
+    
+    it('should parse into a table (async)', function () {
+      expect(table2).toBeTruthy();
+
+      expect(table2.length()).toBe(3);
+
+      expect(table2.getToken(0)).toBe("meist");
+      expect(table2.getToken(1)).toBe("deutlich");
+      expect(table2.getToken(2)).toBe("leistungsfähiger");
+
+      expect(table2.getValue(0, "cnx", "p")[0]).toBe("ADV");
+      expect(table2.getValue(0, "cnx", "syn")[0]).toBe("@PREMOD");
+
+      expect(table2.getValue(2, "cnx", "l")[0]).toBe("fähig");
+      expect(table2.getValue(2, "cnx", "l")[1]).toBe("leistung");
+    });
+
+    it('should parse into a table view', function () {
+      var matchElement = matchElementFactory();
+      expect(matchElement.tagName).toEqual('LI');
+
+      // Match
+      expect(matchElement.children[0].tagName).toEqual('DIV');
+
+      // snippet
+      expect(matchElement.children[0].children[0].tagName).toEqual('DIV');
+      expect(matchElement.children[0].children[0].classList.contains('snippet')).toBeTruthy();
+      expect(matchElement.children[0].children[0].firstChild.nodeValue).toEqual('check');
+
+      // reference
+      expect(matchElement.children[1].classList.contains('ref')).toBeTruthy();
+      expect(matchElement.children[1].firstChild.nodeValue).toEqual('me');
+
+      // not yet
+      expect(matchElement.children[0].children[1]).toBe(undefined);
+
+      var info = matchClass.create(matchElement).info();
+      info.toggle();
+
+      // Match
+      expect(matchElement.children[0].tagName).toEqual('DIV');
+
+      // snippet
+      expect(matchElement.children[0].children[0].tagName).toEqual('DIV');
+      expect(matchElement.children[0].children[0].classList.contains('snippet')).toBeTruthy();
+      expect(matchElement.children[0].children[0].firstChild.nodeValue).toEqual('check');
+
+      // reference
+      expect(matchElement.children[1].classList.contains('ref')).toBeTruthy();
+      expect(matchElement.children[1].firstChild.nodeValue).toEqual('me');
+
+      // now
+      var infotable = matchElement.children[0].children[1];
+      expect(infotable.tagName).toEqual('DIV');
+      expect(infotable.classList.contains('matchinfo')).toBeTruthy();
+
+      expect(infotable.children[0].classList.contains('matchtable')).toBeTruthy();
+      expect(infotable.children[1].classList.contains('addtree')).toBeTruthy();
+    });
+
+    var tree;
+    it('should parse into a tree (async) 1', function (done) {
+      var info = matchClass.create(match).info();
+      expect(info).toBeTruthy();
+      info.getTree(undefined, undefined, function (treem) {
+	tree = treem;
+	done();
+      });
+    });
+
+    it('should parse into a tree (async) 2', function () {
+      expect(tree).toBeTruthy();
+      expect(tree.nodes()).toEqual(49);
+    });
 
 
-  var info, matchElement;
-  it('should parse into a tree view', function () {
-    matchElement = matchElementFactory();
-    expect(matchElement.tagName).toEqual('LI');
+    var info, matchElement;
+    it('should parse into a tree view', function () {
+      matchElement = matchElementFactory();
+      expect(matchElement.tagName).toEqual('LI');
 
-    info = KorAP.Match.create(matchElement).info();
-    info.toggle();
+      info = matchClass.create(matchElement).info();
+      info.toggle();
 
-    // Match
-    expect(matchElement.children[0].tagName).toEqual('DIV');
+      // Match
+      expect(matchElement.children[0].tagName).toEqual('DIV');
 
-    // snippet
-    expect(matchElement.children[0].children[0].tagName).toEqual('DIV');
-    expect(matchElement.children[0].children[0].classList.contains('snippet')).toBeTruthy();
-    expect(matchElement.children[0].children[0].firstChild.nodeValue).toEqual('check');
+      // snippet
+      expect(matchElement.children[0].children[0].tagName).toEqual('DIV');
+      expect(matchElement.children[0].children[0].classList.contains('snippet')).toBeTruthy();
+      expect(matchElement.children[0].children[0].firstChild.nodeValue).toEqual('check');
 
-    // reference
-    expect(matchElement.children[1].classList.contains('ref')).toBeTruthy();
-    expect(matchElement.children[1].firstChild.nodeValue).toEqual('me');
+      // reference
+      expect(matchElement.children[1].classList.contains('ref')).toBeTruthy();
+      expect(matchElement.children[1].firstChild.nodeValue).toEqual('me');
 
-    // now
-    var infotable = matchElement.children[0].children[1];
-    expect(infotable.tagName).toEqual('DIV');
-    expect(infotable.classList.contains('matchinfo')).toBeTruthy();
-    expect(infotable.children[0].classList.contains('matchtable')).toBeTruthy();
-    expect(infotable.children[1].classList.contains('addtree')).toBeTruthy();
-  });
+      // now
+      var infotable = matchElement.children[0].children[1];
+      expect(infotable.tagName).toEqual('DIV');
+      expect(infotable.classList.contains('matchinfo')).toBeTruthy();
+      expect(infotable.children[0].classList.contains('matchtable')).toBeTruthy();
+      expect(infotable.children[1].classList.contains('addtree')).toBeTruthy();
+    });
 
-  it('should add a tree view async 1', function (done) {
-    expect(info).toBeTruthy();
-    info.addTree('mate', 'beebop', function () {
-      done();
+    it('should add a tree view async 1', function (done) {
+      expect(info).toBeTruthy();
+      info.addTree('mate', 'beebop', function () {
+	done();
+      });
+    });
+
+    it('should add a tree view async 2', function () {
+      // With added tree
+      var infotable = matchElement.children[0].children[1];
+      expect(infotable.tagName).toEqual('DIV');
+      expect(infotable.classList.contains('matchinfo')).toBeTruthy();
+      expect(infotable.children[0].classList.contains('matchtable')).toBeTruthy();
+      expect(infotable.children[1].classList.contains('addtree')).toBe(false);
+
+      var tree = infotable.children[1];
+      expect(tree.tagName).toEqual('DIV');
+      expect(tree.classList.contains('matchtree')).toBeTruthy();
+      expect(tree.children[0].tagName).toEqual('H6');
+      expect(tree.children[0].children[0].tagName).toEqual('SPAN');
+      expect(tree.children[0].children[0].firstChild.nodeValue).toEqual('mate');
+      expect(tree.children[0].children[1].tagName).toEqual('SPAN');
+      expect(tree.children[0].children[1].firstChild.nodeValue).toEqual('beebop');
+
+      expect(tree.children[1].tagName).toEqual('DIV');
     });
   });
 
-  it('should add a tree view async 2', function () {
-    // With added tree
-    var infotable = matchElement.children[0].children[1];
-    expect(infotable.tagName).toEqual('DIV');
-    expect(infotable.classList.contains('matchinfo')).toBeTruthy();
-    expect(infotable.children[0].classList.contains('matchtable')).toBeTruthy();
-    expect(infotable.children[1].classList.contains('addtree')).toBe(false);
 
-    var tree = infotable.children[1];
-    expect(tree.tagName).toEqual('DIV');
-    expect(tree.classList.contains('matchtree')).toBeTruthy();
-    expect(tree.children[0].tagName).toEqual('H6');
-    expect(tree.children[0].children[0].tagName).toEqual('SPAN');
-    expect(tree.children[0].children[0].firstChild.nodeValue).toEqual('mate');
-    expect(tree.children[0].children[1].tagName).toEqual('SPAN');
-    expect(tree.children[0].children[1].firstChild.nodeValue).toEqual('beebop');
+  describe('KorAP.MatchTable', function () {
 
-    expect(tree.children[1].tagName).toEqual('DIV');
-  });
-});
+    var matchClass = require('match');
 
+    var table;
+    it('should be retrieved async', function (done) {
+      var info = matchClass.create(match).info();
+      expect(info).toBeTruthy();
+      info.getTable(undefined, function (x) {
+	table = x;
+	done();
+      });
+    });
 
-describe('KorAP.MatchTable', function () {
+    it('should be rendered async', function () {
+      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');
 
-  var table;
-  it('should be retrieved async', function (done) {
-    var info = KorAP.Match.create(match).info();
-    expect(info).toBeTruthy();
-    info.getTable(undefined, function (x) {
-      table = x;
-      done();
+      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');
+
+      // first row
+      tr = e.children[1].children[0];
+      expect(tr.nodeName).toBe('TR');
+      expect(tr.getAttribute('tabindex')).toEqual('0');
+      expect(tr.children[0].nodeName).toBe('TH');
+      expect(tr.children[0].firstChild.nodeValue).toEqual('cnx');
+      expect(tr.children[1].firstChild.nodeValue).toEqual('l');
+      expect(tr.children[2].firstChild.nodeValue).toEqual('meist');
+      expect(tr.children[3].firstChild.nodeValue).toEqual('deutlich');
+      expect(tr.children[4].firstChild.nodeValue).toEqual('fähig');
+      expect(tr.children[4].lastChild.nodeValue).toEqual('leistung');
+
+      // second row
+      tr = e.children[1].children[1];
+      expect(tr.nodeName).toBe('TR');
+      expect(tr.getAttribute('tabindex')).toEqual('0');
+      expect(tr.children[0].nodeName).toBe('TH');
+      expect(tr.children[0].firstChild.nodeValue).toEqual('cnx');
+      expect(tr.children[1].firstChild.nodeValue).toEqual('p');
+      expect(tr.children[2].firstChild.nodeValue).toEqual('ADV');
+      expect(tr.children[3].firstChild.nodeValue).toEqual('A');
+      expect(tr.children[4].firstChild.nodeValue).toEqual('A');
     });
   });
 
-  it('should be rendered async', function () {
-    var e = table.element();
+  describe('KorAP.MatchTree', function () {
+    var tree;
+    var matchClass = require('match');
 
-    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');
+    it('should be rendered async 1', function (done) {
+      var info = matchClass.create(match).info();
+      expect(info).toBeTruthy();
+      info.getTree(undefined, undefined, function (y) {
+	tree = y;
+	done();
+      });
+    });
 
-    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');
-
-    // first row
-    tr = e.children[1].children[0];
-    expect(tr.nodeName).toBe('TR');
-    expect(tr.getAttribute('tabindex')).toEqual('0');
-    expect(tr.children[0].nodeName).toBe('TH');
-    expect(tr.children[0].firstChild.nodeValue).toEqual('cnx');
-    expect(tr.children[1].firstChild.nodeValue).toEqual('l');
-    expect(tr.children[2].firstChild.nodeValue).toEqual('meist');
-    expect(tr.children[3].firstChild.nodeValue).toEqual('deutlich');
-    expect(tr.children[4].firstChild.nodeValue).toEqual('fähig');
-    expect(tr.children[4].lastChild.nodeValue).toEqual('leistung');
-
-    // second row
-    tr = e.children[1].children[1];
-    expect(tr.nodeName).toBe('TR');
-    expect(tr.getAttribute('tabindex')).toEqual('0');
-    expect(tr.children[0].nodeName).toBe('TH');
-    expect(tr.children[0].firstChild.nodeValue).toEqual('cnx');
-    expect(tr.children[1].firstChild.nodeValue).toEqual('p');
-    expect(tr.children[2].firstChild.nodeValue).toEqual('ADV');
-    expect(tr.children[3].firstChild.nodeValue).toEqual('A');
-    expect(tr.children[4].firstChild.nodeValue).toEqual('A');
-  });
-});
-
-describe('KorAP.MatchTree', function () {
-  var tree;
-
-  it('should be rendered async 1', function (done) {
-    var info = KorAP.Match.create(match).info();
-    expect(info).toBeTruthy();
-    info.getTree(undefined, undefined, function (y) {
-      tree = y;
-      done();
+    it('should be rendered async 2', function () {
+      var e = tree.element();
+      expect(e.nodeName).toEqual('svg');
+      expect(e.getElementsByTagName('g').length).toEqual(48);
     });
   });
 
-  it('should be rendered async 2', function () {
-    var e = tree.element();
-    expect(e.nodeName).toEqual('svg');
-    expect(e.getElementsByTagName('g').length).toEqual(48);
+
+  describe('KorAP.MatchTreeItem', function () {
+    var matchTreeItemClass = require('match/treeitem');
+    it('should be initializable', function () {
+      var mi = matchTreeItemClass.create(['cnx/c', 'cnx', 'c'])
+      expect(mi.element().firstChild.nodeValue).toEqual('cnx/c');
+      expect(mi.lcField()).toEqual(' cnx/c');
+      expect(mi.foundry()).toEqual('cnx');
+      expect(mi.layer()).toEqual('c');
+    });
   });
-});
 
 
-describe('KorAP.MatchTreeItem', function () {
-  it('should be initializable', function () {
-    var mi = KorAP.MatchTreeItem.create(['cnx/c', 'cnx', 'c'])
-    expect(mi.element().firstChild.nodeValue).toEqual('cnx/c');
-    expect(mi.lcField()).toEqual(' cnx/c');
-    expect(mi.foundry()).toEqual('cnx');
-    expect(mi.layer()).toEqual('c');
+  describe('KorAP.MatchTreeMenu', function () {
+    var matchTreeMenu = require('match/treemenu');
+    var matchTreeItem = require('match/treeitem');
+
+    it('should be initializable', function () {
+      var menu = matchTreeMenu.create(undefined, [
+	['cnx/c', 'cnx', 'c'],
+	['xip/c', 'xip', 'c']
+      ]);
+
+      expect(menu.itemClass()).toEqual(matchTreeItem);
+      expect(menu.element().nodeName).toEqual('UL');
+      expect(menu.element().style.opacity).toEqual("0");
+      expect(menu.limit()).toEqual(6);
+      menu.show();
+      expect(menu.item(0).active()).toBe(true);
+    });
   });
+
+  // table = view.toTable();
+  // table.sortBy('');
+  // table.element();
+  // tree = view.toTree();
+  // tree.element();
+
 });
-
-
-describe('KorAP.MatchTreeMenu', function () {
-  it('should be initializable', function () {
-    var menu = KorAP.MatchTreeMenu.create(undefined, [
-      ['cnx/c', 'cnx', 'c'],
-      ['xip/c', 'xip', 'c']
-    ]);
-
-    expect(menu.itemClass()).toEqual(KorAP.MatchTreeItem);
-    expect(menu.element().nodeName).toEqual('UL');
-    expect(menu.element().style.opacity).toEqual("0");
-    expect(menu.limit()).toEqual(6);
-    menu.show();
-    expect(menu.item(0).active()).toBe(true);
-  });
-});
-
-// table = view.toTable();
-// table.sortBy('');
-// table.element();
-// tree = view.toTree();
-// tree.element();
-
diff --git a/dev/js/spec/menuSpec.js b/dev/js/spec/menuSpec.js
index 6692753..7436e4d 100644
--- a/dev/js/spec/menuSpec.js
+++ b/dev/js/spec/menuSpec.js
@@ -1,1057 +1,1060 @@
-// The OwnMenu item
-KorAP.OwnMenuItem = {
-  create : function (params) {
-    return Object.create(KorAP.MenuItem).upgradeTo(KorAP.OwnMenuItem)._init(params);
-  },
-  content : function (content) {
-    if (arguments.length === 1) {
-      this._content = content;
-    };
-    return this._content;
-  },
-  _init : function (params) {
-    if (params[0] === undefined)
-      throw new Error("Missing parameters");
+define(['menu'], function () {
 
-    this._content = document.createTextNode(params[0]);
-    this._lcField = ' ' + this.content().textContent.toLowerCase();
+  var menuItemClass = require('menu/item');
+  var menuClass = require('menu');
 
-    return this;
-  }
-};
+  // The OwnMenu item
+  KorAP.OwnMenuItem = {
+    create : function (params) {
+      return Object.create(menuItemClass).upgradeTo(KorAP.OwnMenuItem)._init(params);
+    },
+    content : function (content) {
+      if (arguments.length === 1) {
+	this._content = content;
+      };
+      return this._content;
+    },
+    _init : function (params) {
+      if (params[0] === undefined)
+	throw new Error("Missing parameters");
+
+      this._content = document.createTextNode(params[0]);
+      this._lcField = ' ' + this.content().textContent.toLowerCase();
+
+      return this;
+    }
+  };
+
+  // The OwnMenu
+  KorAP.OwnMenu = {
+    create : function (params) {
+      return Object.create(menuClass)
+	.upgradeTo(KorAP.OwnMenu)
+	._init(KorAP.OwnMenuItem, undefined, params);
+    }
+  };
 
 
-// The OwnMenu
-KorAP.OwnMenu = {
-  create : function (params) {
-    return Object.create(KorAP.Menu)
-      .upgradeTo(KorAP.OwnMenu)
-      ._init(KorAP.OwnMenuItem, undefined, params);
-  }
-};
+  // HintMenuItem
+  KorAP.HintMenuItem = {
+    create : function (params) {
+      return Object.create(menuItemClass)
+	.upgradeTo(KorAP.HintMenuItem)
+	._init(params);
+    },
+    content : function (content) {
+      if (arguments.length === 1) {
+	this._content = content;
+      };
+      return this._content;
+    },
+    _init : function (params) {
+      if (params[0] === undefined || params[1] === undefined)
+	throw new Error("Missing parameters");
+
+      this._name   = params[0];
+      this._action = params[1];
+      this._lcField = ' ' + this._name.toLowerCase();
+
+      if (params.length > 2) {
+	this._desc = params[2];
+	this._lcField += " " + this._desc.toLowerCase();
+      };
+
+      return this;
+    },
+
+    name : function () {
+      return this._name;
+    },
+    action : function () {
+      return this._action;
+    },
+    desc : function () {
+      return this._desc;
+    },
+    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);
+
+      // Create title
+      var name =  document.createElement("strong");
+      name.appendChild(document.createTextNode(this._name));
+      
+      li.appendChild(name);
+
+      // Create description
+      if (this._desc !== undefined) {
+	var desc = document.createElement("span");
+	desc.appendChild(document.createTextNode(this._desc));
+	li.appendChild(desc);
+      };
+      return this._element = li;
+    }
+  };
 
 
-// HintMenuItem
-KorAP.HintMenuItem = {
-  create : function (params) {
-   return Object.create(KorAP.MenuItem)
-      .upgradeTo(KorAP.HintMenuItem)
-      ._init(params);
-  },
-  content : function (content) {
-    if (arguments.length === 1) {
-      this._content = content;
-    };
-    return this._content;
-  },
-  _init : function (params) {
-    if (params[0] === undefined || params[1] === undefined)
-      throw new Error("Missing parameters");
-
-    this._name   = params[0];
-    this._action = params[1];
-    this._lcField = ' ' + this._name.toLowerCase();
-
-    if (params.length > 2) {
-      this._desc = params[2];
-      this._lcField += " " + this._desc.toLowerCase();
-    };
-
-    return this;
-  },
-  name : function () {
-    return this._name;
-  },
-  action : function () {
-    return this._action;
-  },
-  desc : function () {
-    return this._desc;
-  },
-  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);
-
-    // Create title
-    var name =  document.createElement("strong");
-    name.appendChild(document.createTextNode(this._name));
-    
-    li.appendChild(name);
-
-    // Create description
-    if (this._desc !== undefined) {
-      var desc = document.createElement("span");
-      desc.appendChild(document.createTextNode(this._desc));
-      li.appendChild(desc);
-    };
-    return this._element = li;
-  }
-};
+  // HintMenu
+  KorAP.HintMenu = {
+    create : function (context, params) {
+      var obj = Object.create(menuClass)
+	.upgradeTo(KorAP.HintMenu)
+	._init(KorAP.HintMenuItem, undefined, params);
+      obj._context = context;
+      return obj;
+    }
+  };
 
 
-// HintMenu
-KorAP.HintMenu = {
-  create : function (context, params) {
-    var obj = Object.create(KorAP.Menu)
-      .upgradeTo(KorAP.HintMenu)
-      ._init(KorAP.HintMenuItem, undefined, params);
-    obj._context = context;
-    return obj;
-  }
-};
+  // The ComplexMenuItem
+  KorAP.ComplexMenuItem = {
+    create : function (params) {
+      return Object.create(menuItemClass)
+	.upgradeTo(KorAP.ComplexMenuItem)
+	._init(params);
+    },
+    content : function (content) {
+      if (arguments.length === 1) {
+	this._content = content;
+      };
+      return this._content;
+    },
+    _init : function (params) {
+      if (params[0] === undefined)
+	throw new Error("Missing parameters");
+
+      var r = document.createElement('div');
+      for (var i = 1; i <= params.length; i++) {
+	var h = document.createElement('h' + i);
+	h.appendChild(document.createTextNode(params[i-1]));
+	r.appendChild(h);
+      };
+
+      this._content = r;
+      this._lcField = ' ' + this.content().textContent.toLowerCase();
+
+      return this;
+    }
+  };
 
 
-// The ComplexMenuItem
-KorAP.ComplexMenuItem = {
-  create : function (params) {
-    return Object.create(KorAP.MenuItem)
-      .upgradeTo(KorAP.ComplexMenuItem)
-      ._init(params);
-  },
-  content : function (content) {
-    if (arguments.length === 1) {
-      this._content = content;
-    };
-    return this._content;
-  },
-  _init : function (params) {
-    if (params[0] === undefined)
-      throw new Error("Missing parameters");
+  describe('KorAP.MenuItem', function () {
+    it('should be initializable', function () {
+      expect(
+	function() { menuItemClass.create([]) }
+      ).toThrow(new Error("Missing parameters"));
 
-    var r = document.createElement('div');
-    for (var i = 1; i <= params.length; i++) {
-      var h = document.createElement('h' + i);
-      h.appendChild(document.createTextNode(params[i-1]));
-      r.appendChild(h);
-    };
+      expect(
+	function() { KorAP.OwnMenuItem.create([]) }
+      ).toThrow(new Error("Missing parameters"));
 
-    this._content = r;
-    this._lcField = ' ' + this.content().textContent.toLowerCase();
+      var mi = KorAP.OwnMenuItem.create(["Baum"]);
+      expect(mi.element().firstChild.nodeValue).toEqual('Baum');
+      expect(mi.lcField()).toEqual(' baum');
+    });
 
-    return this;
-  }
-};
+    it('shouldn\'t have a reference to the menu', function () {
+      var menuItem = KorAP.OwnMenuItem.create(['Test']);
+      expect(menuItem.menu()).toBe(undefined);
+    });
+
+    it('should be activatable and deactivateable by class', function () {
+      var menuItem = KorAP.OwnMenuItem.create(['Test']);
+
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toBe(null);
+      menuItem.active(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("active");
+      menuItem.active(false); // Is active
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toEqual("");
+      menuItem.active(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("active");
+
+      menuItem = KorAP.OwnMenuItem.create(['Spiegel']);
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toBe(null);
+      menuItem.active(false); // Is not active
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toBe(null);
+    });
+
+    it('should be set to boundary', function () {
+      var menuItem = KorAP.OwnMenuItem.create(['CoreNLP']);
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toBe(null);
+
+      // Set active
+      menuItem.active(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.noMore()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toEqual("active");
+
+      // Set no more
+      menuItem.noMore(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.noMore()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("active no-more");
+
+      // No no more
+      menuItem.noMore(false);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.noMore()).toBe(false);
+      expect(menuItem.element().getAttribute("class")).toEqual("active");
+
+      // Set no more, deactivate
+      menuItem.noMore(true);
+      menuItem.active(false);
+      expect(menuItem.active()).toBe(false);
+      expect(menuItem.noMore()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("no-more");
+
+      // Set active
+      menuItem.active(true);
+      expect(menuItem.active()).toBe(true);
+      expect(menuItem.noMore()).toBe(true);
+      expect(menuItem.element().getAttribute("class")).toEqual("no-more active");
+    });
 
 
+    it('should be highlightable', function () {
+      // Highlight in the middle
+      var menuItem = KorAP.OwnMenuItem.create(['CoreNLP']);
+      menuItem.highlight("ren");
+      expect(menuItem.element().innerHTML).toEqual("Co<mark>reN</mark>LP");
 
-describe('KorAP.MenuItem', function () {
-  it('should be initializable', function () {
-    expect(
-      function() { KorAP.MenuItem.create([]) }
-    ).toThrow(new Error("Missing parameters"));
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual("CoreNLP");
 
-    expect(
-      function() { KorAP.OwnMenuItem.create([]) }
-    ).toThrow(new Error("Missing parameters"));
+      var plain = "<div><h1>CoreNLP</h1><h2>corenlp/</h2></div>";
 
-    var mi = KorAP.OwnMenuItem.create(["Baum"]);
-    expect(mi.element().firstChild.nodeValue).toEqual('Baum');
-    expect(mi.lcField()).toEqual(' baum');
-  });
+      // Starting highlight
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("cor");
+      expect(menuItem.element().innerHTML).toEqual("<div><h1><mark>Cor</mark>eNLP</h1><h2><mark>cor</mark>enlp/</h2></div>");
 
-  it('shouldn\'t have a reference to the menu', function () {
-    var menuItem = KorAP.OwnMenuItem.create(['Test']);
-    expect(menuItem.menu()).toBe(undefined);
-  });
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
 
-  it('should be activatable and deactivateable by class', function () {
-    var menuItem = KorAP.OwnMenuItem.create(['Test']);
+      // Starting highlight - short
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("c");
+      expect(menuItem.element().innerHTML).toEqual("<div><h1><mark>C</mark>oreNLP</h1><h2><mark>c</mark>orenlp/</h2></div>");
 
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toBe(null);
-    menuItem.active(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("active");
-    menuItem.active(false); // Is active
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toEqual("");
-    menuItem.active(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("active");
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
 
-    menuItem = KorAP.OwnMenuItem.create(['Spiegel']);
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toBe(null);
-    menuItem.active(false); // Is not active
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toBe(null);
-  });
+      // Highlight at the end
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("nlp");
+      expect(menuItem.element().innerHTML).toEqual("<div><h1>Core<mark>NLP</mark></h1><h2>core<mark>nlp</mark>/</h2></div>");
 
-  it('should be set to boundary', function () {
-    var menuItem = KorAP.OwnMenuItem.create(['CoreNLP']);
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toBe(null);
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
 
-    // Set active
-    menuItem.active(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.noMore()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toEqual("active");
+      // Highlight at the end - short
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("p");
+      expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNL<mark>P</mark></h1><h2>corenl<mark>p</mark>/</h2></div>");
 
-    // Set no more
-    menuItem.noMore(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.noMore()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("active no-more");
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
 
-    // No no more
-    menuItem.noMore(false);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.noMore()).toBe(false);
-    expect(menuItem.element().getAttribute("class")).toEqual("active");
+      // No highlight
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+      menuItem.highlight("xp");
+      expect(menuItem.element().innerHTML).toEqual(plain);
 
-    // Set no more, deactivate
-    menuItem.noMore(true);
-    menuItem.active(false);
-    expect(menuItem.active()).toBe(false);
-    expect(menuItem.noMore()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("no-more");
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
 
-    // Set active
-    menuItem.active(true);
-    expect(menuItem.active()).toBe(true);
-    expect(menuItem.noMore()).toBe(true);
-    expect(menuItem.element().getAttribute("class")).toEqual("no-more active");
+      // Highlight in the middle - first
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+      menuItem.highlight("ren");
+      expect(menuItem.element().innerHTML).toEqual("<div><h1>Co<mark>reN</mark>LP</h1><h2>co<mark>ren</mark>lp/</h2><h3>This is my Example</h3></div>");
+
+      plain = "<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3>This is my Example</h3></div>"
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
+
+      // Highlight in the middle - second
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+      menuItem.highlight("ampl");
+      expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3>This is my Ex<mark>ampl</mark>e</h3></div>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
+
+      // Highlight in the middle - both
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+      menuItem.highlight("e");
+      expect(menuItem.element().innerHTML).toEqual("<div><h1>Cor<mark>e</mark>NLP</h1><h2>cor<mark>e</mark>nlp/</h2><h3>This is my <mark>E</mark>xampl<mark>e</mark></h3></div>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
+
+      // Highlight in the end - second
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+      menuItem.highlight("le");
+      expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3>This is my Examp<mark>le</mark></h3></div>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
+
+      // Highlight at the beginning - second
+      menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+      menuItem.highlight("this");
+      expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3><mark>This</mark> is my Example</h3></div>");
+
+      menuItem.lowlight();
+      expect(menuItem.element().innerHTML).toEqual(plain);
+    });
   });
 
 
-  it('should be highlightable', function () {
-    // Highlight in the middle
-    var menuItem = KorAP.OwnMenuItem.create(['CoreNLP']);
-    menuItem.highlight("ren");
-    expect(menuItem.element().innerHTML).toEqual("Co<mark>reN</mark>LP");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual("CoreNLP");
-
-    var plain = "<div><h1>CoreNLP</h1><h2>corenlp/</h2></div>";
-
-    // Starting highlight
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("cor");
-    expect(menuItem.element().innerHTML).toEqual("<div><h1><mark>Cor</mark>eNLP</h1><h2><mark>cor</mark>enlp/</h2></div>");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    // Starting highlight - short
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("c");
-    expect(menuItem.element().innerHTML).toEqual("<div><h1><mark>C</mark>oreNLP</h1><h2><mark>c</mark>orenlp/</h2></div>");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    // Highlight at the end
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("nlp");
-    expect(menuItem.element().innerHTML).toEqual("<div><h1>Core<mark>NLP</mark></h1><h2>core<mark>nlp</mark>/</h2></div>");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    // Highlight at the end - short
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("p");
-    expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNL<mark>P</mark></h1><h2>corenl<mark>p</mark>/</h2></div>");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    // No highlight
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
-    menuItem.highlight("xp");
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    // Highlight in the middle - first
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
-    menuItem.highlight("ren");
-    expect(menuItem.element().innerHTML).toEqual("<div><h1>Co<mark>reN</mark>LP</h1><h2>co<mark>ren</mark>lp/</h2><h3>This is my Example</h3></div>");
-
-    plain = "<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3>This is my Example</h3></div>"
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    // Highlight in the middle - second
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
-    menuItem.highlight("ampl");
-    expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3>This is my Ex<mark>ampl</mark>e</h3></div>");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    // Highlight in the middle - both
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
-    menuItem.highlight("e");
-    expect(menuItem.element().innerHTML).toEqual("<div><h1>Cor<mark>e</mark>NLP</h1><h2>cor<mark>e</mark>nlp/</h2><h3>This is my <mark>E</mark>xampl<mark>e</mark></h3></div>");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    // Highlight in the end - second
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
-    menuItem.highlight("le");
-    expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3>This is my Examp<mark>le</mark></h3></div>");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-
-    // Highlight at the beginning - second
-    menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
-    menuItem.highlight("this");
-    expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3><mark>This</mark> is my Example</h3></div>");
-
-    menuItem.lowlight();
-    expect(menuItem.element().innerHTML).toEqual(plain);
-  });
-});
-
-
-describe('KorAP.Menu', function () {
-  var list = [
-    ["Constituency", "c=", "Example 1"],
-    ["Lemma", "l="],
-    ["Morphology", "m=", "Example 2"],
-    ["Part-of-Speech", "p="],
-    ["Syntax", "syn="]
-  ];
-
-  var demolist = [
-    ['Titel', 'title'],
-    ['Untertitel', 'subTitle'],
-    ['Veröffentlichungsdatum', 'pubDate'],
-    ['Länge', 'length'],
-    ['Autor', 'author']
-  ];
-
-  var demolonglist = [
-    ['Titel', 'title'],
-    ['Untertitel', 'subTitle'],
-    ['Veröffentlichungsdatum', 'pubDate'],
-    ['Länge', 'length'],
-    ['Autor', 'author'],
-    ['Genre', 'genre'],
-    ['corpusID', 'corpusID'],
-    ['docID', 'docID'],
-    ['textID', 'textID'],
-  ];
-
-  it('should be initializable', function () {
+  describe('KorAP.Menu', function () {
     var list = [
-      ["Constituency"],
-      ["Lemma"],
-      ["Morphology"],
-      ["Part-of-Speech"],
-      ["Syntax"]
+      ["Constituency", "c=", "Example 1"],
+      ["Lemma", "l="],
+      ["Morphology", "m=", "Example 2"],
+      ["Part-of-Speech", "p="],
+      ["Syntax", "syn="]
     ];
 
-    var menu = KorAP.OwnMenu.create(list);
-    expect(menu.itemClass()).toEqual(KorAP.OwnMenuItem);
-    expect(menu.element().nodeName).toEqual('UL');
-    expect(menu.element().style.opacity).toEqual("0");
-    expect(menu.limit()).toEqual(8);
+    var demolist = [
+      ['Titel', 'title'],
+      ['Untertitel', 'subTitle'],
+      ['Veröffentlichungsdatum', 'pubDate'],
+      ['Länge', 'length'],
+      ['Autor', 'author']
+    ];
 
-    menu.limit(9);
-    expect(menu.limit()).toEqual(9);
+    var demolonglist = [
+      ['Titel', 'title'],
+      ['Untertitel', 'subTitle'],
+      ['Veröffentlichungsdatum', 'pubDate'],
+      ['Länge', 'length'],
+      ['Autor', 'author'],
+      ['Genre', 'genre'],
+      ['corpusID', 'corpusID'],
+      ['docID', 'docID'],
+      ['textID', 'textID'],
+    ];
 
-    menu.limit(8);
+    it('should be initializable', function () {
+      var list = [
+	["Constituency"],
+	["Lemma"],
+	["Morphology"],
+	["Part-of-Speech"],
+	["Syntax"]
+      ];
 
-    // view
-    menu.show();
+      var menu = KorAP.OwnMenu.create(list);
+      expect(menu.itemClass()).toEqual(KorAP.OwnMenuItem);
+      expect(menu.element().nodeName).toEqual('UL');
+      expect(menu.element().style.opacity).toEqual("0");
+      expect(menu.limit()).toEqual(8);
 
-    // First element in list
-    expect(menu.item(0).active()).toBe(true);
-    expect(menu.item(0).noMore()).toBe(true);
+      menu.limit(9);
+      expect(menu.limit()).toEqual(9);
 
-    // Middle element in list
-    expect(menu.item(2).active()).toBe(false);
-    expect(menu.item(2).noMore()).toBe(false);
+      menu.limit(8);
 
-    // Last element in list
-    expect(menu.item(menu.length() - 1).active()).toBe(false);
-    expect(menu.item(menu.length() - 1).noMore()).toBe(true);
+      // view
+      menu.show();
+
+      // First element in list
+      expect(menu.item(0).active()).toBe(true);
+      expect(menu.item(0).noMore()).toBe(true);
+
+      // Middle element in list
+      expect(menu.item(2).active()).toBe(false);
+      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 have a reference to the menu', function () {
+      var menu = KorAP.HintMenu.create("cnx/", list);
+      expect(menu.item(0).menu()).toEqual(menu);
+
+      menu = KorAP.HintMenu.create("cnx/", list);
+      expect(menu.element().menu).toEqual(menu);
+    });
+
+
+    it('should be visible', function () {
+      var menu = KorAP.HintMenu.create("cnx/", list);
+      expect(menu.delete()).toBe(undefined);
+      menu.limit(3);
+
+      expect(menu.show()).toBe(true);
+
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
+      expect(menu.element().childNodes[2].getAttribute("data-action")).toEqual("l=");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Check boundaries
+      expect(menu.element().childNodes[1].classList.contains("no-more")).toBe(true);
+      expect(menu.element().childNodes[2].classList.contains("no-more")).toBe(false);
+      expect(menu.element().childNodes[3].classList.contains("no-more")).toBe(false);
+    });
+
+    it('should be filterable', function () {
+      var menu = KorAP.HintMenu.create("cnx/", list);
+      menu.limit(3);
+      expect(menu.prefix("o").show()).toBe(true);
+      expect(menu.element().childNodes[0].innerHTML).toEqual("o");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</strong><span>Example 2</span>");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Part-<mark>o</mark>f-Speech</strong>");
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Check boundaries
+      expect(menu.element().childNodes[1].classList.contains("no-more")).toBe(true);
+      expect(menu.element().childNodes[2].classList.contains("no-more")).toBe(false);
+      expect(menu.element().childNodes[3].classList.contains("no-more")).toBe(true);
+
+      menu.limit(2);
+
+      expect(menu.prefix("o").show()).toBe(true);
+      expect(menu.element().childNodes[0].innerHTML).toEqual("o");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</strong><span>Example 2</span>");
+      expect(menu.element().childNodes[3]).toBe(undefined);
+
+      // Check boundaries
+      expect(menu.element().childNodes[1].classList.contains("no-more")).toBe(true);
+      expect(menu.element().childNodes[2].classList.contains("no-more")).toBe(false);
+      expect(menu.element().childNodes[3]).toBe(undefined);
+
+      expect(menu.prefix("e").show()).toBe(true);
+      expect(menu.element().childNodes[0].innerHTML).toEqual("e");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
+      expect(menu.element().childNodes[3]).toBe(undefined);
+
+      menu.limit(5);
+      expect(menu.prefix("a").show()).toBe(true);
+      expect(menu.element().childNodes[0].innerHTML).toEqual("a");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Ex<mark>a</mark>mple 1</span>");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemm<mark>a</mark></strong>");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Ex<mark>a</mark>mple 2</span>");
+      expect(menu.element().childNodes[4].innerHTML).toEqual("<strong>P<mark>a</mark>rt-of-Speech</strong>");
+      expect(menu.element().childNodes[5].innerHTML).toEqual("<strong>Synt<mark>a</mark>x</strong>");
+      expect(menu.element().childNodes[6]).toBe(undefined);
+    });
+
+
+    it('should be nextable', function () {
+      var menu = KorAP.HintMenu.create("cnx/", list);
+
+      // Show only 3 items
+      menu.limit(3);
+      expect(menu.show()).toBe(true);
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(2).active()).toBe(false);
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Activate next (1)
+      menu.next();
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(2).active()).toBe(false);
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Activate next (2)
+      menu.next();
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(2).active()).toBe(true);
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Activate next (3)
+      // scroll!
+      menu.next();
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
+      expect(menu.shownItem(2).active()).toBe(true);
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Activate next (4)
+      menu.next();
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Syntax</strong>");
+      expect(menu.shownItem(2).active()).toBe(true);
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Activate next (5) - ROLL
+      menu.next();
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(2).active()).toBe(false);
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Active next (6)
+      menu.next();
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(2).active()).toBe(false);
+      expect(menu.element().childNodes[4]).toBe(undefined);
+    });
+
+    it('should be prevable', function () {
+      var menu = KorAP.HintMenu.create("cnx/", list);
+      menu.limit(3);
+      expect(menu.show()).toBe(true);
+
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(2).active()).toBe(false);
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Activate prev (1) - roll to bottom
+      menu.prev();
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Syntax</strong>");
+      expect(menu.shownItem(2).active()).toBe(true);
+      expect(menu.element().childNodes[4]).toBe(undefined);
+
+      // Activate prev (2)
+      menu.prev();
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Syntax</strong>");
+      expect(menu.shownItem(2).active()).toBe(false);
+      expect(menu.element().childNodes[4]).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[4]).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[4]).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[4]).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[4]).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[4]).toBe(undefined);
+    });
+
+
+    it('should be navigatable and filterable (prefix = "o")', function () {
+      var menu = KorAP.HintMenu.create("cnx/", list);
+      menu.limit(2);
+
+      expect(menu.prefix("o").show()).toBe(true);
+      expect(menu.shownItem(0).name()).toEqual("Constituency");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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[1].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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[2].innerHTML).toEqual("<strong>Part-<mark>o</mark>f-Speech</strong>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Next (3) - to prefix
+      menu.next();
+      expect(menu.shownItem(0).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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[2].innerHTML).toEqual("<strong>Part-<mark>o</mark>f-Speech</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      menu.next();
+      expect(menu.shownItem(0).name()).toEqual("Constituency");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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.HintMenu.create("cnx/", list);
+
+      menu.limit(2);
+      expect(menu.prefix("ex").show()).toBe(true);
+
+      expect(menu.shownItem(0).name()).toEqual("Constituency");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span><mark>Ex</mark>ample 1</span>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>Ex</mark>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[1].innerHTML).toEqual("<strong>Constituency</strong><span><mark>Ex</mark>ample 1</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>Ex</mark>ample 2</span>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Next (2)
+      menu.next();
+
+      expect(menu.prefix()).toEqual('ex');
+      expect(menu.shownItem(0).name()).toEqual("Constituency");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span><mark>Ex</mark>ample 1</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>Ex</mark>ample 2</span>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Reset limit
+      menu.limit(5);
+
+      // Change show
+      expect(menu.prefix("e").show()).toBe(true);
+      expect(menu._prefix.active()).toBe(false);
+      expect(menu.shownItem(0).name()).toEqual("Constituency");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Next (1)
+      menu.next();
+      expect(menu._prefix.active()).toBe(false);
+      expect(menu.prefix()).toEqual('e');
+      expect(menu.shownItem(0).name()).toEqual("Constituency");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Next (2)
+      menu.next();
+      expect(menu._prefix.active()).toBe(true);
+      expect(menu.shownItem(0).name()).toEqual("Constituency");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Next (3)
+      menu.next();
+      expect(menu._prefix.active()).toBe(false);
+      expect(menu.shownItem(0).name()).toEqual("Constituency");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Morphology");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+    });
+
+
+    it('shouldn\'t be viewable with failing prefix', function () {
+      var menu = KorAP.HintMenu.create("cnx/", list);
+      menu.limit(2);
+      expect(menu.prefix("exit").show()).toBe(false);    
+    });
+
+    it('should be navigatable with prefix', function () {
+      var menu = KorAP.HintMenu.create("cnx/", demolist);
+      menu.limit(3);
+
+      expect(menu.show()).toBe(true);
+      expect(menu.prefix()).toEqual("");
+
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
+      expect(menu.shownItem(2).active()).toBe(false);
+      expect(menu.shownItem(3)).toBe(undefined);
+
+      menu._prefix.add('a');
+      expect(menu.show()).toBe(true);
+      expect(menu.prefix()).toEqual("a");
+      expect(menu.shownItem(0).name()).toEqual("Autor");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong><mark>A</mark>utor</strong>");
+
+      menu._prefix.add('u');
+      expect(menu.show()).toBe(true);
+      expect(menu.prefix()).toEqual("au");
+      expect(menu.shownItem(0).name()).toEqual("Autor");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong><mark>Au</mark>tor</strong>");
+
+      menu._prefix.backspace();
+      expect(menu.show()).toBe(true);
+      expect(menu.prefix()).toEqual("a");
+      expect(menu.shownItem(0).name()).toEqual("Autor");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong><mark>A</mark>utor</strong>");
+
+      menu._prefix.backspace();
+      expect(menu.show()).toBe(true);
+      expect(menu.prefix()).toEqual("");
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
+      expect(menu.shownItem(2).active()).toBe(false);
+      expect(menu.shownItem(3)).toBe(undefined);
+
+      // Forward
+      menu._prefix.backspace();
+      expect(menu.show()).toBe(true);
+      expect(menu.prefix()).toEqual("");
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
+      expect(menu.shownItem(2).active()).toBe(false);
+
+      // Forward
+      menu.next();
+      expect(menu.prefix()).toEqual("");
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
+      expect(menu.shownItem(2).active()).toBe(false);
+      expect(menu.shownItem(3)).toBe(undefined);
+
+      // Forward
+      menu.next();
+      expect(menu.prefix()).toEqual("");
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
+      expect(menu.shownItem(2).active()).toBe(true);
+      expect(menu.shownItem(3)).toBe(undefined);
+
+      // Forward
+      menu.next();
+      expect(menu.prefix()).toEqual("");
+      expect(menu.shownItem(0).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Untertitel</strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Veröffentlichungsdatum");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2).name()).toEqual("Länge");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Länge</strong>");
+      expect(menu.shownItem(2).active()).toBe(true);
+      expect(menu.shownItem(3)).toBe(undefined);
+
+      // Forward
+      menu.next();
+      expect(menu.prefix()).toEqual("");
+      expect(menu.shownItem(0).name()).toEqual("Veröffentlichungsdatum");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Länge");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Länge</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2).name()).toEqual("Autor");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Autor</strong>");
+      expect(menu.shownItem(2).active()).toBe(true);
+      expect(menu.shownItem(3)).toBe(undefined);
+
+      // Forward
+      menu.next();
+      expect(menu.prefix()).toEqual("");
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
+      expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
+      expect(menu.shownItem(2).active()).toBe(false);
+    });
+
+
+    it('should be navigatable with a prefix (1)', function () {
+      var menu = KorAP.HintMenu.create("cnx/", demolist);
+      menu.limit(3);
+
+      expect(menu.show()).toBe(true);
+      expect(menu.prefix()).toEqual("");
+
+      menu.prefix('el');
+      expect(menu.show()).toBe(true);
+
+      expect(menu.prefix()).toEqual("el");
+      expect(menu._prefix.active()).toEqual(false);
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Forward
+      menu.next();
+      expect(menu.prefix()).toEqual("el");
+      expect(menu._prefix.active()).toEqual(false);
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Forward
+      menu.next();
+      expect(menu.prefix()).toEqual("el");
+      expect(menu._prefix.active()).toEqual(true);
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Backward
+      menu.prev();
+      expect(menu.prefix()).toEqual("el");
+      expect(menu._prefix.active()).toEqual(false);
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.shownItem(2)).toBe(undefined);
+    });
+
+
+    it('should be navigatable with a prefix (2)', function () {
+      var menu = KorAP.HintMenu.create("cnx/", demolist);
+      menu.limit(3);
+      expect(menu.show()).toBe(true);
+      expect(menu.prefix()).toEqual("");
+      menu.prefix('el');
+      expect(menu.show()).toBe(true);
+
+      expect(menu.prefix()).toEqual("el");
+      expect(menu._prefix.active()).toEqual(false);
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Backward
+      menu.prev();
+      expect(menu._prefix.active()).toEqual(true);
+
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Backward
+      menu.prev();
+      expect(menu._prefix.active()).toEqual(false);
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(true);
+      expect(menu.shownItem(2)).toBe(undefined);
+    });
+
+    it('should be navigatable with a prefix (3)', function () {
+      var menu = KorAP.HintMenu.create("cnx/", demolist);
+      menu.limit(3);
+      expect(menu.show()).toBe(true);
+      expect(menu.prefix()).toEqual("");
+      menu.prefix('el');
+      expect(menu.show()).toBe(true);
+
+      expect(menu.prefix()).toEqual("el");
+      expect(menu._prefix.active()).toEqual(false);
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+      // Backward
+      menu.prev();
+      expect(menu._prefix.active()).toEqual(true);
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(false);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+
+      // Forward
+      menu.next();
+      expect(menu.prefix()).toEqual("el");
+      expect(menu._prefix.active()).toEqual(false);
+      expect(menu.shownItem(0).name()).toEqual("Titel");
+      expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
+      expect(menu.shownItem(0).active()).toBe(true);
+      expect(menu.shownItem(1).name()).toEqual("Untertitel");
+      expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
+      expect(menu.shownItem(1).active()).toBe(false);
+      expect(menu.shownItem(2)).toBe(undefined);
+
+    });
+
+    xit('should be page downable');
+    xit('should be page upable');
+
+    xit('should scroll to a chosen value')
+    xit('should highlight a chosen value')
   });
-
-  it('should have a reference to the menu', function () {
-    var menu = KorAP.HintMenu.create("cnx/", list);
-    expect(menu.item(0).menu()).toEqual(menu);
-
-    menu = KorAP.HintMenu.create("cnx/", list);
-    expect(menu.element().menu).toEqual(menu);
-  });
-
-
-  it('should be visible', function () {
-    var menu = KorAP.HintMenu.create("cnx/", list);
-    expect(menu.delete()).toBe(undefined);
-    menu.limit(3);
-
-    expect(menu.show()).toBe(true);
-
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.element().childNodes[2].getAttribute("data-action")).toEqual("l=");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Check boundaries
-    expect(menu.element().childNodes[1].classList.contains("no-more")).toBe(true);
-    expect(menu.element().childNodes[2].classList.contains("no-more")).toBe(false);
-    expect(menu.element().childNodes[3].classList.contains("no-more")).toBe(false);
-  });
-
-  it('should be filterable', function () {
-    var menu = KorAP.HintMenu.create("cnx/", list);
-    menu.limit(3);
-    expect(menu.prefix("o").show()).toBe(true);
-    expect(menu.element().childNodes[0].innerHTML).toEqual("o");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</strong><span>Example 2</span>");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Part-<mark>o</mark>f-Speech</strong>");
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Check boundaries
-    expect(menu.element().childNodes[1].classList.contains("no-more")).toBe(true);
-    expect(menu.element().childNodes[2].classList.contains("no-more")).toBe(false);
-    expect(menu.element().childNodes[3].classList.contains("no-more")).toBe(true);
-
-    menu.limit(2);
-
-    expect(menu.prefix("o").show()).toBe(true);
-    expect(menu.element().childNodes[0].innerHTML).toEqual("o");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</strong><span>Example 2</span>");
-    expect(menu.element().childNodes[3]).toBe(undefined);
-
-    // Check boundaries
-    expect(menu.element().childNodes[1].classList.contains("no-more")).toBe(true);
-    expect(menu.element().childNodes[2].classList.contains("no-more")).toBe(false);
-    expect(menu.element().childNodes[3]).toBe(undefined);
-
-    expect(menu.prefix("e").show()).toBe(true);
-    expect(menu.element().childNodes[0].innerHTML).toEqual("e");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
-    expect(menu.element().childNodes[3]).toBe(undefined);
-
-    menu.limit(5);
-    expect(menu.prefix("a").show()).toBe(true);
-    expect(menu.element().childNodes[0].innerHTML).toEqual("a");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Ex<mark>a</mark>mple 1</span>");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemm<mark>a</mark></strong>");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Ex<mark>a</mark>mple 2</span>");
-    expect(menu.element().childNodes[4].innerHTML).toEqual("<strong>P<mark>a</mark>rt-of-Speech</strong>");
-    expect(menu.element().childNodes[5].innerHTML).toEqual("<strong>Synt<mark>a</mark>x</strong>");
-    expect(menu.element().childNodes[6]).toBe(undefined);
-  });
-
-
-  it('should be nextable', function () {
-    var menu = KorAP.HintMenu.create("cnx/", list);
-
-    // Show only 3 items
-    menu.limit(3);
-    expect(menu.show()).toBe(true);
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Activate next (1)
-    menu.next();
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Activate next (2)
-    menu.next();
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Activate next (3)
-    // scroll!
-    menu.next();
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Activate next (4)
-    menu.next();
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Syntax</strong>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Activate next (5) - ROLL
-    menu.next();
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Active next (6)
-    menu.next();
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element().childNodes[4]).toBe(undefined);
-  });
-
-  it('should be prevable', function () {
-    var menu = KorAP.HintMenu.create("cnx/", list);
-    menu.limit(3);
-    expect(menu.show()).toBe(true);
-
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Lemma</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Activate prev (1) - roll to bottom
-    menu.prev();
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Syntax</strong>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.element().childNodes[4]).toBe(undefined);
-
-    // Activate prev (2)
-    menu.prev();
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Syntax</strong>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.element().childNodes[4]).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[4]).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[4]).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[4]).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[4]).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[4]).toBe(undefined);
-  });
-
-
-  it('should be navigatable and filterable (prefix = "o")', function () {
-    var menu = KorAP.HintMenu.create("cnx/", list);
-    menu.limit(2);
-
-    expect(menu.prefix("o").show()).toBe(true);
-    expect(menu.shownItem(0).name()).toEqual("Constituency");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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[1].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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[2].innerHTML).toEqual("<strong>Part-<mark>o</mark>f-Speech</strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (3) - to prefix
-    menu.next();
-    expect(menu.shownItem(0).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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[2].innerHTML).toEqual("<strong>Part-<mark>o</mark>f-Speech</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    menu.next();
-    expect(menu.shownItem(0).name()).toEqual("Constituency");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>C<mark>o</mark>nstituency</strong><span>Example 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>M<mark>o</mark>rph<mark>o</mark>l<mark>o</mark>gy</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.HintMenu.create("cnx/", list);
-
-    menu.limit(2);
-    expect(menu.prefix("ex").show()).toBe(true);
-
-    expect(menu.shownItem(0).name()).toEqual("Constituency");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span><mark>Ex</mark>ample 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>Ex</mark>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[1].innerHTML).toEqual("<strong>Constituency</strong><span><mark>Ex</mark>ample 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>Ex</mark>ample 2</span>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (2)
-    menu.next();
-
-    expect(menu.prefix()).toEqual('ex');
-    expect(menu.shownItem(0).name()).toEqual("Constituency");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constituency</strong><span><mark>Ex</mark>ample 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>Ex</mark>ample 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Reset limit
-    menu.limit(5);
-
-    // Change show
-    expect(menu.prefix("e").show()).toBe(true);
-    expect(menu._prefix.active()).toBe(false);
-    expect(menu.shownItem(0).name()).toEqual("Constituency");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (1)
-    menu.next();
-    expect(menu._prefix.active()).toBe(false);
-    expect(menu.prefix()).toEqual('e');
-    expect(menu.shownItem(0).name()).toEqual("Constituency");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (2)
-    menu.next();
-    expect(menu._prefix.active()).toBe(true);
-    expect(menu.shownItem(0).name()).toEqual("Constituency");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Next (3)
-    menu.next();
-    expect(menu._prefix.active()).toBe(false);
-    expect(menu.shownItem(0).name()).toEqual("Constituency");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Constitu<mark>e</mark>ncy</strong><span><mark>E</mark>xampl<mark>e</mark> 1</span>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Morphology");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span><mark>E</mark>xampl<mark>e</mark> 2</span>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-  });
-
-
-  it('shouldn\'t be viewable with failing prefix', function () {
-    var menu = KorAP.HintMenu.create("cnx/", list);
-    menu.limit(2);
-    expect(menu.prefix("exit").show()).toBe(false);    
-  });
-
-  it('should be navigatable with prefix', function () {
-    var menu = KorAP.HintMenu.create("cnx/", demolist);
-    menu.limit(3);
-
-    expect(menu.show()).toBe(true);
-    expect(menu.prefix()).toEqual("");
-
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.shownItem(3)).toBe(undefined);
-
-    menu._prefix.add('a');
-    expect(menu.show()).toBe(true);
-    expect(menu.prefix()).toEqual("a");
-    expect(menu.shownItem(0).name()).toEqual("Autor");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong><mark>A</mark>utor</strong>");
-
-    menu._prefix.add('u');
-    expect(menu.show()).toBe(true);
-    expect(menu.prefix()).toEqual("au");
-    expect(menu.shownItem(0).name()).toEqual("Autor");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong><mark>Au</mark>tor</strong>");
-
-    menu._prefix.backspace();
-    expect(menu.show()).toBe(true);
-    expect(menu.prefix()).toEqual("a");
-    expect(menu.shownItem(0).name()).toEqual("Autor");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong><mark>A</mark>utor</strong>");
-
-    menu._prefix.backspace();
-    expect(menu.show()).toBe(true);
-    expect(menu.prefix()).toEqual("");
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.shownItem(3)).toBe(undefined);
-
-    // Forward
-    menu._prefix.backspace();
-    expect(menu.show()).toBe(true);
-    expect(menu.prefix()).toEqual("");
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
-    expect(menu.shownItem(2).active()).toBe(false);
-
-    // Forward
-    menu.next();
-    expect(menu.prefix()).toEqual("");
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
-    expect(menu.shownItem(2).active()).toBe(false);
-    expect(menu.shownItem(3)).toBe(undefined);
-
-    // Forward
-    menu.next();
-    expect(menu.prefix()).toEqual("");
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.shownItem(3)).toBe(undefined);
-
-    // Forward
-    menu.next();
-    expect(menu.prefix()).toEqual("");
-    expect(menu.shownItem(0).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Untertitel</strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Veröffentlichungsdatum");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name()).toEqual("Länge");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Länge</strong>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.shownItem(3)).toBe(undefined);
-
-    // Forward
-    menu.next();
-    expect(menu.prefix()).toEqual("");
-    expect(menu.shownItem(0).name()).toEqual("Veröffentlichungsdatum");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Länge");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Länge</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name()).toEqual("Autor");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Autor</strong>");
-    expect(menu.shownItem(2).active()).toBe(true);
-    expect(menu.shownItem(3)).toBe(undefined);
-
-    // Forward
-    menu.next();
-    expect(menu.prefix()).toEqual("");
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Titel</strong>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertitel</strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2).name()).toEqual("Veröffentlichungsdatum");
-    expect(menu.element().childNodes[3].innerHTML).toEqual("<strong>Veröffentlichungsdatum</strong>");
-    expect(menu.shownItem(2).active()).toBe(false);
-
-  });
-
-
-  it('should be navigatable with a prefix (1)', function () {
-    var menu = KorAP.HintMenu.create("cnx/", demolist);
-    menu.limit(3);
-
-    expect(menu.show()).toBe(true);
-    expect(menu.prefix()).toEqual("");
-
-    menu.prefix('el');
-    expect(menu.show()).toBe(true);
-
-    expect(menu.prefix()).toEqual("el");
-    expect(menu._prefix.active()).toEqual(false);
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Forward
-    menu.next();
-    expect(menu.prefix()).toEqual("el");
-    expect(menu._prefix.active()).toEqual(false);
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Forward
-    menu.next();
-    expect(menu.prefix()).toEqual("el");
-    expect(menu._prefix.active()).toEqual(true);
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-
-    // Backward
-    menu.prev();
-    expect(menu.prefix()).toEqual("el");
-    expect(menu._prefix.active()).toEqual(false);
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-  });
-
-
-  it('should be navigatable with a prefix (2)', function () {
-    var menu = KorAP.HintMenu.create("cnx/", demolist);
-    menu.limit(3);
-    expect(menu.show()).toBe(true);
-    expect(menu.prefix()).toEqual("");
-    menu.prefix('el');
-    expect(menu.show()).toBe(true);
-
-    expect(menu.prefix()).toEqual("el");
-    expect(menu._prefix.active()).toEqual(false);
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Backward
-    menu.prev();
-    expect(menu._prefix.active()).toEqual(true);
-
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Backward
-    menu.prev();
-    expect(menu._prefix.active()).toEqual(false);
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(true);
-    expect(menu.shownItem(2)).toBe(undefined);
-  });
-
-  it('should be navigatable with a prefix (3)', function () {
-    var menu = KorAP.HintMenu.create("cnx/", demolist);
-    menu.limit(3);
-    expect(menu.show()).toBe(true);
-    expect(menu.prefix()).toEqual("");
-    menu.prefix('el');
-    expect(menu.show()).toBe(true);
-
-    expect(menu.prefix()).toEqual("el");
-    expect(menu._prefix.active()).toEqual(false);
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-    // Backward
-    menu.prev();
-    expect(menu._prefix.active()).toEqual(true);
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(false);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-
-    // Forward
-    menu.next();
-    expect(menu.prefix()).toEqual("el");
-    expect(menu._prefix.active()).toEqual(false);
-    expect(menu.shownItem(0).name()).toEqual("Titel");
-    expect(menu.element().childNodes[1].innerHTML).toEqual("<strong>Tit<mark>el</mark></strong>");
-    expect(menu.shownItem(0).active()).toBe(true);
-    expect(menu.shownItem(1).name()).toEqual("Untertitel");
-    expect(menu.element().childNodes[2].innerHTML).toEqual("<strong>Untertit<mark>el</mark></strong>");
-    expect(menu.shownItem(1).active()).toBe(false);
-    expect(menu.shownItem(2)).toBe(undefined);
-
-  });
-
-  xit('should be page downable');
-  xit('should be page upable');
-
-  xit('should scroll to a chosen value')
-  xit('should highlight a chosen value')
 });
diff --git a/dev/js/spec/vcSpec.js b/dev/js/spec/vcSpec.js
index 1a24fb6..3dd0749 100644
--- a/dev/js/spec/vcSpec.js
+++ b/dev/js/spec/vcSpec.js
@@ -1,1898 +1,1918 @@
 /*
-Todo: In demoSpec: Create "and" on the last element of the top "or"-Group
-*/
+ * Todo: In demoSpec: Create "and" on the last element of the top "or"-Group
+ */
+define(['vc'], function () {
 
+  var vcClass =          require('vc');
+  var docClass =         require('vc/doc');
+  var docGroupClass =    require('vc/docgroup');
+  var unspecifiedClass = require('vc/unspecified');
+  var operatorsClass =   require('vc/operators');
+  var rewriteClass =     require('vc/rewrite');
 
-// Helper method for building factories
-buildFactory = function (objClass, defaults) {
-  return {
-    create : function (overwrites) {
-      var newObj = {};
-      for (var prop in defaults) {
-	newObj[prop] = defaults[prop];
-      };
-      for (var prop in overwrites) {
-	newObj[prop] = overwrites[prop];
-      };
-      if (objClass === KorAP.VirtualCollection)
-	return objClass.render(newObj);
-      else
-	return objClass.create().fromJson(newObj);
+  // Helper method for building factories
+  buildFactory = function (objClass, defaults) {
+    return {
+      create : function (overwrites) {
+	var newObj = {};
+	for (var prop in defaults) {
+	  newObj[prop] = defaults[prop];
+	};
+	for (var prop in overwrites) {
+	  newObj[prop] = overwrites[prop];
+	};
+	if (objClass === vcClass)
+	  return objClass.render(newObj);
+	else
+	  return objClass.create().fromJson(newObj);
+      }
     }
-  }
-};
+  };
 
-function _andOn (obj) {
-  KorAP._and.bind(obj.element().lastChild.firstChild).apply();
-};
+  function _andOn (obj) {
+    KorAP._and.bind(obj.element().lastChild.firstChild).apply();
+  };
 
-function _orOn (obj) {
-  KorAP._or.bind(obj.element().lastChild.firstChild).apply();
-};
+  function _orOn (obj) {
+    KorAP._or.bind(obj.element().lastChild.firstChild).apply();
+  };
 
-function _delOn (obj) {
-  KorAP._delete.bind(obj.element().lastChild.firstChild).apply();
-};
+  function _delOn (obj) {
+    KorAP._delete.bind(obj.element().lastChild.firstChild).apply();
+  };
 
-var demoFactory = buildFactory(KorAP.VirtualCollection, {
-  "@type":"koral:docGroup",
-  "operation":"operation:or",
-  "operands":[
-    {
-      "@type":"koral:docGroup",
-      "operation":"operation:and",
-      "operands":[
-        {
-          "@type":"koral:doc",
-          "key":"Titel",
-          "value":"Baum",
-          "match":"match:eq"
-        },
-        {
-          "@type":"koral:doc",
-          "key":"Veröffentlichungsort",
-          "value":"hihi",
-          "match":"match:eq"
-        },
-        {
-          "@type":"koral:docGroup",
-          "operation":"operation:or",
-          "operands":[
-            {
-              "@type":"koral:doc",
-              "key":"Titel",
-              "value":"Baum",
-              "match":"match:eq"
-            },
-            {
-              "@type":"koral:doc",
-              "key":"Veröffentlichungsort",
-              "value":"hihi",
-              "match":"match:eq"
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "@type":"koral:doc",
-      "key":"Untertitel",
-      "value":"huhu",
-      "match":"match:eq"
-    }
-  ]
-});
-
-
-describe('KorAP.Doc', function () {
-
-  // Create example factories
-  var stringFactory = buildFactory(KorAP.Doc, {
-    "key"   : "author",
-    "value" : "Max Birkendale",
-    "@type" : "koral:doc"
-  });
-
-  // Create example factories
-  var dateFactory = buildFactory(KorAP.Doc, {
-    "key"   : "pubDate",
-    "type"  : "type:date",
-    "match" : "match:eq",
-    "value" : "2014-11-05",
-    "@type" : "koral:doc"
-  });
-
-  // Create example factories
-  var regexFactory = buildFactory(KorAP.Doc, {
-    "key"   : "title",
-    "type"  : "type:regex",
-    "value" : "[^b]ee.+?",
-    "@type" : "koral:doc"
-  });
-
-  it('should be initializable', function () {
-    var doc = KorAP.Doc.create();
-    expect(doc.matchop()).toEqual('eq');
-    expect(doc.key()).toBeUndefined();
-    expect(doc.value()).toBeUndefined();
-    expect(doc.type()).toEqual("string");
-  });
-
-  it('should be definable', function () {
-
-    // Empty doc
-    var doc = KorAP.Doc.create();
-
-    // Set values
-    doc.key("title");
-    doc.value("Der alte Mann");
-    expect(doc.matchop()).toEqual('eq');
-    expect(doc.key()).toEqual("title");
-    expect(doc.type()).toEqual("string");
-    expect(doc.value()).toEqual("Der alte Mann");
-  });
-
-
-  it('should deserialize JSON-LD string', function () {
-    var doc;
-
-    // String default
-    doc = stringFactory.create();
-    expect(doc.matchop()).toEqual('eq');
-    expect(doc.key()).toEqual("author");
-    expect(doc.type()).toEqual("string");
-    expect(doc.value()).toEqual("Max Birkendale");
-
-    // No valid string
-    doc = stringFactory.create({
-      value : undefined
-    });
-    expect(doc).toBeUndefined();
-
-    // No valid string
-    doc = stringFactory.create({
-      value : { "foo" : "bar" }
-    });
-    expect(doc).toBeUndefined();
-
-    // Change match type
-    doc = stringFactory.create({
-      "match" : "match:ne"
-    });
-
-    expect(doc.matchop()).toEqual('ne');
-    expect(doc.key()).toEqual("author");
-    expect(doc.type()).toEqual("string");
-    expect(doc.value()).toEqual("Max Birkendale");
-
-
-    // Invalid match type
-    doc = stringFactory.create({
-      "match" : { "foo" : "bar" }
-    });
-    expect(doc).toBeUndefined();
-  });
-
-  it('should deserialize JSON-LD regex', function () {
-    var doc = regexFactory.create();
-    expect(doc.key()).toEqual("title");
-    expect(doc.type()).toEqual("regex");
-    expect(doc.value()).toEqual("[^b]ee.+?");
-    expect(doc.matchop()).toEqual('eq');
-
-    // change matcher
-    doc = regexFactory.create({
-      match : "match:ne"
-    });
-    expect(doc.matchop()).toEqual('ne');
-
-    // Invalid matcher
-    doc = regexFactory.create({
-      match : "match:chook"
-    });
-    expect(doc).toBeUndefined();
-
-    // Invalid regex
-    doc = regexFactory.create({
-      value : "[^b"
-    });
-    expect(doc).toBeUndefined();
-  });
-
-  it('should deserialize JSON-LD date', function () {
-
-    // Normal date
-    doc = dateFactory.create({});
-
-    expect(doc.matchop()).toEqual('eq');
-    expect(doc.key()).toEqual("pubDate");
-    expect(doc.type()).toEqual("date");
-    expect(doc.value()).toEqual("2014-11-05");
-
-    // Short date 1
-    doc = dateFactory.create({
-      "value" : "2014-11"
-    });
-
-    expect(doc.matchop()).toEqual('eq');
-    expect(doc.key()).toEqual("pubDate");
-    expect(doc.type()).toEqual("date");
-    expect(doc.value()).toEqual("2014-11");
-
-    // Short date 2
-    doc = dateFactory.create({
-      "value" : "2014"
-    });
-
-    expect(doc.matchop()).toEqual('eq');
-    expect(doc.key()).toEqual("pubDate");
-    expect(doc.type()).toEqual("date");
-    expect(doc.value()).toEqual("2014");
-
-    // Invalid date!
-    doc = dateFactory.create({
-      "value" : "2014-11-050"
-    });
-    expect(doc).toBeUndefined();
-
-    // Invalid matcher!
-    doc = dateFactory.create({
-      "match" : "match:ne",
-    });
-    expect(doc).toBeUndefined();
-  });
-
-  it('should be serializale to JSON', function () {
-
-    // Empty doc
-    var doc = KorAP.Doc.create();
-    expect(doc.toJson()).toEqual(jasmine.any(Object));
-
-    // Serialize string
-    doc = stringFactory.create();
-    expect(doc.toJson()).toEqual(jasmine.objectContaining({
-      "@type" : "koral:doc",
-      "type" : "type:string",
-      "key" : "author",
-      "value" : "Max Birkendale",
-      "match" : "match:eq"
-    }));
-
-    // Serialize regex
-    doc = regexFactory.create();
-    expect(doc.toJson()).toEqual(jasmine.objectContaining({
-      "@type" : "koral:doc",
-      "type" : "type:regex",
-      "value" : "[^b]ee.+?",
-      "match" : "match:eq",
-      "key" : 'title'
-    }));
-
-    doc = regexFactory.create({
-      match: "match:ne"
-    });
-    expect(doc.toJson()).toEqual(jasmine.objectContaining({
-      "@type" : "koral:doc",
-      "type" : "type:regex",
-      "value" : "[^b]ee.+?",
-      "match" : "match:ne",
-      "key" : 'title'
-    }));
-
-    doc = dateFactory.create();
-    expect(doc.toJson()).toEqual(jasmine.objectContaining({
-      "@type" : "koral:doc",
-      "type" : "type:date",
-      "value" : "2014-11-05",
-      "match" : "match:eq",
-      "key" : 'pubDate'
-    }));
-
-    doc = dateFactory.create({
-      value : "2014"
-    });
-    expect(doc.toJson()).toEqual(jasmine.objectContaining({
-      "@type" : "koral:doc",
-      "type" : "type:date",
-      "value" : "2014",
-      "match" : "match:eq",
-      "key" : 'pubDate'
-    }));
-  });
-
-  it('should be serializale to String', function () {
-
-    // Empty doc
-    var doc = KorAP.Doc.create();
-    expect(doc.toQuery()).toEqual("");
-
-    // Serialize string
-    doc = stringFactory.create();
-    expect(doc.toQuery()).toEqual('author = "Max Birkendale"');
-
-    // Serialize string with quotes
-    doc = stringFactory.create({ "value" : 'Max "Der Coole" Birkendate'});
-    expect(doc.toQuery()).toEqual('author = "Max \\"Der Coole\\" Birkendate"');
-
-    // Serialize regex
-    doc = regexFactory.create();
-    expect(doc.toQuery()).toEqual('title = /[^b]ee.+?/');
-
-    doc = regexFactory.create({
-      match: "match:ne"
-    });
-    expect(doc.toQuery()).toEqual('title != /[^b]ee.+?/');
-
-    doc = dateFactory.create();
-    expect(doc.toQuery()).toEqual('pubDate in 2014-11-05');
-
-    doc = dateFactory.create({
-      value : "2014"
-    });
-    expect(doc.toQuery()).toEqual('pubDate in 2014');
-  });
-});
-
-
-describe('KorAP.DocGroup', function () {
-  // Create example factories
-  var docFactory = buildFactory(
-    KorAP.Doc,
-    {
-      "@type" : "koral:doc",
-      "match":"match:eq",
-      "key" : "author",
-      "value" : "Max Birkendale"
-    }
-  );
-
-  var docGroupFactory = buildFactory(
-    KorAP.DocGroup, {
-      "@type" : "koral:docGroup",
-      "operation" : "operation:and",
-      "operands" : [
-	docFactory.create().toJson(),
-	docFactory.create({
-	  "key" : "pubDate",
-	  "type" : "type:date",
-	  "value" : "2014-12-05"
-	}).toJson()
-      ]
-    });
-
-
-  it('should be initializable', function () {
-    // Create empty group
-    var docGroup = KorAP.DocGroup.create();
-    expect(docGroup.operation()).toEqual('and');
-
-    // Create empty group
-    docGroup = KorAP.DocGroup.create();
-    docGroup.operation('or');
-    expect(docGroup.operation()).toEqual('or');
-  });
-
-  it('should be definable', function () {
-
-    // Empty group
-    var docGroup = KorAP.DocGroup.create();
-    expect(docGroup.operation()).toEqual('and');
-
-    // Set values
-    docGroup.operation("or");
-    expect(docGroup.operation()).toEqual('or');
-
-    // Set invalid values
-    docGroup.operation("hui");
-    expect(docGroup.operation()).toEqual('or');
-  });
-
-  it('should be deserializable', function () {
-    var docGroup = docGroupFactory.create();
-    expect(docGroup.operation()).toEqual("and");
-    expect(docGroup.operands().length).toEqual(2);
-
-    var op1 = docGroup.getOperand(0);
-    expect(op1.type()).toEqual("string");
-    expect(op1.key()).toEqual("author");
-    expect(op1.value()).toEqual("Max Birkendale");
-    expect(op1.matchop()).toEqual("eq");
-
-    var op2 = docGroup.getOperand(1);
-    expect(op2.type()).toEqual("date");
-    expect(op2.key()).toEqual("pubDate");
-    expect(op2.value()).toEqual("2014-12-05");
-    expect(op2.matchop()).toEqual("eq");
-
-    // Append empty group
-    var newGroup = docGroup.append(KorAP.DocGroup.create());
-    newGroup.operation('or');
-    newGroup.append(docFactory.create());
-    newGroup.append(docFactory.create({
-      "type" : "type:regex",
-      "key" : "title",
-      "value" : "^e.+?$",
-      "match" : "match:ne"
-    }));
-
-    expect(docGroup.operation()).toEqual("and");
-    expect(docGroup.operands().length).toEqual(3);
-
-    var op1 = docGroup.getOperand(0);
-    expect(op1.ldType()).toEqual("doc");
-    expect(op1.type()).toEqual("string");
-    expect(op1.key()).toEqual("author");
-    expect(op1.value()).toEqual("Max Birkendale");
-    expect(op1.matchop()).toEqual("eq");
-
-    var op2 = docGroup.getOperand(1);
-    expect(op2.ldType()).toEqual("doc");
-    expect(op2.type()).toEqual("date");
-    expect(op2.key()).toEqual("pubDate");
-    expect(op2.value()).toEqual("2014-12-05");
-    expect(op2.matchop()).toEqual("eq");
-
-    var op3 = docGroup.getOperand(2);
-    expect(op3.ldType()).toEqual("docGroup");
-    expect(op3.operation()).toEqual("or");
-
-    var op4 = op3.getOperand(0);
-    expect(op4.ldType()).toEqual("doc");
-    expect(op4.type()).toEqual("string");
-    expect(op4.key()).toEqual("author");
-    expect(op4.value()).toEqual("Max Birkendale");
-    expect(op4.matchop()).toEqual("eq");
-
-    var op5 = op3.getOperand(1);
-    expect(op5.ldType()).toEqual("doc");
-    expect(op5.type()).toEqual("regex");
-    expect(op5.key()).toEqual("title");
-    expect(op5.value()).toEqual("^e.+?$");
-    expect(op5.matchop()).toEqual("ne");
-  });
-
-  it('should be serializable to JSON', function () {
-    var docGroup = docGroupFactory.create();
-
-    expect(docGroup.toJson()).toEqual(jasmine.objectContaining({
-      "@type" : "koral:docGroup",
-      "operation" : "operation:and",
-      "operands" : [
-	{
-	  "@type": 'koral:doc',
-	  "key" : 'author',
-	  "match": 'match:eq',
-	  "value": 'Max Birkendale',
-	  "type": 'type:string'
-	},
-	{
-	  "@type": 'koral:doc',
-	  "key": 'pubDate',
-	  "match": 'match:eq',
-	  "value": '2014-12-05',
-	  "type": 'type:date'
-	}
-      ]
-    }));
-  });
-
-  it('should be serializable to String', function () {
-    var docGroup = docGroupFactory.create();
-    expect(docGroup.toQuery()).toEqual('author = "Max Birkendale" & pubDate in 2014-12-05');
-
-    docGroup = docGroupFactory.create({
-      "@type" : "koral:docGroup",
-      "operation" : "operation:or",
-      "operands" : [
-	{
-	  "@type": 'koral:doc',
-	  "key" : 'author',
-	  "match": 'match:eq',
-	  "value": 'Max Birkendale',
-	  "type": 'type:string'
-	},
-	{
-	  "@type" : "koral:docGroup",
-	  "operation" : "operation:and",
-	  "operands" : [
-	    {
-	      "@type": 'koral:doc',
-	      "key": 'pubDate',
-	      "match": 'match:geq',
-	      "value": '2014-05-12',
-	      "type": 'type:date'
-	    },
-	    {
-	      "@type": 'koral:doc',
-	      "key": 'pubDate',
-	      "match": 'match:leq',
-	      "value": '2014-12-05',
-	      "type": 'type:date'
-	    },
-	    {
-	      "@type": 'koral:doc',
-	      "key": 'foo',
-	      "match": 'match:ne',
-	      "value": '[a]?bar',
-	      "type": 'type:regex'
-	    }
-	  ]
-	}
-      ]
-    });
-    expect(docGroup.toQuery()).toEqual(
-      'author = "Max Birkendale" | (pubDate since 2014-05-12 & pubDate until 2014-12-05 & foo != /[a]?bar/)'
-    );
-  });
-});
-
-describe('KorAP.UnspecifiedDoc', function () {
-  it('should be initializable', function () {
-    var doc = KorAP.UnspecifiedDoc.create();
-    var docElement = doc.element();
-    expect(docElement.getAttribute('class')).toEqual('doc unspecified');
-    expect(docElement.firstChild.firstChild.data).toEqual('⋯');
-    expect(docElement.lastChild.lastChild.data).toEqual('⋯');
-    expect(doc.toQuery()).toEqual('');
-
-    // Only removable
-    expect(docElement.lastChild.children.length).toEqual(0);
-  });
-
-  it('should be removable, when no root', function () {
-    var docGroup = KorAP.DocGroup.create();
-    docGroup.operation('or');
-    expect(docGroup.operation()).toEqual('or');
-
-    docGroup.append({
-      "@type": 'koral:doc',
-      "key": 'pubDate',
-      "match": 'match:eq',
-      "value": '2014-12-05',
-      "type": 'type:date'      
-    });
-
-    // Add unspecified object
-    docGroup.append();
-
-    expect(docGroup.element().getAttribute('class')).toEqual('docGroup');
-    expect(docGroup.element().children[0].getAttribute('class')).toEqual('doc');
-
-    var unspec = docGroup.element().children[1];
-    expect(unspec.getAttribute('class')).toEqual('doc unspecified');
-
-    // Removable
-    expect(unspec.lastChild.children.length).toEqual(1);
-    expect(unspec.lastChild.children[0].getAttribute('class')).toEqual('delete');
-  });
-
-  it('should be replaceable by a doc', function () {
-    var doc = KorAP.UnspecifiedDoc.create();
-    expect(doc.ldType()).toEqual("non");
-    // No parent, therefor not updateable
-    expect(doc.key("baum")).toBeNull();
-
-    var docGroup = KorAP.DocGroup.create();
-    docGroup.operation('or');
-    expect(docGroup.operation()).toEqual('or');
-
-    docGroup.append({
-      "@type": 'koral:doc',
-      "key": 'pubDate',
-      "match": 'match:eq',
-      "value": '2014-12-05',
-      "type": 'type:date'      
-    });
-
-    expect(docGroup.toQuery()).toEqual("pubDate in 2014-12-05");
-    docGroup.append();
-
-    expect(docGroup.getOperand(0).ldType()).toEqual("doc");
-    expect(docGroup.getOperand(1).ldType()).toEqual("non");
-
-    var op = docGroup.getOperand(1).element().lastChild;
-    expect(op.getAttribute('class')).toEqual('operators');
-    expect(op.children[0].getAttribute('class')).toEqual('delete');
-    expect(op.children.length).toEqual(1);
-
-    // Replace unspecified doc
-    expect(docGroup.getOperand(1).key("name")).not.toBeNull();
-    expect(docGroup.getOperand(1).ldType()).toEqual("doc");
-    expect(docGroup.getOperand(1).key()).toEqual("name");
-    expect(docGroup.getOperand(1).value()).toEqual("");
-
-    op = docGroup.getOperand(1).element().lastChild;
-    expect(op.getAttribute('class')).toEqual('operators');
-    expect(op.children[0].getAttribute('class')).toEqual('and');
-    expect(op.children[1].getAttribute('class')).toEqual('or');
-    expect(op.children[2].getAttribute('class')).toEqual('delete');
-    expect(op.children.length).toEqual(3);
-
-    docGroup.getOperand(1).value("Pachelbel");
-    expect(docGroup.getOperand(1).value()).toEqual("Pachelbel");
-    expect(docGroup.getOperand(1).type()).toEqual("string");
-    expect(docGroup.getOperand(1).matchop()).toEqual("eq");
-
-    // Specified!
-    expect(docGroup.toQuery()).toEqual('pubDate in 2014-12-05 | name = "Pachelbel"');
-  });
-
-  it('should be replaceable on root', function () {
-    var vc = KorAP.VirtualCollection.render();
-    expect(vc.toQuery()).toEqual("");
-
-    expect(vc.root().ldType()).toEqual("non");
-
-    // No operators on root
-    op = vc.root().element().lastChild;
-    expect(op.lastChild.textContent).toEqual('⋯');
-
-    // Replace
-    expect(vc.root().key("baum")).not.toBeNull();
-    expect(vc.root().ldType()).toEqual("doc");
-
-    op = vc.root().element().lastChild;
-    expect(op.getAttribute('class')).toEqual('operators');
-    expect(op.children[0].getAttribute('class')).toEqual('and');
-    expect(op.children[1].getAttribute('class')).toEqual('or');
-    expect(op.children[2].getAttribute('class')).toEqual('delete');
-    expect(op.children.length).toEqual(3);
-  });
-});
-
-describe('KorAP.Doc element', function () {
-  it('should be initializable', function () {
-    var docElement = KorAP.Doc.create(undefined, {
-      "@type" : "koral:doc",
-      "key":"Titel",
-      "value":"Baum",
-      "match":"match:eq"
-    });
-    expect(docElement.key()).toEqual('Titel');
-    expect(docElement.matchop()).toEqual('eq');
-    expect(docElement.value()).toEqual('Baum');
-
-    var docE = docElement.element();
-    expect(docE.children[0].firstChild.data).toEqual('Titel');
-    expect(docE.children[1].firstChild.data).toEqual('eq');
-    expect(docE.children[1].getAttribute('data-type')).toEqual('string');
-    expect(docE.children[2].firstChild.data).toEqual('Baum');
-    expect(docE.children[2].getAttribute('data-type')).toEqual('string');
-
-    expect(docElement.toJson()).toEqual(jasmine.objectContaining({
-      "@type" : "koral:doc",
-      "key":"Titel",
-      "value":"Baum",
-      "match":"match:eq"
-    }));
-  });
-});
-
-describe('KorAP.DocGroup element', function () {
-  it('should be initializable', function () {
-
-    var docGroup = KorAP.DocGroup.create(undefined, {
-      "@type" : "koral:docGroup",
-      "operation" : "operation:and",
-      "operands" : [
-	{
-	  "@type": 'koral:doc',
-	  "key" : 'author',
-	  "match": 'match:eq',
-	  "value": 'Max Birkendale',
-	  "type": 'type:string'
-	},
-	{
-	  "@type": 'koral:doc',
-	  "key": 'pubDate',
-	  "match": 'match:eq',
-	  "value": '2014-12-05',
-	  "type": 'type:date'
-	}
-      ]
-    });
-
-    expect(docGroup.operation()).toEqual('and');
-    var e = docGroup.element();
-    expect(e.getAttribute('class')).toEqual('docGroup');
-    expect(e.getAttribute('data-operation')).toEqual('and');
-
-    var first = e.children[0];
-    expect(first.getAttribute('class')).toEqual('doc');
-    expect(first.children[0].getAttribute('class')).toEqual('key');
-    expect(first.children[1].getAttribute('class')).toEqual('match');
-    expect(first.children[2].getAttribute('class')).toEqual('value');
-    expect(first.children[2].getAttribute('data-type')).toEqual('string');
-    expect(first.children[0].firstChild.data).toEqual('author');
-    expect(first.children[1].firstChild.data).toEqual('eq');
-    expect(first.children[2].firstChild.data).toEqual('Max Birkendale');
-
-    var second = e.children[1];
-    expect(second.getAttribute('class')).toEqual('doc');
-    expect(second.children[0].getAttribute('class')).toEqual('key');
-    expect(second.children[1].getAttribute('class')).toEqual('match');
-    expect(second.children[2].getAttribute('class')).toEqual('value');
-    expect(second.children[2].getAttribute('data-type')).toEqual('date');
-    expect(second.children[0].firstChild.data).toEqual('pubDate');
-    expect(second.children[1].firstChild.data).toEqual('eq');
-    expect(second.children[2].firstChild.data).toEqual('2014-12-05');
-
-  });
-
-  it('should be deserializable with nested groups', function () {
-    var docGroup = KorAP.DocGroup.create(undefined, {
-      "@type" : "koral:docGroup",
-      "operation" : "operation:or",
-      "operands" : [
-	{
-	  "@type": 'koral:doc',
-	  "key" : 'author',
-	  "match": 'match:eq',
-	  "value": 'Max Birkendale',
-	  "type": 'type:string'
-	},
-	{
-	  "@type" : "koral:docGroup",
-	  "operation" : "operation:and",
-	  "operands" : [
-	    {
-	      "@type": 'koral:doc',
-	      "key": 'pubDate',
-	      "match": 'match:geq',
-	      "value": '2014-05-12',
-	      "type": 'type:date'
-	    },
-	    {
-	      "@type": 'koral:doc',
-	      "key": 'pubDate',
-	      "match": 'match:leq',
-	      "value": '2014-12-05',
-	      "type": 'type:date'
-	    }
-	  ]
-	}
-      ]
-    });
-
-    expect(docGroup.operation()).toEqual('or');
-    var e = docGroup.element();
-    expect(e.getAttribute('class')).toEqual('docGroup');
-    expect(e.getAttribute('data-operation')).toEqual('or');
-
-    expect(e.children[0].getAttribute('class')).toEqual('doc');
-    var docop = e.children[0].lastChild;
-    expect(docop.getAttribute('class')).toEqual('operators');
-    expect(docop.children[0].getAttribute('class')).toEqual('and');
-    expect(docop.children[1].getAttribute('class')).toEqual('or');
-    expect(docop.children[2].getAttribute('class')).toEqual('delete');
-
-    expect(e.children[1].getAttribute('class')).toEqual('docGroup');
-    expect(e.children[1].getAttribute('data-operation')).toEqual('and');
-
-    // This and-operation can be "or"ed or "delete"d
-    var secop = e.children[1].children[2];
-    expect(secop.getAttribute('class')).toEqual('operators');
-    expect(secop.children[0].getAttribute('class')).toEqual('or');
-    expect(secop.children[1].getAttribute('class')).toEqual('delete');
-
-    // This or-operation can be "and"ed or "delete"d
-    expect(e.children[2].getAttribute('class')).toEqual('operators');
-    expect(e.lastChild.getAttribute('class')).toEqual('operators');
-    expect(e.lastChild.children[0].getAttribute('class')).toEqual('and');
-    expect(e.lastChild.children[1].getAttribute('class')).toEqual('delete');
-
-  });
-});
-
-describe('KorAP.VirtualCollection', function () {
-
-  var simpleGroupFactory = buildFactory(KorAP.DocGroup, {
-    "@type" : "koral:docGroup",
-    "operation" : "operation:and",
-    "operands" : [
+  var demoFactory = buildFactory(vcClass, {
+    "@type":"koral:docGroup",
+    "operation":"operation:or",
+    "operands":[
       {
-	"@type": 'koral:doc',
-	"key" : 'author',
-	"match": 'match:eq',
-	"value": 'Max Birkendale',
-	"type": 'type:string'
+	"@type":"koral:docGroup",
+	"operation":"operation:and",
+	"operands":[
+          {
+            "@type":"koral:doc",
+            "key":"Titel",
+            "value":"Baum",
+            "match":"match:eq"
+          },
+          {
+            "@type":"koral:doc",
+            "key":"Veröffentlichungsort",
+            "value":"hihi",
+            "match":"match:eq"
+          },
+          {
+            "@type":"koral:docGroup",
+            "operation":"operation:or",
+            "operands":[
+              {
+		"@type":"koral:doc",
+		"key":"Titel",
+		"value":"Baum",
+		"match":"match:eq"
+              },
+              {
+		"@type":"koral:doc",
+		"key":"Veröffentlichungsort",
+		"value":"hihi",
+		"match":"match:eq"
+              }
+            ]
+          }
+	]
       },
       {
-	"@type": 'koral:doc',
-	"key": 'pubDate',
-	"match": 'match:eq',
-	"value": '2014-12-05',
-	"type": 'type:date'
+	"@type":"koral:doc",
+	"key":"Untertitel",
+	"value":"huhu",
+	"match":"match:eq"
       }
     ]
   });
 
-  var nestedGroupFactory = buildFactory(KorAP.VirtualCollection, {
-    "@type" : "koral:docGroup",
-    "operation" : "operation:or",
-    "operands" : [
+  describe('KorAP.Doc', function () {
+    // Create example factories
+    var stringFactory = buildFactory(docClass, {
+      "key"   : "author",
+      "value" : "Max Birkendale",
+      "@type" : "koral:doc"
+    });
+
+    // Create example factories
+    var dateFactory = buildFactory(docClass, {
+      "key"   : "pubDate",
+      "type"  : "type:date",
+      "match" : "match:eq",
+      "value" : "2014-11-05",
+      "@type" : "koral:doc"
+    });
+
+    // Create example factories
+    var regexFactory = buildFactory(docClass, {
+      "key"   : "title",
+      "type"  : "type:regex",
+      "value" : "[^b]ee.+?",
+      "@type" : "koral:doc"
+    });
+
+    it('should be initializable', function () {
+      var doc = docClass.create();
+      expect(doc.matchop()).toEqual('eq');
+      expect(doc.key()).toBeUndefined();
+      expect(doc.value()).toBeUndefined();
+      expect(doc.type()).toEqual("string");
+    });
+
+    it('should be definable', function () {
+
+      // Empty doc
+      var doc = docClass.create();
+
+      // Set values
+      doc.key("title");
+      doc.value("Der alte Mann");
+      expect(doc.matchop()).toEqual('eq');
+      expect(doc.key()).toEqual("title");
+      expect(doc.type()).toEqual("string");
+      expect(doc.value()).toEqual("Der alte Mann");
+    });
+
+
+    it('should deserialize JSON-LD string', function () {
+      var doc;
+
+      // String default
+      doc = stringFactory.create();
+      expect(doc.matchop()).toEqual('eq');
+      expect(doc.key()).toEqual("author");
+      expect(doc.type()).toEqual("string");
+      expect(doc.value()).toEqual("Max Birkendale");
+
+      // No valid string
+      doc = stringFactory.create({
+	value : undefined
+      });
+      expect(doc).toBeUndefined();
+
+      // No valid string
+      doc = stringFactory.create({
+	value : { "foo" : "bar" }
+      });
+      expect(doc).toBeUndefined();
+
+      // Change match type
+      doc = stringFactory.create({
+	"match" : "match:ne"
+      });
+
+      expect(doc.matchop()).toEqual('ne');
+      expect(doc.key()).toEqual("author");
+      expect(doc.type()).toEqual("string");
+      expect(doc.value()).toEqual("Max Birkendale");
+
+      // Invalid match type
+      doc = stringFactory.create({
+	"match" : { "foo" : "bar" }
+      });
+      expect(doc).toBeUndefined();
+    });
+
+    it('should deserialize JSON-LD regex', function () {
+      var doc = regexFactory.create();
+      expect(doc.key()).toEqual("title");
+      expect(doc.type()).toEqual("regex");
+      expect(doc.value()).toEqual("[^b]ee.+?");
+      expect(doc.matchop()).toEqual('eq');
+
+      // change matcher
+      doc = regexFactory.create({
+	match : "match:ne"
+      });
+      expect(doc.matchop()).toEqual('ne');
+
+      // Invalid matcher
+      doc = regexFactory.create({
+	match : "match:chook"
+      });
+      expect(doc).toBeUndefined();
+
+      // Invalid regex
+      doc = regexFactory.create({
+	value : "[^b"
+      });
+      expect(doc).toBeUndefined();
+    });
+
+    it('should deserialize JSON-LD date', function () {
+
+      // Normal date
+      doc = dateFactory.create({});
+
+      expect(doc.matchop()).toEqual('eq');
+      expect(doc.key()).toEqual("pubDate");
+      expect(doc.type()).toEqual("date");
+      expect(doc.value()).toEqual("2014-11-05");
+
+      // Short date 1
+      doc = dateFactory.create({
+	"value" : "2014-11"
+      });
+
+      expect(doc.matchop()).toEqual('eq');
+      expect(doc.key()).toEqual("pubDate");
+      expect(doc.type()).toEqual("date");
+      expect(doc.value()).toEqual("2014-11");
+
+      // Short date 2
+      doc = dateFactory.create({
+	"value" : "2014"
+      });
+
+      expect(doc.matchop()).toEqual('eq');
+      expect(doc.key()).toEqual("pubDate");
+      expect(doc.type()).toEqual("date");
+      expect(doc.value()).toEqual("2014");
+
+      // Invalid date!
+      doc = dateFactory.create({
+	"value" : "2014-11-050"
+      });
+      expect(doc).toBeUndefined();
+
+      // Invalid matcher!
+      doc = dateFactory.create({
+	"match" : "match:ne",
+      });
+      expect(doc).toBeUndefined();
+    });
+
+    it('should be serializale to JSON', function () {
+
+      // Empty doc
+      var doc = docClass.create();
+      expect(doc.toJson()).toEqual(jasmine.any(Object));
+
+      // Serialize string
+      doc = stringFactory.create();
+      expect(doc.toJson()).toEqual(jasmine.objectContaining({
+	"@type" : "koral:doc",
+	"type" : "type:string",
+	"key" : "author",
+	"value" : "Max Birkendale",
+	"match" : "match:eq"
+      }));
+
+      // Serialize regex
+      doc = regexFactory.create();
+      expect(doc.toJson()).toEqual(jasmine.objectContaining({
+	"@type" : "koral:doc",
+	"type" : "type:regex",
+	"value" : "[^b]ee.+?",
+	"match" : "match:eq",
+	"key" : 'title'
+      }));
+
+      doc = regexFactory.create({
+	match: "match:ne"
+      });
+      expect(doc.toJson()).toEqual(jasmine.objectContaining({
+	"@type" : "koral:doc",
+	"type" : "type:regex",
+	"value" : "[^b]ee.+?",
+	"match" : "match:ne",
+	"key" : 'title'
+      }));
+
+      doc = dateFactory.create();
+      expect(doc.toJson()).toEqual(jasmine.objectContaining({
+	"@type" : "koral:doc",
+	"type" : "type:date",
+	"value" : "2014-11-05",
+	"match" : "match:eq",
+	"key" : 'pubDate'
+      }));
+
+      doc = dateFactory.create({
+	value : "2014"
+      });
+      expect(doc.toJson()).toEqual(jasmine.objectContaining({
+	"@type" : "koral:doc",
+	"type" : "type:date",
+	"value" : "2014",
+	"match" : "match:eq",
+	"key" : 'pubDate'
+      }));
+    });
+
+
+    it('should be serializale to String', function () {
+      // Empty doc
+      var doc = docClass.create();
+      expect(doc.toQuery()).toEqual("");
+
+      // Serialize string
+      doc = stringFactory.create();
+      expect(doc.toQuery()).toEqual('author = "Max Birkendale"');
+
+      // Serialize string with quotes
+      doc = stringFactory.create({ "value" : 'Max "Der Coole" Birkendate'});
+      expect(doc.toQuery()).toEqual('author = "Max \\"Der Coole\\" Birkendate"');
+
+      // Serialize regex
+      doc = regexFactory.create();
+      expect(doc.toQuery()).toEqual('title = /[^b]ee.+?/');
+
+      doc = regexFactory.create({
+	match: "match:ne"
+      });
+      expect(doc.toQuery()).toEqual('title != /[^b]ee.+?/');
+
+      doc = dateFactory.create();
+      expect(doc.toQuery()).toEqual('pubDate in 2014-11-05');
+
+      doc = dateFactory.create({
+	value : "2014"
+      });
+      expect(doc.toQuery()).toEqual('pubDate in 2014');
+    });
+  });
+
+
+  describe('KorAP.DocGroup', function () {
+    // Create example factories
+    var docFactory = buildFactory(
+      docClass,
       {
-	"@type": 'koral:doc',
-	"key" : 'author',
-	"match": 'match:eq',
-	"value": 'Max Birkendale',
-	"type": 'type:string'
-      },
-      {
+	"@type" : "koral:doc",
+	"match":"match:eq",
+	"key" : "author",
+	"value" : "Max Birkendale"
+      }
+    );
+
+    var docGroupFactory = buildFactory(
+      docGroupClass, {
+	"@type" : "koral:docGroup",
+	"operation" : "operation:and",
+	"operands" : [
+	  docFactory.create().toJson(),
+	  docFactory.create({
+	    "key" : "pubDate",
+	    "type" : "type:date",
+	    "value" : "2014-12-05"
+	  }).toJson()
+	]
+      });
+
+    it('should be initializable', function () {
+      // Create empty group
+      var docGroup = docGroupClass.create();
+      expect(docGroup.operation()).toEqual('and');
+
+      // Create empty group
+      docGroup = docGroupClass.create();
+      docGroup.operation('or');
+      expect(docGroup.operation()).toEqual('or');
+    });
+
+    it('should be definable', function () {
+
+      // Empty group
+      var docGroup = docGroupClass.create();
+      expect(docGroup.operation()).toEqual('and');
+
+      // Set values
+      docGroup.operation("or");
+      expect(docGroup.operation()).toEqual('or');
+
+      // Set invalid values
+      docGroup.operation("hui");
+      expect(docGroup.operation()).toEqual('or');
+    });
+
+    it('should be deserializable', function () {
+      var docGroup = docGroupFactory.create();
+      expect(docGroup.operation()).toEqual("and");
+      expect(docGroup.operands().length).toEqual(2);
+
+      var op1 = docGroup.getOperand(0);
+      expect(op1.type()).toEqual("string");
+      expect(op1.key()).toEqual("author");
+      expect(op1.value()).toEqual("Max Birkendale");
+      expect(op1.matchop()).toEqual("eq");
+
+      var op2 = docGroup.getOperand(1);
+      expect(op2.type()).toEqual("date");
+      expect(op2.key()).toEqual("pubDate");
+      expect(op2.value()).toEqual("2014-12-05");
+      expect(op2.matchop()).toEqual("eq");
+
+      // Append empty group
+      var newGroup = docGroup.append(docGroupClass.create());
+      newGroup.operation('or');
+      newGroup.append(docFactory.create());
+      newGroup.append(docFactory.create({
+	"type" : "type:regex",
+	"key" : "title",
+	"value" : "^e.+?$",
+	"match" : "match:ne"
+      }));
+
+      expect(docGroup.operation()).toEqual("and");
+      expect(docGroup.operands().length).toEqual(3);
+
+      var op1 = docGroup.getOperand(0);
+      expect(op1.ldType()).toEqual("doc");
+      expect(op1.type()).toEqual("string");
+      expect(op1.key()).toEqual("author");
+      expect(op1.value()).toEqual("Max Birkendale");
+      expect(op1.matchop()).toEqual("eq");
+
+      var op2 = docGroup.getOperand(1);
+      expect(op2.ldType()).toEqual("doc");
+      expect(op2.type()).toEqual("date");
+      expect(op2.key()).toEqual("pubDate");
+      expect(op2.value()).toEqual("2014-12-05");
+      expect(op2.matchop()).toEqual("eq");
+
+      var op3 = docGroup.getOperand(2);
+      expect(op3.ldType()).toEqual("docGroup");
+      expect(op3.operation()).toEqual("or");
+
+      var op4 = op3.getOperand(0);
+      expect(op4.ldType()).toEqual("doc");
+      expect(op4.type()).toEqual("string");
+      expect(op4.key()).toEqual("author");
+      expect(op4.value()).toEqual("Max Birkendale");
+      expect(op4.matchop()).toEqual("eq");
+
+      var op5 = op3.getOperand(1);
+      expect(op5.ldType()).toEqual("doc");
+      expect(op5.type()).toEqual("regex");
+      expect(op5.key()).toEqual("title");
+      expect(op5.value()).toEqual("^e.+?$");
+      expect(op5.matchop()).toEqual("ne");
+    });
+
+    it('should be serializable to JSON', function () {
+      var docGroup = docGroupFactory.create();
+
+      expect(docGroup.toJson()).toEqual(jasmine.objectContaining({
 	"@type" : "koral:docGroup",
 	"operation" : "operation:and",
 	"operands" : [
 	  {
 	    "@type": 'koral:doc',
-	    "key": 'pubDate',
-	    "match": 'match:geq',
-	    "value": '2014-05-12',
-	    "type": 'type:date'
+	    "key" : 'author',
+	    "match": 'match:eq',
+	    "value": 'Max Birkendale',
+	    "type": 'type:string'
 	  },
 	  {
 	    "@type": 'koral:doc',
 	    "key": 'pubDate',
-	    "match": 'match:leq',
-	    "value": '2014-12-05',
-	    "type": 'type:date'
-	  }
-	]
-      }
-    ]
-  });
-
-  var flatGroupFactory = buildFactory(KorAP.VirtualCollection, {
-    "@type" : "koral:docGroup",
-    "operation" : "operation:and",
-    "operands" : [
-      {
-	"@type": 'koral:doc',
-	"key": 'pubDate',
-	"match": 'match:geq',
-	"value": '2014-05-12',
-	"type": 'type:date'
-      },
-      {
-	"@type": 'koral:doc',
-	"key": 'pubDate',
-	"match": 'match:leq',
-	"value": '2014-12-05',
-	"type": 'type:date'
-      },
-      {
-	"@type": 'koral:doc',
-	"key": 'foo',
-	"match": 'match:eq',
-	"value": 'bar',
-	"type": 'type:string'
-      }
-    ]
-  });
-  
-  it('should be initializable', function () {
-    var vc = KorAP.VirtualCollection.render();
-    expect(vc.element().getAttribute('class')).toEqual('vc');
-    expect(vc.root().element().getAttribute('class')).toEqual('doc unspecified');
-
-    // Not removable
-    expect(vc.root().element().lastChild.children.length).toEqual(0);
-  });
-
-  it('should be based on a doc', function () {
-    var vc = KorAP.VirtualCollection.render({
-      "@type" : "koral:doc",
-      "key":"Titel",
-      "value":"Baum",
-      "match":"match:eq"
-    });
-
-    expect(vc.element().getAttribute('class')).toEqual('vc');
-    expect(vc.root().element().getAttribute('class')).toEqual('doc');
-    expect(vc.root().key()).toEqual('Titel');
-    expect(vc.root().value()).toEqual('Baum');
-    expect(vc.root().matchop()).toEqual('eq');
-
-    var docE = vc.root().element();
-    expect(docE.children[0].firstChild.data).toEqual('Titel');
-    expect(docE.children[1].firstChild.data).toEqual('eq');
-    expect(docE.children[1].getAttribute('data-type')).toEqual('string');
-    expect(docE.children[2].firstChild.data).toEqual('Baum');
-    expect(docE.children[2].getAttribute('data-type')).toEqual('string');
-  });
-
-  it('should be based on a docGroup', function () {
-    var vc = KorAP.VirtualCollection.render(simpleGroupFactory.create().toJson());
-
-    expect(vc.element().getAttribute('class')).toEqual('vc');
-    expect(vc.root().element().getAttribute('class')).toEqual('docGroup');
-    expect(vc.root().operation()).toEqual('and');
-
-    var docGroup = vc.root();
-
-    var first = docGroup.getOperand(0);
-    expect(first.key()).toEqual('author');
-    expect(first.value()).toEqual('Max Birkendale');
-    expect(first.matchop()).toEqual('eq');
-
-    var second = docGroup.getOperand(1);
-    expect(second.key()).toEqual('pubDate');
-    expect(second.value()).toEqual('2014-12-05');
-    expect(second.matchop()).toEqual('eq');
-  });
-
-
-  it('should be based on a nested docGroup', function () {
-    var vc = nestedGroupFactory.create();
-
-    expect(vc.element().getAttribute('class')).toEqual('vc');
-    expect(vc.element().firstChild.getAttribute('class')).toEqual('docGroup');
-    expect(vc.element().firstChild.children[0].getAttribute('class')).toEqual('doc');
-    var dg = vc.element().firstChild.children[1];
-    expect(dg.getAttribute('class')).toEqual('docGroup');
-    expect(dg.children[0].getAttribute('class')).toEqual('doc');
-    expect(dg.children[1].getAttribute('class')).toEqual('doc');
-    expect(dg.children[2].getAttribute('class')).toEqual('operators');
-    expect(vc.element().firstChild.children[2].getAttribute('class')).toEqual('operators');
-  });    
-
-  it('should be modifiable by deletion in flat docGroups', function () {
-    var vc = flatGroupFactory.create();
-    var docGroup = vc.root();
-
-    expect(docGroup.element().getAttribute('class')).toEqual('docGroup');
-
-    var doc = docGroup.getOperand(1);
-    expect(doc.key()).toEqual("pubDate");
-    expect(doc.value()).toEqual("2014-12-05");
-
-    // Remove operand 1
-    expect(docGroup.delOperand(doc).update()).not.toBeUndefined();
-    expect(doc._element).toEqual(undefined);
-
-    doc = docGroup.getOperand(1);
-    expect(doc.key()).toEqual("foo");
-
-    // Remove operand 1
-    expect(docGroup.delOperand(doc).update()).not.toBeUndefined();
-    expect(doc._element).toEqual(undefined);
-
-    // Only one operand left ...
-    expect(docGroup.getOperand(1)).toBeUndefined();
-    // ... but there shouldn't be a group anymore at all!
-    expect(docGroup.getOperand(0)).toBeUndefined();
-    
-    var obj = vc.root();
-    expect(obj.ldType()).toEqual("doc");
-    expect(obj.key()).toEqual("pubDate");
-    expect(obj.value()).toEqual("2014-05-12");
-
-    expect(obj.element().getAttribute('class')).toEqual('doc');
-  }); 
-
-
-  it('should be modifiable by deletion in nested docGroups (root case)', function () {
-    var vc = nestedGroupFactory.create();
-
-    expect(vc.toQuery()).toEqual(
-      'author = "Max Birkendale" | (pubDate since 2014-05-12 & pubDate until 2014-12-05)'
-    );
-
-    var docGroup = vc.root();
-    expect(docGroup.ldType()).toEqual("docGroup");
-    expect(docGroup.operation()).toEqual("or");
-
-    var doc = docGroup.getOperand(0);
-    expect(doc.key()).toEqual("author");
-    expect(doc.value()).toEqual("Max Birkendale");
-
-    docGroup = docGroup.getOperand(1);
-    expect(docGroup.operation()).toEqual("and");
-
-    doc = docGroup.getOperand(0);
-    expect(doc.key()).toEqual("pubDate");
-    expect(doc.matchop()).toEqual("geq");
-    expect(doc.value()).toEqual("2014-05-12");
-    expect(doc.type()).toEqual("date");
-
-    doc = docGroup.getOperand(1);
-    expect(doc.key()).toEqual("pubDate");
-    expect(doc.matchop()).toEqual("leq");
-    expect(doc.value()).toEqual("2014-12-05");
-    expect(doc.type()).toEqual("date");
-
-    // Remove first operand so everything becomes root
-    expect(
-      vc.root().delOperand(
-	vc.root().getOperand(0)
-      ).update().ldType()
-    ).toEqual("docGroup");
-
-    expect(vc.root().ldType()).toEqual("docGroup");
-    expect(vc.root().operation()).toEqual("and");
-    expect(vc.root().getOperand(0).ldType()).toEqual("doc");
-
-    expect(vc.toQuery()).toEqual(
-      'pubDate since 2014-05-12 & pubDate until 2014-12-05'
-    );
-  });
-
-  it('should be modifiable by deletion in nested docGroups (resolve group case)', function () {
-    var vc = nestedGroupFactory.create();
-
-    // Get nested group
-    var firstGroup = vc.root().getOperand(1);
-    firstGroup.append(simpleGroupFactory.create({ "operation" : "operation:or" }));
-    
-    // Structur is now:
-    // or(doc, and(doc, doc, or(doc, doc)))
-
-    // Get nested or in and
-    var orGroup = vc.root().getOperand(1).getOperand(2);
-    expect(orGroup.ldType()).toEqual("docGroup");
-    expect(orGroup.operation()).toEqual("or");
-
-    // Remove 
-    // Structur is now:
-    // or(doc, and(doc, doc, doc)))
-    expect(orGroup.delOperand(orGroup.getOperand(0)).update().operation()).toEqual("and");
-    expect(vc.root().getOperand(1).operands().length).toEqual(3);
-  });
-
-  it('should be modifiable by deletion in nested docGroups (identical group case)', function () {
-    var vc = nestedGroupFactory.create();
-
-    // Get nested group
-    var firstGroup = vc.root().getOperand(1);
-    firstGroup.append(simpleGroupFactory.create({
-      "operation" : "operation:or"
-    }));
-    var oldAuthor = firstGroup.getOperand(2).getOperand(0);
-    oldAuthor.key("title");
-    oldAuthor.value("Der Birnbaum");
-    
-    // Structur is now:
-    // or(doc, and(doc, doc, or(doc, doc)))
-    expect(vc.toQuery()).toEqual(
-      'author = "Max Birkendale" | (pubDate since 2014-05-12 & pubDate until 2014-12-05 & (title = "Der Birnbaum" | pubDate in 2014-12-05))'
-    );
-
-    var andGroup = vc.root().getOperand(1);
-
-    // Get leading docs in and
-    var doc1 = andGroup.getOperand(0);
-    expect(doc1.ldType()).toEqual("doc");
-    expect(doc1.value()).toEqual("2014-05-12");
-    var doc2 = andGroup.getOperand(1);
-    expect(doc2.ldType()).toEqual("doc");
-    expect(doc2.value()).toEqual("2014-12-05");
-
-    // Remove 2
-    expect(andGroup.delOperand(doc2).update().operation()).toEqual("and");
-    // Structur is now:
-    // or(doc, and(doc, or(doc, doc)))
-
-    expect(vc.toQuery()).toEqual(
-      'author = "Max Birkendale"' +
-	' | (pubDate since 2014-05-12 & ' +
-	'(title = "Der Birnbaum" | pubDate in 2014-12-05))'
-    );
-
-
-    // Remove 1
-    expect(andGroup.delOperand(doc1).update().operation()).toEqual("or");
-    // Structur is now:
-    // or(doc, doc, doc)
-
-    expect(vc.toQuery()).toEqual(
-      'author = "Max Birkendale" | title = "Der Birnbaum" | pubDate in 2014-12-05'
-    );
-  });
-
-  it('should be reducible to unspecification', function () {
-    var vc = demoFactory.create();
-
-    expect(vc.toQuery()).toEqual(vc.root().toQuery());
-
-    expect(vc.toQuery()).toEqual(
-      '(Titel = "Baum" & Veröffentlichungsort = "hihi" & ' +
-	'(Titel = "Baum" | Veröffentlichungsort = "hihi")) ' +
-	'| Untertitel = "huhu"');
-
-    expect(vc.root().element().lastChild.children[0].firstChild.nodeValue).toEqual('and');
-    expect(vc.root().element().lastChild.children[1].firstChild.nodeValue).toEqual('×');
-    expect(vc.root().delOperand(vc.root().getOperand(0)).update()).not.toBeUndefined();
-    expect(vc.toQuery()).toEqual('Untertitel = "huhu"');
-
-    var lc = vc.root().element().lastChild;
-    expect(lc.children[0].firstChild.nodeValue).toEqual('and');
-    expect(lc.children[1].firstChild.nodeValue).toEqual('or');
-    expect(lc.children[2].firstChild.nodeValue).toEqual('×');
-
-    // Clean everything
-    vc.clean();
-    expect(vc.toQuery()).toEqual('');
-  });
-
-  it('should flatten on import', function () {
-    var vc = KorAP.VirtualCollection.create().render({
-      "@type":"koral:docGroup",
-      "operation":"operation:or",
-      "operands":[
-	{
-	  "@type":"koral:docGroup",
-	  "operation":"operation:or",
-	  "operands":[
-            {
-              "@type":"koral:doc",
-              "key":"Titel",
-              "value":"Baum",
-              "match":"match:eq"
-            },
-            {
-              "@type":"koral:doc",
-              "key":"Veröffentlichungsort",
-              "value":"hihi",
-              "match":"match:eq"
-            },
-            {
-              "@type":"koral:docGroup",
-              "operation":"operation:or",
-              "operands":[
-		{
-		  "@type":"koral:doc",
-		  "key":"Titel",
-		  "value":"Baum",
-		  "match":"match:eq"
-		},
-		{
-		  "@type":"koral:doc",
-		  "key":"Veröffentlichungsort",
-		  "value":"hihi",
-		  "match":"match:eq"
-		}
-              ]
-            }
-	  ]
-	},
-	{
-	  "@type":"koral:doc",
-	  "key":"Untertitel",
-	  "value":"huhu",
-	  "match":"match:eq"
-	}
-      ]
-    });
-
-    expect(vc.toQuery()).toEqual(
-      'Titel = "Baum" | Veröffentlichungsort = "hihi" | Untertitel = "huhu"'
-    );
-
-
-  });
-});
-
-describe('KorAP.Operators', function () {
-  it('should be initializable', function () {
-    var op = KorAP.Operators.create(true, false, false);
-    expect(op.and()).toBeTruthy();
-    expect(op.or()).not.toBeTruthy();
-    expect(op.del()).not.toBeTruthy();
-
-    op.and(false);
-    expect(op.and()).not.toBeTruthy();
-    expect(op.or()).not.toBeTruthy();
-    expect(op.del()).not.toBeTruthy();
-
-    op.or(true);
-    op.del(true);
-    expect(op.and()).not.toBeTruthy();
-    expect(op.or()).toBeTruthy();
-    expect(op.del()).toBeTruthy();
-
-    var e = op.element();
-    expect(e.getAttribute('class')).toEqual('operators');
-    expect(e.children[0].getAttribute('class')).toEqual('or');
-    expect(e.children[0].firstChild.data).toEqual('or');
-    expect(e.children[1].getAttribute('class')).toEqual('delete');
-    expect(e.children[1].firstChild.data).toEqual('×');
-
-    op.and(true);
-    op.del(false);
-    op.update();
-
-    e = op.element();
-    expect(e.getAttribute('class')).toEqual('operators');
-    expect(e.children[0].getAttribute('class')).toEqual('and');
-    expect(e.children[0].firstChild.data).toEqual('and');
-    expect(e.children[1].getAttribute('class')).toEqual('or');
-    expect(e.children[1].firstChild.data).toEqual('or');
-  });
-});
-
-describe('KorAP._delete (event)', function () {
-  var complexVCFactory = buildFactory(KorAP.VirtualCollection,{
-    "@type": 'koral:docGroup',
-    'operation' : 'operation:and',
-    'operands' : [
-      {
-	"@type": 'koral:doc',
-	"key": 'pubDate',
-	"match": 'match:eq',
-	"value": '2014-12-05',
-	"type": 'type:date'
-      },
-      {
-	"@type" : 'koral:docGroup',
-	'operation' : 'operation:or',
-	'operands' : [
-	  {
-	    '@type' : 'koral:doc',
-	    'key' : 'title',
-	    'value' : 'Hello World!'
-	  },
-	  {
-	    '@type' : 'koral:doc',
-	    'key' : 'foo',
-	    'value' : 'bar'
-	  }
-	]
-      }
-    ]
-  });
-
-  it('should clean on root docs', function () {
-    var vc = KorAP.VirtualCollection.render({
-      "@type": 'koral:doc',
-      "key": 'pubDate',
-      "match": 'match:eq',
-      "value": '2014-12-05',
-      "type": 'type:date'
-    });
-    expect(vc.root().toQuery()).toEqual('pubDate in 2014-12-05');
-    expect(vc.root().element().lastChild.getAttribute('class')).toEqual('operators');
-
-    // Clean with delete from root
-    expect(vc.root().element().lastChild.lastChild.getAttribute('class')).toEqual('delete');
-    _delOn(vc.root());
-    expect(vc.root().toQuery()).toEqual('');
-    expect(vc.root().element().lastChild.lastChild.data).toEqual('⋯');
-  });
-
-  it ('should remove on nested docs', function () {
-    var vc = KorAP.VirtualCollection.render(
-      {
-	"@type": 'koral:docGroup',
-	'operation' : 'operation:and',
-	'operands' : [
-	  {
-	    "@type": 'koral:doc',
-	    "key": 'pubDate',
 	    "match": 'match:eq',
 	    "value": '2014-12-05',
 	    "type": 'type:date'
-	  },
-	  {
-	    "@type" : 'koral:doc',
-	    'key' : 'foo',
-	    'value' : 'bar'
 	  }
 	]
-      }
-    );
+      }));
+    });
 
-    // Delete with direct element access
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
-    _delOn(vc.root().getOperand(0));
+    it('should be serializable to String', function () {
+      var docGroup = docGroupFactory.create();
+      expect(docGroup.toQuery()).toEqual(
+	'author = "Max Birkendale" & pubDate in 2014-12-05'
+      );
 
-    expect(vc.toQuery()).toEqual('foo = "bar"');
-    expect(vc.root().ldType()).toEqual('doc');
-  });
-
-  it ('should clean on doc groups', function () {
-    var vc = KorAP.VirtualCollection.render(
-      {
-	"@type": 'koral:docGroup',
-	'operation' : 'operation:and',
-	'operands' : [
+      docGroup = docGroupFactory.create({
+	"@type" : "koral:docGroup",
+	"operation" : "operation:or",
+	"operands" : [
 	  {
 	    "@type": 'koral:doc',
-	    "key": 'pubDate',
+	    "key" : 'author',
 	    "match": 'match:eq',
-	    "value": '2014-12-05',
-	    "type": 'type:date'
+	    "value": 'Max Birkendale',
+	    "type": 'type:string'
 	  },
 	  {
-	    "@type" : 'koral:doc',
-	    'key' : 'foo',
-	    'value' : 'bar'
-	  }
-	]
-      }
-    );
-
-    // Cleanwith direct element access
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
-    _delOn(vc.root());
-    expect(vc.toQuery()).toEqual('');
-    expect(vc.root().ldType()).toEqual('non');
-  });
-
-  it ('should remove on nested doc groups (case of ungrouping 1)', function () {
-    var vc = complexVCFactory.create();
-
-    // Delete with direct element access
-    expect(vc.toQuery()).toEqual(
-      'pubDate in 2014-12-05 & (title = "Hello World!" | foo = "bar")'
-    );
-
-    // Remove hello world:
-    _delOn(vc.root().getOperand(1).getOperand(0));
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
-    expect(vc.root().ldType()).toEqual('docGroup');
-  });
-
-  it ('should remove on nested doc groups (case of ungrouping 2)', function () {
-    var vc = complexVCFactory.create();
-
-    // Delete with direct element access
-    expect(vc.toQuery()).toEqual(
-      'pubDate in 2014-12-05 & (title = "Hello World!" | foo = "bar")'
-    );
-
-    // Remove bar
-    _delOn(vc.root().getOperand(1).getOperand(1));
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & title = "Hello World!"');
-    expect(vc.root().ldType()).toEqual('docGroup');
-    expect(vc.root().operation()).toEqual('and');
-  });
-
-  it ('should remove on nested doc groups (case of root changing)', function () {
-    var vc = complexVCFactory.create();
-
-    // Delete with direct element access
-    expect(vc.toQuery()).toEqual(
-      'pubDate in 2014-12-05 & (title = "Hello World!" | foo = "bar")'
-    );
-
-    // Remove bar
-    _delOn(vc.root().getOperand(0));
-    expect(vc.toQuery()).toEqual('title = "Hello World!" | foo = "bar"');
-    expect(vc.root().ldType()).toEqual('docGroup');
-    expect(vc.root().operation()).toEqual('or');
-  });
-
-  it ('should remove on nested doc groups (list flattening)', function () {
-    var vc = KorAP.VirtualCollection.render(
-      {
-	"@type": 'koral:docGroup',
-	'operation' : 'operation:or',
-	'operands' : [
-	  {
-	    "@type": 'koral:doc',
-	    "key": 'pubDate',
-	    "match": 'match:eq',
-	    "value": '2014-12-05',
-	    "type": 'type:date'
-	  },
-	  {
-	    "@type" : 'koral:doc',
-	    'key' : 'foo',
-	    'value' : 'bar'
-	  },
-	  {
-	    "@type": 'koral:docGroup',
-	    'operation' : 'operation:and',
-	    'operands' : [
+	    "@type" : "koral:docGroup",
+	    "operation" : "operation:and",
+	    "operands" : [
 	      {
 		"@type": 'koral:doc',
 		"key": 'pubDate',
-		"match": 'match:eq',
+		"match": 'match:geq',
+		"value": '2014-05-12',
+		"type": 'type:date'
+	      },
+	      {
+		"@type": 'koral:doc',
+		"key": 'pubDate',
+		"match": 'match:leq',
 		"value": '2014-12-05',
 		"type": 'type:date'
 	      },
 	      {
-		"@type" : 'koral:docGroup',
-		'operation' : 'operation:or',
-		'operands' : [
+		"@type": 'koral:doc',
+		"key": 'foo',
+		"match": 'match:ne',
+		"value": '[a]?bar',
+		"type": 'type:regex'
+	      }
+	    ]
+	  }
+	]
+      });
+      expect(docGroup.toQuery()).toEqual(
+	'author = "Max Birkendale" | ' +
+	  '(pubDate since 2014-05-12 & ' +
+	  'pubDate until 2014-12-05 & foo != /[a]?bar/)'
+      );
+    });
+  });
+
+  describe('KorAP.UnspecifiedDoc', function () {
+    it('should be initializable', function () {
+      var doc = unspecifiedClass.create();
+      var docElement = doc.element();
+      expect(docElement.getAttribute('class')).toEqual('doc unspecified');
+      expect(docElement.firstChild.firstChild.data).toEqual('⋯');
+      expect(docElement.lastChild.lastChild.data).toEqual('⋯');
+      expect(doc.toQuery()).toEqual('');
+
+      // Only removable
+      expect(docElement.lastChild.children.length).toEqual(0);
+    });
+
+    it('should be removable, when no root', function () {
+      var docGroup = docGroupClass.create();
+      docGroup.operation('or');
+      expect(docGroup.operation()).toEqual('or');
+
+      docGroup.append({
+	"@type": 'koral:doc',
+	"key": 'pubDate',
+	"match": 'match:eq',
+	"value": '2014-12-05',
+	"type": 'type:date'      
+      });
+
+      // Add unspecified object
+      docGroup.append();
+
+      expect(docGroup.element().getAttribute('class')).toEqual('docGroup');
+      expect(docGroup.element().children[0].getAttribute('class')).toEqual('doc');
+
+      var unspec = docGroup.element().children[1];
+      expect(unspec.getAttribute('class')).toEqual('doc unspecified');
+
+      // Removable
+      expect(unspec.lastChild.children.length).toEqual(1);
+      expect(unspec.lastChild.children[0].getAttribute('class')).toEqual('delete');
+    });
+
+    it('should be replaceable by a doc', function () {
+      var doc = unspecifiedClass.create();
+      expect(doc.ldType()).toEqual("non");
+      // No parent, therefor not updateable
+      expect(doc.key("baum")).toBeNull();
+
+      var docGroup = docGroupClass.create();
+      docGroup.operation('or');
+      expect(docGroup.operation()).toEqual('or');
+
+      docGroup.append({
+	"@type": 'koral:doc',
+	"key": 'pubDate',
+	"match": 'match:eq',
+	"value": '2014-12-05',
+	"type": 'type:date'      
+      });
+
+      expect(docGroup.toQuery()).toEqual("pubDate in 2014-12-05");
+      docGroup.append();
+
+      expect(docGroup.getOperand(0).ldType()).toEqual("doc");
+      expect(docGroup.getOperand(1).ldType()).toEqual("non");
+
+      var op = docGroup.getOperand(1).element().lastChild;
+      expect(op.getAttribute('class')).toEqual('operators');
+      expect(op.children[0].getAttribute('class')).toEqual('delete');
+      expect(op.children.length).toEqual(1);
+
+      // Replace unspecified doc
+      expect(docGroup.getOperand(1).key("name")).not.toBeNull();
+      expect(docGroup.getOperand(1).ldType()).toEqual("doc");
+      expect(docGroup.getOperand(1).key()).toEqual("name");
+      expect(docGroup.getOperand(1).value()).toEqual("");
+
+      op = docGroup.getOperand(1).element().lastChild;
+      expect(op.getAttribute('class')).toEqual('operators');
+      expect(op.children[0].getAttribute('class')).toEqual('and');
+      expect(op.children[1].getAttribute('class')).toEqual('or');
+      expect(op.children[2].getAttribute('class')).toEqual('delete');
+      expect(op.children.length).toEqual(3);
+
+      docGroup.getOperand(1).value("Pachelbel");
+      expect(docGroup.getOperand(1).value()).toEqual("Pachelbel");
+      expect(docGroup.getOperand(1).type()).toEqual("string");
+      expect(docGroup.getOperand(1).matchop()).toEqual("eq");
+
+      // Specified!
+      expect(docGroup.toQuery()).toEqual('pubDate in 2014-12-05 | name = "Pachelbel"');
+    });
+
+    it('should be replaceable on root', function () {
+      var vc = vcClass.render();
+      expect(vc.toQuery()).toEqual("");
+
+      expect(vc.root().ldType()).toEqual("non");
+
+      // No operators on root
+      op = vc.root().element().lastChild;
+      expect(op.lastChild.textContent).toEqual('⋯');
+
+      // Replace
+      expect(vc.root().key("baum")).not.toBeNull();
+      expect(vc.root().ldType()).toEqual("doc");
+
+      op = vc.root().element().lastChild;
+      expect(op.getAttribute('class')).toEqual('operators');
+      expect(op.children[0].getAttribute('class')).toEqual('and');
+      expect(op.children[1].getAttribute('class')).toEqual('or');
+      expect(op.children[2].getAttribute('class')).toEqual('delete');
+      expect(op.children.length).toEqual(3);
+    });
+  });
+
+  describe('KorAP.Doc element', function () {
+    it('should be initializable', function () {
+      var docElement = docClass.create(undefined, {
+	"@type" : "koral:doc",
+	"key":"Titel",
+	"value":"Baum",
+	"match":"match:eq"
+      });
+      expect(docElement.key()).toEqual('Titel');
+      expect(docElement.matchop()).toEqual('eq');
+      expect(docElement.value()).toEqual('Baum');
+
+      var docE = docElement.element();
+      expect(docE.children[0].firstChild.data).toEqual('Titel');
+      expect(docE.children[1].firstChild.data).toEqual('eq');
+      expect(docE.children[1].getAttribute('data-type')).toEqual('string');
+      expect(docE.children[2].firstChild.data).toEqual('Baum');
+      expect(docE.children[2].getAttribute('data-type')).toEqual('string');
+      
+      expect(docElement.toJson()).toEqual(jasmine.objectContaining({
+	"@type" : "koral:doc",
+	"key":"Titel",
+	"value":"Baum",
+	"match":"match:eq"
+      }));
+    });
+  });
+
+  describe('KorAP.DocGroup element', function () {
+    it('should be initializable', function () {
+
+      var docGroup = docGroupClass.create(undefined, {
+	"@type" : "koral:docGroup",
+	"operation" : "operation:and",
+	"operands" : [
+	  {
+	    "@type": 'koral:doc',
+	    "key" : 'author',
+	    "match": 'match:eq',
+	    "value": 'Max Birkendale',
+	    "type": 'type:string'
+	  },
+	  {
+	    "@type": 'koral:doc',
+	    "key": 'pubDate',
+	    "match": 'match:eq',
+	    "value": '2014-12-05',
+	    "type": 'type:date'
+	  }
+	]
+      });
+
+      expect(docGroup.operation()).toEqual('and');
+      var e = docGroup.element();
+      expect(e.getAttribute('class')).toEqual('docGroup');
+      expect(e.getAttribute('data-operation')).toEqual('and');
+
+      var first = e.children[0];
+      expect(first.getAttribute('class')).toEqual('doc');
+      expect(first.children[0].getAttribute('class')).toEqual('key');
+      expect(first.children[1].getAttribute('class')).toEqual('match');
+      expect(first.children[2].getAttribute('class')).toEqual('value');
+      expect(first.children[2].getAttribute('data-type')).toEqual('string');
+      expect(first.children[0].firstChild.data).toEqual('author');
+      expect(first.children[1].firstChild.data).toEqual('eq');
+      expect(first.children[2].firstChild.data).toEqual('Max Birkendale');
+
+      var second = e.children[1];
+      expect(second.getAttribute('class')).toEqual('doc');
+      expect(second.children[0].getAttribute('class')).toEqual('key');
+      expect(second.children[1].getAttribute('class')).toEqual('match');
+      expect(second.children[2].getAttribute('class')).toEqual('value');
+      expect(second.children[2].getAttribute('data-type')).toEqual('date');
+      expect(second.children[0].firstChild.data).toEqual('pubDate');
+      expect(second.children[1].firstChild.data).toEqual('eq');
+      expect(second.children[2].firstChild.data).toEqual('2014-12-05');
+    });
+
+    it('should be deserializable with nested groups', function () {
+      var docGroup = docGroupClass.create(undefined, {
+	"@type" : "koral:docGroup",
+	"operation" : "operation:or",
+	"operands" : [
+	  {
+	    "@type": 'koral:doc',
+	    "key" : 'author',
+	    "match": 'match:eq',
+	    "value": 'Max Birkendale',
+	    "type": 'type:string'
+	  },
+	  {
+	    "@type" : "koral:docGroup",
+	    "operation" : "operation:and",
+	    "operands" : [
+	      {
+		"@type": 'koral:doc',
+		"key": 'pubDate',
+		"match": 'match:geq',
+		"value": '2014-05-12',
+		"type": 'type:date'
+	      },
+	      {
+		"@type": 'koral:doc',
+		"key": 'pubDate',
+		"match": 'match:leq',
+		"value": '2014-12-05',
+		"type": 'type:date'
+	      }
+	    ]
+	  }
+	]
+      });
+
+      expect(docGroup.operation()).toEqual('or');
+      var e = docGroup.element();
+      expect(e.getAttribute('class')).toEqual('docGroup');
+      expect(e.getAttribute('data-operation')).toEqual('or');
+
+      expect(e.children[0].getAttribute('class')).toEqual('doc');
+      var docop = e.children[0].lastChild;
+      expect(docop.getAttribute('class')).toEqual('operators');
+      expect(docop.children[0].getAttribute('class')).toEqual('and');
+      expect(docop.children[1].getAttribute('class')).toEqual('or');
+      expect(docop.children[2].getAttribute('class')).toEqual('delete');
+
+      expect(e.children[1].getAttribute('class')).toEqual('docGroup');
+      expect(e.children[1].getAttribute('data-operation')).toEqual('and');
+
+      // This and-operation can be "or"ed or "delete"d
+      var secop = e.children[1].children[2];
+      expect(secop.getAttribute('class')).toEqual('operators');
+      expect(secop.children[0].getAttribute('class')).toEqual('or');
+      expect(secop.children[1].getAttribute('class')).toEqual('delete');
+
+      // This or-operation can be "and"ed or "delete"d
+      expect(e.children[2].getAttribute('class')).toEqual('operators');
+      expect(e.lastChild.getAttribute('class')).toEqual('operators');
+      expect(e.lastChild.children[0].getAttribute('class')).toEqual('and');
+      expect(e.lastChild.children[1].getAttribute('class')).toEqual('delete');
+    });
+  });
+
+  describe('KorAP.VirtualCollection', function () {
+    var simpleGroupFactory = buildFactory(docGroupClass, {
+      "@type" : "koral:docGroup",
+      "operation" : "operation:and",
+      "operands" : [
+	{
+	  "@type": 'koral:doc',
+	  "key" : 'author',
+	  "match": 'match:eq',
+	  "value": 'Max Birkendale',
+	  "type": 'type:string'
+	},
+	{
+	  "@type": 'koral:doc',
+	  "key": 'pubDate',
+	  "match": 'match:eq',
+	  "value": '2014-12-05',
+	  "type": 'type:date'
+	}
+      ]
+    });
+
+    var nestedGroupFactory = buildFactory(vcClass, {
+      "@type" : "koral:docGroup",
+      "operation" : "operation:or",
+      "operands" : [
+	{
+	  "@type": 'koral:doc',
+	  "key" : 'author',
+	  "match": 'match:eq',
+	  "value": 'Max Birkendale',
+	  "type": 'type:string'
+	},
+	{
+	  "@type" : "koral:docGroup",
+	  "operation" : "operation:and",
+	  "operands" : [
+	    {
+	      "@type": 'koral:doc',
+	      "key": 'pubDate',
+	      "match": 'match:geq',
+	      "value": '2014-05-12',
+	      "type": 'type:date'
+	    },
+	    {
+	      "@type": 'koral:doc',
+	      "key": 'pubDate',
+	      "match": 'match:leq',
+	      "value": '2014-12-05',
+	      "type": 'type:date'
+	    }
+	  ]
+	}
+      ]
+    });
+
+    var flatGroupFactory = buildFactory(vcClass, {
+      "@type" : "koral:docGroup",
+      "operation" : "operation:and",
+      "operands" : [
+	{
+	  "@type": 'koral:doc',
+	  "key": 'pubDate',
+	  "match": 'match:geq',
+	  "value": '2014-05-12',
+	  "type": 'type:date'
+	},
+	{
+	  "@type": 'koral:doc',
+	  "key": 'pubDate',
+	  "match": 'match:leq',
+	  "value": '2014-12-05',
+	  "type": 'type:date'
+	},
+	{
+	  "@type": 'koral:doc',
+	  "key": 'foo',
+	  "match": 'match:eq',
+	  "value": 'bar',
+	  "type": 'type:string'
+	}
+      ]
+    });
+    
+    it('should be initializable', function () {
+      var vc = vcClass.render();
+      expect(vc.element().getAttribute('class')).toEqual('vc');
+      expect(vc.root().element().getAttribute('class')).toEqual('doc unspecified');
+
+      // Not removable
+      expect(vc.root().element().lastChild.children.length).toEqual(0);
+    });
+
+    it('should be based on a doc', function () {
+      var vc = vcClass.render({
+	"@type" : "koral:doc",
+	"key":"Titel",
+	"value":"Baum",
+	"match":"match:eq"
+      });
+
+      expect(vc.element().getAttribute('class')).toEqual('vc');
+      expect(vc.root().element().getAttribute('class')).toEqual('doc');
+      expect(vc.root().key()).toEqual('Titel');
+      expect(vc.root().value()).toEqual('Baum');
+      expect(vc.root().matchop()).toEqual('eq');
+
+      var docE = vc.root().element();
+      expect(docE.children[0].firstChild.data).toEqual('Titel');
+      expect(docE.children[1].firstChild.data).toEqual('eq');
+      expect(docE.children[1].getAttribute('data-type')).toEqual('string');
+      expect(docE.children[2].firstChild.data).toEqual('Baum');
+      expect(docE.children[2].getAttribute('data-type')).toEqual('string');
+    });
+
+    it('should be based on a docGroup', function () {
+      var vc = vcClass.render(simpleGroupFactory.create().toJson());
+
+      expect(vc.element().getAttribute('class')).toEqual('vc');
+      expect(vc.root().element().getAttribute('class')).toEqual('docGroup');
+      expect(vc.root().operation()).toEqual('and');
+
+      var docGroup = vc.root();
+
+      var first = docGroup.getOperand(0);
+      expect(first.key()).toEqual('author');
+      expect(first.value()).toEqual('Max Birkendale');
+      expect(first.matchop()).toEqual('eq');
+
+      var second = docGroup.getOperand(1);
+      expect(second.key()).toEqual('pubDate');
+      expect(second.value()).toEqual('2014-12-05');
+      expect(second.matchop()).toEqual('eq');
+    });
+
+
+    it('should be based on a nested docGroup', function () {
+      var vc = nestedGroupFactory.create();
+
+      expect(vc.element().getAttribute('class')).toEqual('vc');
+      expect(vc.element().firstChild.getAttribute('class')).toEqual('docGroup');
+      expect(vc.element().firstChild.children[0].getAttribute('class')).toEqual('doc');
+      var dg = vc.element().firstChild.children[1];
+      expect(dg.getAttribute('class')).toEqual('docGroup');
+      expect(dg.children[0].getAttribute('class')).toEqual('doc');
+      expect(dg.children[1].getAttribute('class')).toEqual('doc');
+      expect(dg.children[2].getAttribute('class')).toEqual('operators');
+      expect(vc.element().firstChild.children[2].getAttribute('class')).toEqual('operators');
+    });    
+
+    it('should be modifiable by deletion in flat docGroups', function () {
+      var vc = flatGroupFactory.create();
+      var docGroup = vc.root();
+
+      expect(docGroup.element().getAttribute('class')).toEqual('docGroup');
+
+      var doc = docGroup.getOperand(1);
+      expect(doc.key()).toEqual("pubDate");
+      expect(doc.value()).toEqual("2014-12-05");
+
+      // Remove operand 1
+      expect(docGroup.delOperand(doc).update()).not.toBeUndefined();
+      expect(doc._element).toEqual(undefined);
+
+      doc = docGroup.getOperand(1);
+      expect(doc.key()).toEqual("foo");
+
+      // Remove operand 1
+      expect(docGroup.delOperand(doc).update()).not.toBeUndefined();
+      expect(doc._element).toEqual(undefined);
+
+      // Only one operand left ...
+      expect(docGroup.getOperand(1)).toBeUndefined();
+      // ... but there shouldn't be a group anymore at all!
+      expect(docGroup.getOperand(0)).toBeUndefined();
+      
+      var obj = vc.root();
+      expect(obj.ldType()).toEqual("doc");
+      expect(obj.key()).toEqual("pubDate");
+      expect(obj.value()).toEqual("2014-05-12");
+
+      expect(obj.element().getAttribute('class')).toEqual('doc');
+    }); 
+
+
+    it('should be modifiable by deletion in nested docGroups (root case)', function () {
+      var vc = nestedGroupFactory.create();
+
+      expect(vc.toQuery()).toEqual(
+	'author = "Max Birkendale" | (pubDate since 2014-05-12 & pubDate until 2014-12-05)'
+      );
+
+      var docGroup = vc.root();
+      expect(docGroup.ldType()).toEqual("docGroup");
+      expect(docGroup.operation()).toEqual("or");
+
+      var doc = docGroup.getOperand(0);
+      expect(doc.key()).toEqual("author");
+      expect(doc.value()).toEqual("Max Birkendale");
+
+      docGroup = docGroup.getOperand(1);
+      expect(docGroup.operation()).toEqual("and");
+
+      doc = docGroup.getOperand(0);
+      expect(doc.key()).toEqual("pubDate");
+      expect(doc.matchop()).toEqual("geq");
+      expect(doc.value()).toEqual("2014-05-12");
+      expect(doc.type()).toEqual("date");
+
+      doc = docGroup.getOperand(1);
+      expect(doc.key()).toEqual("pubDate");
+      expect(doc.matchop()).toEqual("leq");
+      expect(doc.value()).toEqual("2014-12-05");
+      expect(doc.type()).toEqual("date");
+
+      // Remove first operand so everything becomes root
+      expect(
+	vc.root().delOperand(
+	  vc.root().getOperand(0)
+	).update().ldType()
+      ).toEqual("docGroup");
+
+      expect(vc.root().ldType()).toEqual("docGroup");
+      expect(vc.root().operation()).toEqual("and");
+      expect(vc.root().getOperand(0).ldType()).toEqual("doc");
+
+      expect(vc.toQuery()).toEqual(
+	'pubDate since 2014-05-12 & pubDate until 2014-12-05'
+      );
+    });
+
+    it('should be modifiable by deletion in nested docGroups (resolve group case)', function () {
+      var vc = nestedGroupFactory.create();
+
+      // Get nested group
+      var firstGroup = vc.root().getOperand(1);
+      firstGroup.append(simpleGroupFactory.create({ "operation" : "operation:or" }));
+      
+      // Structur is now:
+      // or(doc, and(doc, doc, or(doc, doc)))
+
+      // Get nested or in and
+      var orGroup = vc.root().getOperand(1).getOperand(2);
+      expect(orGroup.ldType()).toEqual("docGroup");
+      expect(orGroup.operation()).toEqual("or");
+
+      // Remove 
+      // Structur is now:
+      // or(doc, and(doc, doc, doc)))
+      expect(orGroup.delOperand(orGroup.getOperand(0)).update().operation()).toEqual("and");
+      expect(vc.root().getOperand(1).operands().length).toEqual(3);
+    });
+
+    it('should be modifiable by deletion in nested docGroups (identical group case)', function () {
+      var vc = nestedGroupFactory.create();
+
+      // Get nested group
+      var firstGroup = vc.root().getOperand(1);
+      firstGroup.append(simpleGroupFactory.create({
+	"operation" : "operation:or"
+      }));
+      var oldAuthor = firstGroup.getOperand(2).getOperand(0);
+      oldAuthor.key("title");
+      oldAuthor.value("Der Birnbaum");
+      
+      // Structur is now:
+      // or(doc, and(doc, doc, or(doc, doc)))
+      expect(vc.toQuery()).toEqual(
+	'author = "Max Birkendale" | ' +
+	  '(pubDate since 2014-05-12 & ' +
+	  'pubDate until 2014-12-05 & ' +
+	  '(title = "Der Birnbaum" | ' +
+	  'pubDate in 2014-12-05))'
+      );
+
+      var andGroup = vc.root().getOperand(1);
+
+      // Get leading docs in and
+      var doc1 = andGroup.getOperand(0);
+      expect(doc1.ldType()).toEqual("doc");
+      expect(doc1.value()).toEqual("2014-05-12");
+      var doc2 = andGroup.getOperand(1);
+      expect(doc2.ldType()).toEqual("doc");
+      expect(doc2.value()).toEqual("2014-12-05");
+
+      // Remove 2
+      expect(
+	andGroup.delOperand(doc2).update().operation()
+      ).toEqual("and");
+      // Structur is now:
+      // or(doc, and(doc, or(doc, doc)))
+
+      expect(vc.toQuery()).toEqual(
+	'author = "Max Birkendale"' +
+	  ' | (pubDate since 2014-05-12 & ' +
+	  '(title = "Der Birnbaum" | pubDate in 2014-12-05))'
+      );
+
+
+      // Remove 1
+      expect(andGroup.delOperand(doc1).update().operation()).toEqual("or");
+      // Structur is now:
+      // or(doc, doc, doc)
+
+      expect(vc.toQuery()).toEqual(
+	'author = "Max Birkendale" | title = "Der Birnbaum" | pubDate in 2014-12-05'
+      );
+    });
+
+    it('should be reducible to unspecification', function () {
+      var vc = demoFactory.create();
+
+      expect(vc.toQuery()).toEqual(vc.root().toQuery());
+      expect(vc.toQuery()).toEqual(
+	'(Titel = "Baum" & Veröffentlichungsort = "hihi" & ' +
+	  '(Titel = "Baum" | Veröffentlichungsort = "hihi")) ' +
+	  '| Untertitel = "huhu"');
+      expect(vc.root().element().lastChild.children[0].firstChild.nodeValue).toEqual('and');
+      expect(vc.root().element().lastChild.children[1].firstChild.nodeValue).toEqual('×');
+      expect(vc.root().delOperand(vc.root().getOperand(0)).update()).not.toBeUndefined();
+      expect(vc.toQuery()).toEqual('Untertitel = "huhu"');
+
+      var lc = vc.root().element().lastChild;
+      expect(lc.children[0].firstChild.nodeValue).toEqual('and');
+      expect(lc.children[1].firstChild.nodeValue).toEqual('or');
+      expect(lc.children[2].firstChild.nodeValue).toEqual('×');
+
+      // Clean everything
+      vc.clean();
+      expect(vc.toQuery()).toEqual('');
+    });
+
+    it('should flatten on import', function () {
+      var vc = vcClass.create().render({
+	"@type":"koral:docGroup",
+	"operation":"operation:or",
+	"operands":[
+	  {
+	    "@type":"koral:docGroup",
+	    "operation":"operation:or",
+	    "operands":[
+              {
+		"@type":"koral:doc",
+		"key":"Titel",
+		"value":"Baum",
+		"match":"match:eq"
+              },
+              {
+		"@type":"koral:doc",
+		"key":"Veröffentlichungsort",
+		"value":"hihi",
+		"match":"match:eq"
+              },
+              {
+		"@type":"koral:docGroup",
+		"operation":"operation:or",
+		"operands":[
 		  {
-		    '@type' : 'koral:doc',
-		    'key' : 'title',
-		    'value' : 'Hello World!'
+		    "@type":"koral:doc",
+		    "key":"Titel",
+		    "value":"Baum",
+		    "match":"match:eq"
 		  },
 		  {
-		    '@type' : 'koral:doc',
-		    'key' : 'yeah',
-		    'value' : 'juhu'
+		    "@type":"koral:doc",
+		    "key":"Veröffentlichungsort",
+		    "value":"hihi",
+		    "match":"match:eq"
 		  }
 		]
-	      }
-	    ]
-	  }
-	]
-      }
-    );
-
-    // Delete with direct element access
-    expect(vc.toQuery()).toEqual(
-      'pubDate in 2014-12-05 | foo = "bar" | ' +
-	'(pubDate in 2014-12-05 & ' +
-	'(title = "Hello World!" | yeah = "juhu"))'
-    );
-
-    expect(vc.root().ldType()).toEqual('docGroup');
-    expect(vc.root().operation()).toEqual('or');
-
-    // Operands and operators
-    expect(vc.element().firstChild.children.length).toEqual(4);
-    expect(vc.element().firstChild.lastChild.getAttribute('class')).toEqual('operators');
-
-    // Remove inner group and flatten
-    _delOn(vc.root().getOperand(2).getOperand(0));
-
-    expect(vc.toQuery()).toEqual(
-      'pubDate in 2014-12-05 | foo = "bar" | title = "Hello World!" | yeah = "juhu"'
-    );
-    expect(vc.root().ldType()).toEqual('docGroup');
-    expect(vc.root().operation()).toEqual('or');
-
-    // Operands and operators
-    expect(vc.element().firstChild.children.length).toEqual(5);
-    expect(vc.element().firstChild.lastChild.getAttribute('class')).toEqual('operators');
-  });
-});
-
-describe('KorAP._add (event)', function () {
-  var complexVCFactory = buildFactory(KorAP.VirtualCollection,{
-    "@type": 'koral:docGroup',
-    'operation' : 'operation:and',
-    'operands' : [
-      {
-	"@type": 'koral:doc',
-	"key": 'pubDate',
-	"match": 'match:eq',
-	"value": '2014-12-05',
-	"type": 'type:date'
-      },
-      {
-	"@type" : 'koral:docGroup',
-	'operation' : 'operation:or',
-	'operands' : [
-	  {
-	    '@type' : 'koral:doc',
-	    'key' : 'title',
-	    'value' : 'Hello World!'
-	  },
-	  {
-	    '@type' : 'koral:doc',
-	    'key' : 'foo',
-	    'value' : 'bar'
-	  }
-	]
-      }
-    ]
-  });
-
-  it ('should add new unspecified doc with "and"', function () {
-    var vc = KorAP.VirtualCollection.render(
-      {
-	"@type": 'koral:docGroup',
-	'operation' : 'operation:and',
-	'operands' : [
-	  {
-	    "@type": 'koral:doc',
-	    "key": 'pubDate',
-	    "match": 'match:eq',
-	    "value": '2014-12-05',
-	    "type": 'type:date'
-	  },
-	  {
-	    "@type" : 'koral:doc',
-	    'key' : 'foo',
-	    'value' : 'bar'
-	  }
-	]
-      }
-    );
-
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
-
-    var fc = vc.element().firstChild;
-    expect(fc.getAttribute('data-operation')).toEqual('and');
-    expect(fc.children.length).toEqual(3);
-    expect(fc.lastChild.getAttribute('class')).toEqual('operators');
-    expect(fc.children[0].getAttribute('class')).toEqual('doc');
-    expect(fc.children[1].getAttribute('class')).toEqual('doc');
-
-    // add with 'and' in the middle
-    _andOn(vc.root().getOperand(0));
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
-
-    fc = vc.element().firstChild;
-    expect(fc.getAttribute('data-operation')).toEqual('and');
-    expect(fc.children.length).toEqual(4);
-    expect(fc.lastChild.getAttribute('class')).toEqual('operators');
-
-    expect(fc.children[0].getAttribute('class')).toEqual('doc');
-    expect(fc.children[1].getAttribute('class')).toEqual('doc unspecified');
-    expect(fc.children[2].getAttribute('class')).toEqual('doc');
-  });
-
-  it ('should add new unspecified doc with "or"', function () {
-    var vc = KorAP.VirtualCollection.render(
-      {
-	"@type": 'koral:docGroup',
-	'operation' : 'operation:and',
-	'operands' : [
-	  {
-	    "@type": 'koral:doc',
-	    "key": 'pubDate',
-	    "match": 'match:eq',
-	    "value": '2014-12-05',
-	    "type": 'type:date'
-	  },
-	  {
-	    "@type" : 'koral:doc',
-	    'key' : 'foo',
-	    'value' : 'bar'
-	  }
-	]
-      }
-    );
-
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
-
-    var fc = vc.element().firstChild;
-    expect(fc.children.length).toEqual(3);
-    expect(fc.lastChild.getAttribute('class')).toEqual('operators');
-    expect(fc.children[0].getAttribute('class')).toEqual('doc');
-    expect(fc.children[1].getAttribute('class')).toEqual('doc');
-
-    // add with 'or' in the middle
-    _orOn(vc.root().getOperand(0));
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
-    fc = vc.element().firstChild;
-
-    expect(fc.getAttribute('data-operation')).toEqual('and');
-    expect(fc.children.length).toEqual(3);
-    expect(fc.children[0].getAttribute('class')).toEqual('docGroup');
-    expect(fc.children[0].getAttribute('data-operation')).toEqual('or');
-    expect(fc.children[1].getAttribute('class')).toEqual('doc');
-    expect(fc.children[2].getAttribute('class')).toEqual('operators');
-    expect(fc.lastChild.getAttribute('class')).toEqual('operators');
-
-    fc = vc.element().firstChild.firstChild;
-    expect(fc.children.length).toEqual(3);
-    expect(fc.children[0].getAttribute('class')).toEqual('doc');
-    expect(fc.children[1].getAttribute('class')).toEqual('doc unspecified');
-    expect(fc.children[2].getAttribute('class')).toEqual('operators');
-    expect(fc.lastChild.getAttribute('class')).toEqual('operators');
-  });
-
-  it ('should add new unspecified doc with "and" before group', function () {
-    var vc = demoFactory.create();
-
-    // Wrap with direct element access
-    expect(vc.toQuery()).toEqual(
-      '(Titel = "Baum" & Veröffentlichungsort = "hihi" & (Titel = "Baum" | Veröffentlichungsort = "hihi")) | Untertitel = "huhu"'
-    );
-
-    expect(vc.root().getOperand(0).ldType()).toEqual('docGroup');
-    expect(vc.root().getOperand(0).operation()).toEqual('and');
-    expect(vc.root().getOperand(0).operands().length).toEqual(3);
-
-    // Add unspecified on the second doc
-    var secDoc = vc.root().getOperand(0).getOperand(1);
-    expect(secDoc.value()).toEqual('hihi');
-
-    // Add
-    _andOn(secDoc);
-
-    var fo = vc.root().getOperand(0);
-
-    expect(fo.ldType()).toEqual('docGroup');
-    expect(fo.operation()).toEqual('and');
-    expect(fo.operands().length).toEqual(4);
-
-    expect(fo.getOperand(0).ldType()).toEqual('doc');
-    expect(fo.getOperand(1).ldType()).toEqual('doc');
-    expect(fo.getOperand(2).ldType()).toEqual('non');
-    expect(fo.getOperand(3).ldType()).toEqual('docGroup');
-  });
-
-
-  it ('should remove a doc with an unspecified doc in a nested group', function () {
-    var vc = demoFactory.create();
-
-    // Wrap with direct element access
-    expect(vc.toQuery()).toEqual(
-      '(Titel = "Baum" & Veröffentlichungsort = "hihi" & (Titel = "Baum" | Veröffentlichungsort = "hihi")) | Untertitel = "huhu"'
-    );
-
-    var fo = vc.root().getOperand(0).getOperand(0);
-    expect(fo.key()).toEqual('Titel');
-    expect(fo.value()).toEqual('Baum');
-
-    // Add unspecified on the root group
-    _orOn(fo);
-
-    fo = vc.root().getOperand(0).getOperand(0);
-
-    expect(fo.operation()).toEqual('or');
-    expect(fo.getOperand(0).ldType()).toEqual('doc');
-    expect(fo.getOperand(1).ldType()).toEqual('non');
-
-    // Delete document
-    _delOn(fo.getOperand(0));
-
-    // The operand is now non
-    expect(vc.root().getOperand(0).getOperand(0).ldType()).toEqual('non');
-    expect(vc.root().getOperand(0).getOperand(1).ldType()).toEqual('doc');
-    expect(vc.root().getOperand(0).getOperand(2).ldType()).toEqual('docGroup');
-  });
-
-  it ('should remove an unspecified doc with an doc in a nested group', function () {
-    var vc = demoFactory.create();
-
-    // Wrap with direct element access
-    expect(vc.toQuery()).toEqual(
-      '(Titel = "Baum" & Veröffentlichungsort = "hihi" & (Titel = "Baum" | Veröffentlichungsort = "hihi")) | Untertitel = "huhu"'
-    );
-
-    var fo = vc.root().getOperand(0).getOperand(0);
-    expect(fo.key()).toEqual('Titel');
-    expect(fo.value()).toEqual('Baum');
-
-    // Add unspecified on the root group
-    _orOn(fo);
-
-    fo = vc.root().getOperand(0).getOperand(0);
-
-    expect(fo.operation()).toEqual('or');
-    expect(fo.getOperand(0).ldType()).toEqual('doc');
-    expect(fo.getOperand(1).ldType()).toEqual('non');
-
-    // Delete unspecified doc
-    _delOn(fo.getOperand(1));
-
-    // The operand is now non
-    fo = vc.root().getOperand(0);
-    expect(fo.getOperand(0).ldType()).toEqual('doc');
-    expect(fo.getOperand(0).key()).toEqual('Titel');
-    expect(fo.getOperand(0).value()).toEqual('Baum');
-    expect(fo.getOperand(1).ldType()).toEqual('doc');
-    expect(fo.getOperand(2).ldType()).toEqual('docGroup');
-  });
-
-
-  it ('should add on parent group (case "and")', function () {
-    var vc = complexVCFactory.create();
-
-    // Wrap with direct element access
-    expect(vc.toQuery()).toEqual(
-      'pubDate in 2014-12-05 & (title = "Hello World!" | foo = "bar")'
-    );
-
-    expect(vc.root().operands().length).toEqual(2);
-
-    // Add unspecified on the root group
-    _andOn(vc.root().getOperand(1));
-    expect(vc.toQuery()).toEqual(
-      'pubDate in 2014-12-05 & (title = "Hello World!" | foo = "bar")'
-    );
-
-    expect(vc.root().ldType()).toEqual('docGroup');
-    expect(vc.root().operands().length).toEqual(3);
-    expect(vc.root().getOperand(0).ldType()).toEqual('doc');
-    expect(vc.root().getOperand(1).ldType()).toEqual('docGroup');
-    expect(vc.root().getOperand(1).operation()).toEqual('or');
-    expect(vc.root().getOperand(2).ldType()).toEqual('non');
-
-    // Add another unspecified on the root group
-    _andOn(vc.root().getOperand(1));
-
-    expect(vc.root().operands().length).toEqual(4);
-    expect(vc.root().getOperand(0).ldType()).toEqual('doc');
-    expect(vc.root().getOperand(1).ldType()).toEqual('docGroup');
-    expect(vc.root().getOperand(2).ldType()).toEqual('non');
-    expect(vc.root().getOperand(3).ldType()).toEqual('non');
-
-    // Add another unspecified after the first doc
-    _andOn(vc.root().getOperand(0));
-
-    expect(vc.root().operands().length).toEqual(5);
-    expect(vc.root().getOperand(0).ldType()).toEqual('doc');
-    expect(vc.root().getOperand(1).ldType()).toEqual('non');
-    expect(vc.root().getOperand(2).ldType()).toEqual('docGroup');
-    expect(vc.root().getOperand(3).ldType()).toEqual('non');
-    expect(vc.root().getOperand(4).ldType()).toEqual('non');
-  });
-
-  it ('should wrap on root', function () {
-    var vc = KorAP.VirtualCollection.render(
-      {
-	"@type": 'koral:docGroup',
-	'operation' : 'operation:and',
-	'operands' : [
-	  {
-	    "@type": 'koral:doc',
-	    "key": 'pubDate',
-	    "match": 'match:eq',
-	    "value": '2014-12-05',
-	    "type": 'type:date'
-	  },
-	  {
-	    "@type" : 'koral:doc',
-	    'key' : 'foo',
-	    'value' : 'bar'
-	  }
-	]
-      }
-    );
-
-    // Wrap on root
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
-    expect(vc.root().ldType()).toEqual('docGroup');
-    expect(vc.root().operation()).toEqual('and');
-    _orOn(vc.root());
-    expect(vc.root().ldType()).toEqual('docGroup');
-    expect(vc.root().operation()).toEqual('or');
-
-    expect(vc.root().getOperand(0).ldType()).toEqual('docGroup');
-    expect(vc.root().getOperand(0).operation()).toEqual('and');
-  });
-
-  it ('should add on root (case "and")', function () {
-    var vc = KorAP.VirtualCollection.render(
-      {
-	"@type": 'koral:doc',
-	"key": 'pubDate',
-	"match": 'match:eq',
-	"value": '2014-12-05',
-	"type": 'type:date'
-      }
-    );
-
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05');
-    expect(vc.root().ldType()).toEqual('doc');
-    expect(vc.root().key()).toEqual('pubDate');
-    expect(vc.root().value()).toEqual('2014-12-05');
-
-    // Wrap on root
-    _andOn(vc.root());
-    expect(vc.root().ldType()).toEqual('docGroup');
-    expect(vc.root().operation()).toEqual('and');
-  });
-
-  it ('should add on root (case "or")', function () {
-    var vc = KorAP.VirtualCollection.render(
-      {
-	"@type": 'koral:doc',
-	"key": 'pubDate',
-	"match": 'match:eq',
-	"value": '2014-12-05',
-	"type": 'type:date'
-      }
-    );
-
-    expect(vc.toQuery()).toEqual('pubDate in 2014-12-05');
-    expect(vc.root().key()).toEqual('pubDate');
-    expect(vc.root().value()).toEqual('2014-12-05');
-
-    // Wrap on root
-    _orOn(vc.root());
-    expect(vc.root().ldType()).toEqual('docGroup');
-    expect(vc.root().operation()).toEqual('or');
-  });
-
-  it ('should support multiple sub groups per group', function () {
-    var vc = KorAP.VirtualCollection.render(
-      {
-	"@type": 'koral:docGroup',
-	'operation' : 'operation:or',
-	'operands' : [
-	  {
-	    "@type": 'koral:docGroup',
-	    'operation' : 'operation:and',
-	    'operands' : [
-	      {
-		"@type": 'koral:doc',
-		"key": 'title',
-		"value": 't1',
-	      },
-	      {
-		"@type" : 'koral:doc',
-		'key' : 'title',
-		'value' : 't2'
-	      }
+              }
 	    ]
 	  },
 	  {
-	    "@type": 'koral:docGroup',
-	    'operation' : 'operation:and',
-	    'operands' : [
-	      {
-		"@type": 'koral:doc',
-		"key": 'title',
-		"value": 't3',
-	      },
-	      {
-		"@type" : 'koral:doc',
-		'key' : 'title',
-		'value' : 't4'
-	      }
-	    ]
+	    "@type":"koral:doc",
+	    "key":"Untertitel",
+	    "value":"huhu",
+	    "match":"match:eq"
 	  }
 	]
-      }
-    );
-    expect(vc.toQuery()).toEqual(
-      '(title = "t1" & title = "t2") | (title = "t3" & title = "t4")'
-    );
-    expect(vc.root().operation()).toEqual('or');
-    expect(vc.root().getOperand(0).toQuery()).toEqual('title = "t1" & title = "t2"');
-    expect(vc.root().getOperand(1).toQuery()).toEqual('title = "t3" & title = "t4"');
+      });
 
-    _andOn(vc.root());
-
-    expect(vc.root().operation()).toEqual('and');
-    expect(vc.root().getOperand(0).ldType()).toEqual('docGroup');
-    expect(vc.root().getOperand(1).ldType()).toEqual('non');
-  });
-});
-
-describe('KorAP.Rewrite', function () {
-
-  it('should be initializable', function () {
-    var rewrite = KorAP.Rewrite.create({
-      "@type" : "koral:rewrite",
-      "operation" : "operation:modification",
-      "src" : "querySerializer",
-      "scope" : "tree"
+      expect(vc.toQuery()).toEqual(
+	'Titel = "Baum" | Veröffentlichungsort = "hihi" | Untertitel = "huhu"'
+      );
     });
-    expect(rewrite.toString()).toEqual('Modification of "tree" by "querySerializer"');
   });
 
-  it('should be deserialized by docs', function () {
-    var doc = KorAP.Doc.create(undefined,
-      {
-        "@type":"koral:doc",
-        "key":"Titel",
-        "value":"Baum",
-        "match":"match:eq"
+  describe('KorAP.Operators', function () {
+    it('should be initializable', function () {
+      var op = operatorsClass.create(true, false, false);
+      expect(op.and()).toBeTruthy();
+      expect(op.or()).not.toBeTruthy();
+      expect(op.del()).not.toBeTruthy();
+
+      op.and(false);
+      expect(op.and()).not.toBeTruthy();
+      expect(op.or()).not.toBeTruthy();
+      expect(op.del()).not.toBeTruthy();
+
+      op.or(true);
+      op.del(true);
+      expect(op.and()).not.toBeTruthy();
+      expect(op.or()).toBeTruthy();
+      expect(op.del()).toBeTruthy();
+
+      var e = op.element();
+      expect(e.getAttribute('class')).toEqual('operators');
+      expect(e.children[0].getAttribute('class')).toEqual('or');
+      expect(e.children[0].firstChild.data).toEqual('or');
+      expect(e.children[1].getAttribute('class')).toEqual('delete');
+      expect(e.children[1].firstChild.data).toEqual('×');
+
+      op.and(true);
+      op.del(false);
+      op.update();
+
+      e = op.element();
+      expect(e.getAttribute('class')).toEqual('operators');
+      expect(e.children[0].getAttribute('class')).toEqual('and');
+      expect(e.children[0].firstChild.data).toEqual('and');
+      expect(e.children[1].getAttribute('class')).toEqual('or');
+      expect(e.children[1].firstChild.data).toEqual('or');
+    });
+  });
+
+  describe('KorAP._delete (event)', function () {
+    var complexVCFactory = buildFactory(vcClass,{
+      "@type": 'koral:docGroup',
+      'operation' : 'operation:and',
+      'operands' : [
+	{
+	  "@type": 'koral:doc',
+	  "key": 'pubDate',
+	  "match": 'match:eq',
+	  "value": '2014-12-05',
+	  "type": 'type:date'
+	},
+	{
+	  "@type" : 'koral:docGroup',
+	  'operation' : 'operation:or',
+	  'operands' : [
+	    {
+	      '@type' : 'koral:doc',
+	      'key' : 'title',
+	      'value' : 'Hello World!'
+	    },
+	    {
+	      '@type' : 'koral:doc',
+	      'key' : 'foo',
+	      'value' : 'bar'
+	    }
+	  ]
+	}
+      ]
+    });
+
+    it('should clean on root docs', function () {
+      var vc = vcClass.render({
+	"@type": 'koral:doc',
+	"key": 'pubDate',
+	"match": 'match:eq',
+	"value": '2014-12-05',
+	"type": 'type:date'
       });
+      expect(vc.root().toQuery()).toEqual('pubDate in 2014-12-05');
+      expect(vc.root().element().lastChild.getAttribute('class')).toEqual('operators');
 
-    expect(doc.element().classList.contains('doc')).toBeTruthy();
-    expect(doc.element().classList.contains('rewritten')).toBe(false);
+      // Clean with delete from root
+      expect(vc.root().element().lastChild.lastChild.getAttribute('class')).toEqual('delete');
+      _delOn(vc.root());
+      expect(vc.root().toQuery()).toEqual('');
+      expect(vc.root().element().lastChild.lastChild.data).toEqual('⋯');
+    });
 
-    doc = KorAP.Doc.create(undefined,
-      {
-        "@type":"koral:doc",
-        "key":"Titel",
-        "value":"Baum",
-        "match":"match:eq",
-	"rewrites" : [
-	  {
-	    "@type" : "koral:rewrite",
-	    "operation" : "operation:modification",
-	    "src" : "querySerializer",
-	    "scope" : "tree"
-	  }
-	]
+    it('should remove on nested docs', function () {
+      var vc = vcClass.render(
+	{
+	  "@type": 'koral:docGroup',
+	  'operation' : 'operation:and',
+	  'operands' : [
+	    {
+	      "@type": 'koral:doc',
+	      "key": 'pubDate',
+	      "match": 'match:eq',
+	      "value": '2014-12-05',
+	      "type": 'type:date'
+	    },
+	    {
+	      "@type" : 'koral:doc',
+	      'key' : 'foo',
+	      'value' : 'bar'
+	    }
+	  ]
+	}
+      );
+
+      // Delete with direct element access
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
+      _delOn(vc.root().getOperand(0));
+
+      expect(vc.toQuery()).toEqual('foo = "bar"');
+      expect(vc.root().ldType()).toEqual('doc');
+    });
+
+    it('should clean on doc groups', function () {
+      var vc = vcClass.render(
+	{
+	  "@type": 'koral:docGroup',
+	  'operation' : 'operation:and',
+	  'operands' : [
+	    {
+	      "@type": 'koral:doc',
+	      "key": 'pubDate',
+	      "match": 'match:eq',
+	      "value": '2014-12-05',
+	      "type": 'type:date'
+	    },
+	    {
+	      "@type" : 'koral:doc',
+	      'key' : 'foo',
+	      'value' : 'bar'
+	    }
+	  ]
+	}
+      );
+
+      // Cleanwith direct element access
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
+      _delOn(vc.root());
+      expect(vc.toQuery()).toEqual('');
+      expect(vc.root().ldType()).toEqual('non');
+    });
+
+    it('should remove on nested doc groups (case of ungrouping 1)', function () {
+      var vc = complexVCFactory.create();
+
+      // Delete with direct element access
+      expect(vc.toQuery()).toEqual(
+	'pubDate in 2014-12-05 & (title = "Hello World!" | foo = "bar")'
+      );
+
+      // Remove hello world:
+      _delOn(vc.root().getOperand(1).getOperand(0));
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
+      expect(vc.root().ldType()).toEqual('docGroup');
+    });
+
+    it('should remove on nested doc groups (case of ungrouping 2)', function () {
+      var vc = complexVCFactory.create();
+
+      // Delete with direct element access
+      expect(vc.toQuery()).toEqual(
+	'pubDate in 2014-12-05 & (title = "Hello World!" | foo = "bar")'
+      );
+
+      // Remove bar
+      _delOn(vc.root().getOperand(1).getOperand(1));
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & title = "Hello World!"');
+      expect(vc.root().ldType()).toEqual('docGroup');
+      expect(vc.root().operation()).toEqual('and');
+    });
+
+    it('should remove on nested doc groups (case of root changing)', function () {
+      var vc = complexVCFactory.create();
+
+      // Delete with direct element access
+      expect(vc.toQuery()).toEqual(
+	'pubDate in 2014-12-05 & ' +
+	  '(title = "Hello World!" | foo = "bar")'
+      );
+
+      // Remove bar
+      _delOn(vc.root().getOperand(0));
+      expect(vc.toQuery()).toEqual('title = "Hello World!" | foo = "bar"');
+      expect(vc.root().ldType()).toEqual('docGroup');
+      expect(vc.root().operation()).toEqual('or');
+    });
+
+    it('should remove on nested doc groups (list flattening)', function () {
+      var vc = vcClass.render(
+	{
+	  "@type": 'koral:docGroup',
+	  'operation' : 'operation:or',
+	  'operands' : [
+	    {
+	      "@type": 'koral:doc',
+	      "key": 'pubDate',
+	      "match": 'match:eq',
+	      "value": '2014-12-05',
+	      "type": 'type:date'
+	    },
+	    {
+	      "@type" : 'koral:doc',
+	      'key' : 'foo',
+	      'value' : 'bar'
+	    },
+	    {
+	      "@type": 'koral:docGroup',
+	      'operation' : 'operation:and',
+	      'operands' : [
+		{
+		  "@type": 'koral:doc',
+		  "key": 'pubDate',
+		  "match": 'match:eq',
+		  "value": '2014-12-05',
+		  "type": 'type:date'
+		},
+		{
+		  "@type" : 'koral:docGroup',
+		  'operation' : 'operation:or',
+		  'operands' : [
+		    {
+		      '@type' : 'koral:doc',
+		      'key' : 'title',
+		      'value' : 'Hello World!'
+		    },
+		    {
+		      '@type' : 'koral:doc',
+		      'key' : 'yeah',
+		      'value' : 'juhu'
+		    }
+		  ]
+		}
+	      ]
+	    }
+	  ]
+	}
+      );
+
+      // Delete with direct element access
+      expect(vc.toQuery()).toEqual(
+	'pubDate in 2014-12-05 | foo = "bar" | ' +
+	  '(pubDate in 2014-12-05 & ' +
+	  '(title = "Hello World!" | yeah = "juhu"))'
+      );
+
+      expect(vc.root().ldType()).toEqual('docGroup');
+      expect(vc.root().operation()).toEqual('or');
+
+      // Operands and operators
+      expect(vc.element().firstChild.children.length).toEqual(4);
+      expect(vc.element().firstChild.lastChild.getAttribute('class')).toEqual('operators');
+
+      // Remove inner group and flatten
+      _delOn(vc.root().getOperand(2).getOperand(0));
+
+      expect(vc.toQuery()).toEqual(
+	'pubDate in 2014-12-05 | foo = "bar" | title = "Hello World!" | yeah = "juhu"'
+      );
+      expect(vc.root().ldType()).toEqual('docGroup');
+      expect(vc.root().operation()).toEqual('or');
+
+      // Operands and operators
+      expect(vc.element().firstChild.children.length).toEqual(5);
+      expect(vc.element().firstChild.lastChild.getAttribute('class')).toEqual('operators');
+    });
+  });
+
+  describe('KorAP._add (event)', function () {
+    var complexVCFactory = buildFactory(vcClass,{
+      "@type": 'koral:docGroup',
+      'operation' : 'operation:and',
+      'operands' : [
+	{
+	  "@type": 'koral:doc',
+	  "key": 'pubDate',
+	  "match": 'match:eq',
+	  "value": '2014-12-05',
+	  "type": 'type:date'
+	},
+	{
+	  "@type" : 'koral:docGroup',
+	  'operation' : 'operation:or',
+	  'operands' : [
+	    {
+	      '@type' : 'koral:doc',
+	      'key' : 'title',
+	      'value' : 'Hello World!'
+	    },
+	    {
+	      '@type' : 'koral:doc',
+	      'key' : 'foo',
+	      'value' : 'bar'
+	    }
+	  ]
+	}
+      ]
+    });
+
+    it('should add new unspecified doc with "and"', function () {
+      var vc = vcClass.render(
+	{
+	  "@type": 'koral:docGroup',
+	  'operation' : 'operation:and',
+	  'operands' : [
+	    {
+	      "@type": 'koral:doc',
+	      "key": 'pubDate',
+	      "match": 'match:eq',
+	      "value": '2014-12-05',
+	      "type": 'type:date'
+	    },
+	    {
+	      "@type" : 'koral:doc',
+	      'key' : 'foo',
+	      'value' : 'bar'
+	    }
+	  ]
+	}
+      );
+
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
+
+      var fc = vc.element().firstChild;
+      expect(fc.getAttribute('data-operation')).toEqual('and');
+      expect(fc.children.length).toEqual(3);
+      expect(fc.lastChild.getAttribute('class')).toEqual('operators');
+      expect(fc.children[0].getAttribute('class')).toEqual('doc');
+      expect(fc.children[1].getAttribute('class')).toEqual('doc');
+
+      // add with 'and' in the middle
+      _andOn(vc.root().getOperand(0));
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
+
+      fc = vc.element().firstChild;
+      expect(fc.getAttribute('data-operation')).toEqual('and');
+      expect(fc.children.length).toEqual(4);
+      expect(fc.lastChild.getAttribute('class')).toEqual('operators');
+
+      expect(fc.children[0].getAttribute('class')).toEqual('doc');
+      expect(fc.children[1].getAttribute('class')).toEqual('doc unspecified');
+      expect(fc.children[2].getAttribute('class')).toEqual('doc');
+    });
+
+    it('should add new unspecified doc with "or"', function () {
+      var vc = vcClass.render(
+	{
+	  "@type": 'koral:docGroup',
+	  'operation' : 'operation:and',
+	  'operands' : [
+	    {
+	      "@type": 'koral:doc',
+	      "key": 'pubDate',
+	      "match": 'match:eq',
+	      "value": '2014-12-05',
+	      "type": 'type:date'
+	    },
+	    {
+	      "@type" : 'koral:doc',
+	      'key' : 'foo',
+	      'value' : 'bar'
+	    }
+	  ]
+	}
+      );
+
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
+
+      var fc = vc.element().firstChild;
+      expect(fc.children.length).toEqual(3);
+      expect(fc.lastChild.getAttribute('class')).toEqual('operators');
+      expect(fc.children[0].getAttribute('class')).toEqual('doc');
+      expect(fc.children[1].getAttribute('class')).toEqual('doc');
+
+      // add with 'or' in the middle
+      _orOn(vc.root().getOperand(0));
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
+      fc = vc.element().firstChild;
+
+      expect(fc.getAttribute('data-operation')).toEqual('and');
+      expect(fc.children.length).toEqual(3);
+      expect(fc.children[0].getAttribute('class')).toEqual('docGroup');
+      expect(fc.children[0].getAttribute('data-operation')).toEqual('or');
+      expect(fc.children[1].getAttribute('class')).toEqual('doc');
+      expect(fc.children[2].getAttribute('class')).toEqual('operators');
+      expect(fc.lastChild.getAttribute('class')).toEqual('operators');
+
+      fc = vc.element().firstChild.firstChild;
+      expect(fc.children.length).toEqual(3);
+      expect(fc.children[0].getAttribute('class')).toEqual('doc');
+      expect(fc.children[1].getAttribute('class')).toEqual('doc unspecified');
+      expect(fc.children[2].getAttribute('class')).toEqual('operators');
+      expect(fc.lastChild.getAttribute('class')).toEqual('operators');
+    });
+
+    it('should add new unspecified doc with "and" before group', function () {
+      var vc = demoFactory.create();
+
+      // Wrap with direct element access
+      expect(vc.toQuery()).toEqual(
+	'(Titel = "Baum" & ' +
+	  'Veröffentlichungsort = "hihi" & ' +
+	  '(Titel = "Baum" | ' +
+	  'Veröffentlichungsort = "hihi")) | ' +
+	  'Untertitel = "huhu"'
+      );
+
+      expect(vc.root().getOperand(0).ldType()).toEqual('docGroup');
+      expect(vc.root().getOperand(0).operation()).toEqual('and');
+      expect(vc.root().getOperand(0).operands().length).toEqual(3);
+
+      // Add unspecified on the second doc
+      var secDoc = vc.root().getOperand(0).getOperand(1);
+      expect(secDoc.value()).toEqual('hihi');
+
+      // Add
+      _andOn(secDoc);
+
+      var fo = vc.root().getOperand(0);
+
+      expect(fo.ldType()).toEqual('docGroup');
+      expect(fo.operation()).toEqual('and');
+      expect(fo.operands().length).toEqual(4);
+
+      expect(fo.getOperand(0).ldType()).toEqual('doc');
+      expect(fo.getOperand(1).ldType()).toEqual('doc');
+      expect(fo.getOperand(2).ldType()).toEqual('non');
+      expect(fo.getOperand(3).ldType()).toEqual('docGroup');
+    });
+
+
+    it('should remove a doc with an unspecified doc in a nested group', function () {
+      var vc = demoFactory.create();
+
+      // Wrap with direct element access
+      expect(vc.toQuery()).toEqual(
+	'(Titel = "Baum" & Veröffentlichungsort = "hihi" & (Titel = "Baum" | Veröffentlichungsort = "hihi")) | Untertitel = "huhu"'
+      );
+
+      var fo = vc.root().getOperand(0).getOperand(0);
+      expect(fo.key()).toEqual('Titel');
+      expect(fo.value()).toEqual('Baum');
+
+      // Add unspecified on the root group
+      _orOn(fo);
+
+      fo = vc.root().getOperand(0).getOperand(0);
+
+      expect(fo.operation()).toEqual('or');
+      expect(fo.getOperand(0).ldType()).toEqual('doc');
+      expect(fo.getOperand(1).ldType()).toEqual('non');
+
+      // Delete document
+      _delOn(fo.getOperand(0));
+
+      // The operand is now non
+      expect(vc.root().getOperand(0).getOperand(0).ldType()).toEqual('non');
+      expect(vc.root().getOperand(0).getOperand(1).ldType()).toEqual('doc');
+      expect(vc.root().getOperand(0).getOperand(2).ldType()).toEqual('docGroup');
+    });
+
+
+    it('should remove an unspecified doc with an doc in a nested group', function () {
+      var vc = demoFactory.create();
+
+      // Wrap with direct element access
+      expect(vc.toQuery()).toEqual(
+	'(Titel = "Baum" & ' +
+	  'Veröffentlichungsort = "hihi" & ' +
+	  '(Titel = "Baum" ' +
+	  '| Veröffentlichungsort = "hihi")) | ' +
+	  'Untertitel = "huhu"'
+      );
+
+      var fo = vc.root().getOperand(0).getOperand(0);
+      expect(fo.key()).toEqual('Titel');
+      expect(fo.value()).toEqual('Baum');
+
+      // Add unspecified on the root group
+      _orOn(fo);
+
+      fo = vc.root().getOperand(0).getOperand(0);
+
+      expect(fo.operation()).toEqual('or');
+      expect(fo.getOperand(0).ldType()).toEqual('doc');
+      expect(fo.getOperand(1).ldType()).toEqual('non');
+
+      // Delete unspecified doc
+      _delOn(fo.getOperand(1));
+
+      // The operand is now non
+      fo = vc.root().getOperand(0);
+      expect(fo.getOperand(0).ldType()).toEqual('doc');
+      expect(fo.getOperand(0).key()).toEqual('Titel');
+      expect(fo.getOperand(0).value()).toEqual('Baum');
+      expect(fo.getOperand(1).ldType()).toEqual('doc');
+      expect(fo.getOperand(2).ldType()).toEqual('docGroup');
+    });
+
+
+    it('should add on parent group (case "and")', function () {
+      var vc = complexVCFactory.create();
+
+      // Wrap with direct element access
+      expect(vc.toQuery()).toEqual(
+	'pubDate in 2014-12-05 & (title = "Hello World!" | foo = "bar")'
+      );
+
+      expect(vc.root().operands().length).toEqual(2);
+
+      // Add unspecified on the root group
+      _andOn(vc.root().getOperand(1));
+      expect(vc.toQuery()).toEqual(
+	'pubDate in 2014-12-05 & (title = "Hello World!" | foo = "bar")'
+      );
+
+      expect(vc.root().ldType()).toEqual('docGroup');
+      expect(vc.root().operands().length).toEqual(3);
+      expect(vc.root().getOperand(0).ldType()).toEqual('doc');
+      expect(vc.root().getOperand(1).ldType()).toEqual('docGroup');
+      expect(vc.root().getOperand(1).operation()).toEqual('or');
+      expect(vc.root().getOperand(2).ldType()).toEqual('non');
+
+      // Add another unspecified on the root group
+      _andOn(vc.root().getOperand(1));
+
+      expect(vc.root().operands().length).toEqual(4);
+      expect(vc.root().getOperand(0).ldType()).toEqual('doc');
+      expect(vc.root().getOperand(1).ldType()).toEqual('docGroup');
+      expect(vc.root().getOperand(2).ldType()).toEqual('non');
+      expect(vc.root().getOperand(3).ldType()).toEqual('non');
+
+      // Add another unspecified after the first doc
+      _andOn(vc.root().getOperand(0));
+
+      expect(vc.root().operands().length).toEqual(5);
+      expect(vc.root().getOperand(0).ldType()).toEqual('doc');
+      expect(vc.root().getOperand(1).ldType()).toEqual('non');
+      expect(vc.root().getOperand(2).ldType()).toEqual('docGroup');
+      expect(vc.root().getOperand(3).ldType()).toEqual('non');
+      expect(vc.root().getOperand(4).ldType()).toEqual('non');
+    });
+
+    it('should wrap on root', function () {
+      var vc = vcClass.render(
+	{
+	  "@type": 'koral:docGroup',
+	  'operation' : 'operation:and',
+	  'operands' : [
+	    {
+	      "@type": 'koral:doc',
+	      "key": 'pubDate',
+	      "match": 'match:eq',
+	      "value": '2014-12-05',
+	      "type": 'type:date'
+	    },
+	    {
+	      "@type" : 'koral:doc',
+	      'key' : 'foo',
+	      'value' : 'bar'
+	    }
+	  ]
+	}
+      );
+
+      // Wrap on root
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
+      expect(vc.root().ldType()).toEqual('docGroup');
+      expect(vc.root().operation()).toEqual('and');
+      _orOn(vc.root());
+      expect(vc.root().ldType()).toEqual('docGroup');
+      expect(vc.root().operation()).toEqual('or');
+
+      expect(vc.root().getOperand(0).ldType()).toEqual('docGroup');
+      expect(vc.root().getOperand(0).operation()).toEqual('and');
+    });
+
+    it('should add on root (case "and")', function () {
+      var vc = vcClass.render(
+	{
+	  "@type": 'koral:doc',
+	  "key": 'pubDate',
+	  "match": 'match:eq',
+	  "value": '2014-12-05',
+	  "type": 'type:date'
+	}
+      );
+
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05');
+      expect(vc.root().ldType()).toEqual('doc');
+      expect(vc.root().key()).toEqual('pubDate');
+      expect(vc.root().value()).toEqual('2014-12-05');
+
+      // Wrap on root
+      _andOn(vc.root());
+      expect(vc.root().ldType()).toEqual('docGroup');
+      expect(vc.root().operation()).toEqual('and');
+    });
+
+    it('should add on root (case "or")', function () {
+      var vc = vcClass.render(
+	{
+	  "@type": 'koral:doc',
+	  "key": 'pubDate',
+	  "match": 'match:eq',
+	  "value": '2014-12-05',
+	  "type": 'type:date'
+	}
+      );
+
+      expect(vc.toQuery()).toEqual('pubDate in 2014-12-05');
+      expect(vc.root().key()).toEqual('pubDate');
+      expect(vc.root().value()).toEqual('2014-12-05');
+
+      // Wrap on root
+      _orOn(vc.root());
+      expect(vc.root().ldType()).toEqual('docGroup');
+      expect(vc.root().operation()).toEqual('or');
+    });
+
+    it('should support multiple sub groups per group', function () {
+      var vc = vcClass.render(
+	{
+	  "@type": 'koral:docGroup',
+	  'operation' : 'operation:or',
+	  'operands' : [
+	    {
+	      "@type": 'koral:docGroup',
+	      'operation' : 'operation:and',
+	      'operands' : [
+		{
+		  "@type": 'koral:doc',
+		  "key": 'title',
+		  "value": 't1',
+		},
+		{
+		  "@type" : 'koral:doc',
+		  'key' : 'title',
+		  'value' : 't2'
+		}
+	      ]
+	    },
+	    {
+	      "@type": 'koral:docGroup',
+	      'operation' : 'operation:and',
+	      'operands' : [
+		{
+		  "@type": 'koral:doc',
+		  "key": 'title',
+		  "value": 't3',
+		},
+		{
+		  "@type" : 'koral:doc',
+		  'key' : 'title',
+		  'value' : 't4'
+		}
+	      ]
+	    }
+	  ]
+	}
+      );
+      expect(vc.toQuery()).toEqual(
+	'(title = "t1" & title = "t2") | ' +
+	  '(title = "t3" & title = "t4")'
+      );
+      expect(vc.root().operation()).toEqual('or');
+      expect(vc.root().getOperand(0).toQuery()).toEqual('title = "t1" & title = "t2"');
+      expect(vc.root().getOperand(1).toQuery()).toEqual('title = "t3" & title = "t4"');
+
+      _andOn(vc.root());
+
+      expect(vc.root().operation()).toEqual('and');
+      expect(vc.root().getOperand(0).ldType()).toEqual('docGroup');
+      expect(vc.root().getOperand(1).ldType()).toEqual('non');
+    });
+  });
+
+  describe('KorAP.Rewrite', function () {
+
+    it('should be initializable', function () {
+      var rewrite = rewriteClass.create({
+	"@type" : "koral:rewrite",
+	"operation" : "operation:modification",
+	"src" : "querySerializer",
+	"scope" : "tree"
       });
+      expect(rewrite.toString()).toEqual('Modification of "tree" by "querySerializer"');
+    });
 
-    expect(doc.element().classList.contains('doc')).toBeTruthy();
-    expect(doc.element().classList.contains('rewritten')).toBeTruthy();
+    it('should be deserialized by docs', function () {
+      var doc = docClass.create(
+	undefined,
+	{
+	  "@type":"koral:doc",
+	  "key":"Titel",
+	  "value":"Baum",
+	  "match":"match:eq"
+	});
+
+      expect(doc.element().classList.contains('doc')).toBeTruthy();
+      expect(doc.element().classList.contains('rewritten')).toBe(false);
+
+      doc = docClass.create(
+	undefined,
+	{
+	  "@type":"koral:doc",
+	  "key":"Titel",
+	  "value":"Baum",
+	  "match":"match:eq",
+	  "rewrites" : [
+	    {
+	      "@type" : "koral:rewrite",
+	      "operation" : "operation:modification",
+	      "src" : "querySerializer",
+	      "scope" : "tree"
+	    }
+	  ]
+	});
+      
+      expect(doc.element().classList.contains('doc')).toBeTruthy();
+      expect(doc.element().classList.contains('rewritten')).toBeTruthy();
+    });
+    /*
+      it('should be deserialized by docGroups', function () {
+      });
+    */
   });
-/*
-  it('should be deserialized by docGroups', function () {
-  });
-*/
-});
-/*
-describe('KorAP.DocKey', function () {
-  it('should be initializable', function () {
+  /*
+    describe('KorAP.DocKey', function () {
+    it('should be initializable', function () {
     var docKey = KorAP.DocKey.create();
     expect(docKey.toString()).toEqual('...');
-  });
+    });
+    });
+  */
 });
-*/
diff --git a/dev/js/src/match.js b/dev/js/src/match.js
index beb4bca..d3aee67 100644
--- a/dev/js/src/match.js
+++ b/dev/js/src/match.js
@@ -9,11 +9,9 @@
  * - Scroll to match vertically per default
  */
 define([
-  'match/infolayer',
   'match/info',
   'util'
-], function (infoLayerClass,
-	     infoClass) {
+], function (infoClass) {
 
   // Localization values
   var loc   = KorAP.Locale;
@@ -21,8 +19,6 @@
   loc.SHOWINFO = loc.SHOWINFO || 'Show information';
   loc.CLOSE    = loc.CLOSE    || 'Close';
   
-  // KorAP._AvailableRE = new RegExp("^([^\/]+?)\/([^=]+?)(?:=(spans|rels|tokens))?$");
-  // KorAP._TermRE      = new RegExp("^(?:([^\/]+?)\/)?([^:]+?):(.+?)$");
   var _matchTerms  = ['corpusID', 'docID', 'textID', 'matchID', 'available'];
 
   /**
@@ -39,6 +35,7 @@
       return Object.create(this)._init(match);
     },
 
+
     /**
      * Initialize match.
      */
@@ -74,16 +71,11 @@
 	// Iterate over allowed match terms
 	for (var i in _matchTerms) {
 	  var term = _matchTerms[i];
-	  if (match[term] !== undefined) {
-	    this[term] = match[term];
-	  }
-	  else {
-	    this[term] = undefined;
-	  }
+	  this[term] = match[term] !== undefined ? match[term] : undefined;
 	};
       };
       
-      this._available = {
+      this._avail = {
 	tokens : [],
 	spans  : [],
 	rels   : []
@@ -95,8 +87,8 @@
 
 	// Create info layer objects
 	try {
-	  var layer = infoLayerClass.create(term);
-	  this._available[layer.type].push(layer);
+	  var layer = require('match/infolayer').create(term);
+	  this._avail[layer.type].push(layer);
 	}
 	catch (e) {
 	  continue;
@@ -111,7 +103,7 @@
      * Return a list of parseable tree annotations.
      */
     getSpans : function () {
-      return this._available.spans;
+      return this._avail.spans;
     },
 
 
@@ -119,7 +111,7 @@
      * Return a list of parseable token annotations.
      */
     getTokens : function () {
-      return this._available.tokens;
+      return this._avail.tokens;
     },
 
 
@@ -127,9 +119,10 @@
      * Return a list of parseable relation annotations.
      */
     getRels : function () {
-      return this._available.rels;
+      return this._avail.rels;
     },
 
+
     /**
      * Open match
      */
@@ -149,13 +142,18 @@
       // Add active class to element
       element.classList.add('active');
 
+      // Already there
+      if (element.classList.contains('action'))
+	return true;
+
       // Create action buttons
       var ul = document.createElement('ul');
       ul.classList.add('action', 'right');
-      element.appendChild(ul);
 
-      // Use localization
-      var loc = KorAP.Locale;
+      element.appendChild(ul);
+      element.classList.add('action');
+
+      // Todo: Open in new frame
 
       // Add close button
       var close = document.createElement('li');
@@ -191,17 +189,16 @@
       return true;
     },
 
+
     /**
      * Close info view
      */
     close : function () {
       this._element.classList.remove('active');
-
-/*
-      if (this._info !== undefined) {
-	this._info.destroy();
-      };
-*/
+      /* if (this._info !== undefined) {
+       *   this._info.destroy();
+       * };
+       */
     },
 
 
@@ -218,7 +215,7 @@
       if (this._element === undefined ||
 	  this._element === null)
 	return this._info;
-
+      
       // Info is already activated
       if (this._info._element !== undefined)
 	return this._info;
@@ -226,14 +223,12 @@
       return this._info;
     },
 
-
+    
     /**
      * Get match element.
      */
     element : function () {
-
-      // May be null
-      return this._element;
+      return this._element; // May be null
     }
   };
 });
diff --git a/dev/js/src/match/info.js b/dev/js/src/match/info.js
index b24bed5..c47f5ae 100644
--- a/dev/js/src/match/info.js
+++ b/dev/js/src/match/info.js
@@ -1,7 +1,16 @@
   /**
    * Information about a match.
    */
-define(['match/infolayer','match/table','match/tree', 'match/treemenu', 'util'], function (infoLayerClass, matchTableClass, matchTreeClass, matchTreeMenuClass) {
+define([
+  'match/infolayer',
+  'match/table',
+  'match/tree',
+  'match/treemenu',
+  'util'
+], function (infoLayerClass,
+	     matchTableClass,
+	     matchTreeClass,
+	     matchTreeMenuClass) {
 
   // TODO: Make this async
   KorAP.API.getMatchInfo = KorAP.API.getMatchInfo || function () {
diff --git a/dev/js/src/util.js b/dev/js/src/util.js
index d183c36..b3bb423 100644
--- a/dev/js/src/util.js
+++ b/dev/js/src/util.js
@@ -10,6 +10,11 @@
   };
 };
 
+var _quoteRE = new RegExp("([\"\\\\])", 'g');
+String.prototype.quote = function () {
+  return this.replace(_quoteRE, '\\$1');
+};
+
 // Add toggleClass method similar to jquery
 HTMLElement.prototype.toggleClass = function (c1, c2) {
   var cl = this.classList;
diff --git a/dev/js/src/vc.js b/dev/js/src/vc.js
index 48c5694..65ac5ca 100644
--- a/dev/js/src/vc.js
+++ b/dev/js/src/vc.js
@@ -45,14 +45,6 @@
   // KorAP._validGroupOpRE     = new RegExp("^(?:and|or)$");
   // KorAP._quote              = new RegExp("([\"\\\\])", 'g');
 
-  // Localization values
-  var loc   = (KorAP.Locale = KorAP.Locale || {} );
-  /*
-    loc.AND   = loc.AND   || 'and';
-    loc.OR    = loc.OR    || 'or';
-    loc.DEL   = loc.DEL   || '×';
-    loc.EMPTY = loc.EMPTY || '⋯'
-  */
 
   /**
    * Virtual Collection
@@ -93,7 +85,7 @@
 
       else {
 	// Add unspecified object
-	obj._root = KorAP.UnspecifiedDoc.create(obj);
+	obj._root = unspecDocClass.create(obj);
       };
 
       // Init element and update
diff --git a/dev/js/src/vc/doc.js b/dev/js/src/vc/doc.js
index 61c6439..700f410 100644
--- a/dev/js/src/vc/doc.js
+++ b/dev/js/src/vc/doc.js
@@ -133,7 +133,7 @@
     // Wrap a new operation around the doc element
     wrap : function (op) {
       var parent = this.parent();
-      var group = KorAP.DocGroup.create(parent);
+      var group = require('vc/docgroup').create(parent);
       group.operation(op);
       group.append(this);
       group.append();
@@ -353,7 +353,7 @@
 	return string + '/' + this.value() + '/';
 	break;
       case "string":
-	return string + '"' + this.value().replace(KorAP._quote, '\\$1') + '"';
+	return string + '"' + this.value().quote() + '"';
 	break;
       };
 
diff --git a/dev/js/src/vc/operators.js b/dev/js/src/vc/operators.js
index 312f75d..9b0ebd1 100644
--- a/dev/js/src/vc/operators.js
+++ b/dev/js/src/vc/operators.js
@@ -50,19 +50,19 @@
 
 
   // Add doc with 'and' relation
-  var _and = function () {
+  KorAP._and = function () {
     return _add(this, 'and');
   };
 
 
   // Add doc with 'or' relation
-  var _or = function () {
+  KorAP._or = function () {
     return _add(this, 'or');
   };
 
 
   // Remove doc or docGroup
-  var _delete = function () {
+  KorAP._delete = function () {
     var ref = this.parentNode.refTo;
     if (ref.parent().ldType() !== null) {
       return ref.parent().delOperand(ref).update();
@@ -98,7 +98,7 @@
       if (this._and === true) {
 	var andE = document.createElement('span');
 	andE.setAttribute('class', 'and');
-	andE.addEventListener('click', _and, false);
+	andE.addEventListener('click', KorAP._and, false);
 	andE.appendChild(
 	  document.createTextNode(loc.AND)
 	);
@@ -109,7 +109,7 @@
       if (this._or === true) {
 	var orE = document.createElement('span');
 	orE.setAttribute('class', 'or');
-	orE.addEventListener('click', _or, false);
+	orE.addEventListener('click', KorAP._or, false);
 	orE.appendChild(document.createTextNode(loc.OR));
 	op.appendChild(orE);
       };
@@ -119,7 +119,7 @@
 	var delE = document.createElement('span');
 	delE.setAttribute('class', 'delete');
 	delE.appendChild(document.createTextNode(loc.DEL));
-	delE.addEventListener('click', _delete, false);
+	delE.addEventListener('click', KorAP._delete, false);
 	op.appendChild(delE);
       };
 
diff --git a/dev/js/src/vc/rewrite.js b/dev/js/src/vc/rewrite.js
index 79ba4b3..f0dfe34 100644
--- a/dev/js/src/vc/rewrite.js
+++ b/dev/js/src/vc/rewrite.js
@@ -4,7 +4,6 @@
 define(['vc/jsonld', 'util'], function (jsonldClass) {
 
   var _validRewriteOpRE   = new RegExp("^(?:injec|modifica)tion$");
-  var _quote              = new RegExp("([\"\\\\])", 'g');
 
   return {
     // Construction method
@@ -87,12 +86,12 @@
 	this._scope === null ?
 	  'object' :
 	  '"' +
-	  this.scope().replace(_quote, '\\$1') +
+	  this.scope().quote() +
 	  '"'
       );
       str += ' by ' +
 	'"' +
-	this.src().replace(_quote, '\\$1') +
+	this.src().quote() +
 	'"';
       return str;
     }
diff --git a/dev/scss/header.scss b/dev/scss/header.scss
index 9876f80..2a49312 100644
--- a/dev/scss/header.scss
+++ b/dev/scss/header.scss
@@ -52,6 +52,54 @@
     margin: 0px;
     position: relative;
   }
+
+  .button {
+    &.right {
+      float: right;
+      display: inline-block;
+    }
+    &.top {
+      position: absolute;
+      display: block;
+      top: 0;
+      right: 0;
+      margin-right: 0;
+      width: 22px;
+      background-color: $dark-green;
+      text-align: center;
+      height: 100%;
+    }
+    color: $nearly-white;
+    line-height: 2em;
+    margin-right: $right-distance;
+    > a {
+      color: $nearly-white;
+      cursor:pointer;
+      position: relative;
+      font-size: 120%;
+      > span {
+	@include blind;
+      }
+    }
+    > a::after {
+      font-family: 'FontAwesome';
+    }
+    > a.tutorial::after {
+      content: $fa-tutorial;
+    }
+    > a.align.left::after {
+      content: $fa-left-align;
+    }
+    > a.align.right::after {
+      content: $fa-right-align;
+    }
+    > a.question::after {
+      content: $fa-question;
+    }
+    > a.login::after {
+      content: $fa-login;
+    }
+  }
 }
 
 
diff --git a/dev/scss/searchbar.scss b/dev/scss/searchbar.scss
index ac9927d..00c65e2 100644
--- a/dev/scss/searchbar.scss
+++ b/dev/scss/searchbar.scss
@@ -2,7 +2,6 @@
 @import "util";
 
 $border-size: 2px;
-$right-distance: 30px;
 
 /**
  * Input field
@@ -108,32 +107,3 @@
     }
   }
 }
-
-#button-right {
-  display: inline-block;
-  float: right;
-  color: $nearly-white;
-  line-height: 2em;
-  margin-right: $right-distance;
-  > a {
-    color: $nearly-white;
-    cursor:pointer;
-    position: relative;
-    font-size: 120%;
-    > span {
-      @include blind;
-    }
-  }
-  > a::after {
-    font-family: 'FontAwesome';
-  }
-  > a.tutorial::after {
-    content: '\f19d';
-  }
-  > a.align.left::after {
-    content: '\f036';
-  }
-  > a.align.right::after {
-    content: '\f038';
-  }
-}
diff --git a/dev/scss/sidebar.scss b/dev/scss/sidebar.scss
index a94c1d8..3adc1b4 100644
--- a/dev/scss/sidebar.scss
+++ b/dev/scss/sidebar.scss
@@ -3,7 +3,7 @@
 
 $border-size: 2px;
 
-#sidebar {
+aside {
   // box-shadow: 2px 2px 5px darken($dark-green, 15%);
   // box-shadow: $choose-box-shadow;
   outline: none;
@@ -122,7 +122,7 @@
 }
 
 
-#sidebar:not(:focus):not(.active) {
+aside:not(:focus):not(.active) {
   margin-left: -1 * ($logo-left-distance - 15px);
 //  box-shadow: none;
 /*
diff --git a/dev/scss/tutorial.scss b/dev/scss/tutorial.scss
index 0b03cd0..4b4345b 100644
--- a/dev/scss/tutorial.scss
+++ b/dev/scss/tutorial.scss
@@ -44,7 +44,7 @@
 
 body.embedded {
   background-color: $nearly-white;
-  #sidebar {
+  aside {
 /*
     border-right: {
       width: $border-size;
diff --git a/dev/scss/util.scss b/dev/scss/util.scss
index 3321de1..6d2172f 100644
--- a/dev/scss/util.scss
+++ b/dev/scss/util.scss
@@ -90,9 +90,11 @@
  * Margins
  */
 $standard-margin: 30px;
+$right-distance: 30px;
 $right-match-distance: 20px;
 $logo-left-distance: 230px;
 
+
 @mixin blind {
   position: absolute;
   margin-left: -3000px;
@@ -156,14 +158,20 @@
 /**
  * Font Awesome symbols
  */
-$fa-bars:     "\f0c9";
-$fa-extlink:  "\f08e";
-$fa-up:       "\f0d8";
-$fa-down:     "\f0d7";
-$fa-close:    "\f00d";
-$fa-info:     "\f05a";
-$fa-elipsis:  "\f141";
-$fa-previous: "\f0d9";
-$fa-next:     "\f0da";
-$fa-search:   "\f002";
-$fa-rewrite:  "\f040"; // "\f14b"
\ No newline at end of file
+$fa-bars:        "\f0c9";
+$fa-extlink:     "\f08e";
+$fa-up:          "\f0d8";
+$fa-down:        "\f0d7";
+$fa-close:       "\f00d";
+$fa-info:        "\f05a";
+$fa-elipsis:     "\f141";
+$fa-previous:    "\f0d9";
+$fa-next:        "\f0da";
+$fa-search:      "\f002";
+$fa-rewrite:     "\f040"; // "\f14b"
+$fa-login:       "\f090";
+$fa-logout:      "\f08b";
+$fa-tutorial:    "\f19d";
+$fa-left-align:  "\f036";
+$fa-right-align: "\f038";
+$fa-question:    "\f128"; // "\f059";
\ No newline at end of file