Test suite now relies on requirejs as well
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('...');
-  });
+    });
+    });
+  */
 });
-*/