Introduce vc fragments for corpusByMatch

Change-Id: I0376bc646555181efa76608fe80f63c12aec80e0
diff --git a/dev/js/spec/vcSpec.js b/dev/js/spec/vcSpec.js
index 33953b5..bab1747 100644
--- a/dev/js/spec/vcSpec.js
+++ b/dev/js/spec/vcSpec.js
@@ -11,7 +11,8 @@
   'vc/unspecified',
   'vc/operators',
   'vc/rewrite',
-  'vc/stringval'
+  'vc/stringval',
+  'vc/fragment'
 ], function (vcClass,
              docClass,
              menuClass,
@@ -21,7 +22,8 @@
              unspecifiedClass,
              operatorsClass,
              rewriteClass,
-             stringValClass) {
+             stringValClass,
+             fragmentClass) {
 
   KorAP._vcKeyMenu = undefined;
 
@@ -2869,4 +2871,77 @@
       expect(vc.builder().firstChild.firstChild.innerText).toEqual('x');
     });
   });
+
+  describe('KorAP.VC.Fragment', function () {
+    it('should be initializable', function () {
+      var f = fragmentClass.create();
+      var e = f.element();
+      expect(e.classList.contains('vc')).toBeTruthy();
+      expect(e.classList.contains('fragment')).toBeTruthy();
+      expect(e.children.length).toEqual(0);
+    });
+
+    it('should be expansable', function () {
+      var f = fragmentClass.create();
+      f.add("author", "Peter");
+
+      var root = f.element().firstChild;
+
+      expect(root.classList.contains("doc")).toBeTruthy();
+      expect(root.children[0].tagName).toEqual("SPAN");
+      expect(root.children[0].textContent).toEqual("author");
+      expect(root.children[1].tagName).toEqual("SPAN");
+      expect(root.children[1].textContent).toEqual("eq");
+      expect(root.children[2].tagName).toEqual("SPAN");
+      expect(root.children[2].textContent).toEqual("Peter");
+
+      f.add("title", "Example");
+
+      root = f.element().firstChild;
+
+      expect(root.classList.contains("docGroup")).toBeTruthy();
+
+      var doc = root.children[0];
+
+      expect(doc.children[0].tagName).toEqual("SPAN");
+      expect(doc.children[0].textContent).toEqual("author");
+      expect(doc.children[1].tagName).toEqual("SPAN");
+      expect(doc.children[1].textContent).toEqual("eq");
+      expect(doc.children[2].tagName).toEqual("SPAN");
+      expect(doc.children[2].textContent).toEqual("Peter");
+      
+      doc = root.children[1];
+
+      expect(doc.children[0].tagName).toEqual("SPAN");
+      expect(doc.children[0].textContent).toEqual("title");
+      expect(doc.children[1].tagName).toEqual("SPAN");
+      expect(doc.children[1].textContent).toEqual("eq");
+      expect(doc.children[2].tagName).toEqual("SPAN");
+      expect(doc.children[2].textContent).toEqual("Example");
+    });
+
+
+    it('should be reducible', function () {
+      var f = fragmentClass.create();
+      f.add("author", "Peter");
+      f.add("title", "Example");
+
+      var root = f.element().firstChild;
+      expect(root.classList.contains("docGroup")).toBeTruthy();
+
+      expect(root.children.length).toEqual(2);
+
+      f.remove("author","Peter");
+
+      root = f.element().firstChild;
+      expect(root.classList.contains("doc")).toBeTruthy();
+
+      expect(root.children[0].tagName).toEqual("SPAN");
+      expect(root.children[0].textContent).toEqual("title");
+      expect(root.children[1].tagName).toEqual("SPAN");
+      expect(root.children[1].textContent).toEqual("eq");
+      expect(root.children[2].tagName).toEqual("SPAN");
+      expect(root.children[2].textContent).toEqual("Example");
+    });
+  });
 });
diff --git a/dev/js/src/vc.js b/dev/js/src/vc.js
index bed434f..d2029d0 100644
--- a/dev/js/src/vc.js
+++ b/dev/js/src/vc.js
@@ -296,7 +296,7 @@
     },
     
     /**
-     * Get the element associated with the virtual collection
+     * Get the element associated with the virtual corpus
      */
     element : function() {
       if (this._element !== undefined) {
diff --git a/dev/js/src/vc/fragment.js b/dev/js/src/vc/fragment.js
new file mode 100644
index 0000000..a1892c8
--- /dev/null
+++ b/dev/js/src/vc/fragment.js
@@ -0,0 +1,131 @@
+/**
+ * Create a virtual corpus fragment,
+ * that can be shown and merge with the
+ * main VC.
+ *
+ * @author Nils Diewald
+ */
+
+define(['util'], function () {
+  "use strict";
+
+  // Create a VC doc
+  function _doc (op) {
+    var doc = document.createElement('div');
+    doc.setAttribute('class','doc');
+          
+    var key = doc.addE('span');
+    key.setAttribute('class','key');
+    key.addT(op[0]);
+
+    var match = doc.addE('span');
+    match.setAttribute('class','match');
+    match.addT('eq');
+
+    var value = doc.addE('span');
+    value.setAttribute('class', 'value');
+    value.addT(op[1]);
+      
+    return doc;
+  };
+
+  
+  return {
+
+    create : function () {
+      var obj = Object.create(this);
+      obj._operands = [];
+      return obj;
+    },
+
+
+    /**
+     * Add document constraint to fragment
+     */
+    add : function (key, value, type) {
+      for (var i in this._operands) {
+        var op = this._operands[i];
+        if (op[0] === key && op[1] === value) {
+          array.splice(index, 1);
+        };
+      };
+      this._operands.push([key, value, type]);
+      this.update();
+    },
+
+    
+    /**
+     * Remove document constraint from fragment
+     */
+    remove : function (key, value) {
+      for (var i in this._operands) {
+        var op = this._operands[i];
+        if (op[0] === key && op[1] === value) {
+          this._operands.splice(i, 1);
+          this.update();
+          return;
+        };
+      };
+      return;
+    },
+
+    
+    /**
+     * Add fragment constraints to VC.
+     */
+    mergeWithVC : function () {
+    },
+
+
+    /**
+     * Get the element associated with the virtual corpus
+     */
+    element : function () {
+      if (this._element !== undefined) {
+        return this._element;
+      };
+
+      this._element = document.createElement('div');
+      this._element.classList.add('vc', 'fragment');
+      return this._element;
+    },
+
+
+    /**
+     * Update the whole object based on the underlying data structure
+     */
+    update : function() {
+
+      // <div class="docGroup" data-operation="and">
+      //   <div class="doc">
+      //     <span class="key">author</span>
+      //     <span class="match">eq</span>
+      //     <span class="value">Baum</span>
+      //   </div>
+      // </div>
+      var root;
+      var l = this._operands.length;
+      if (l > 1) {
+
+        root = document.createElement('div');
+        root.setAttribute('class','docGroup');
+        root.setAttribute('data-operation', 'and');
+
+        for (var i in this._operands) {
+          root.appendChild(_doc(this._operands[i]));
+        };
+      }
+      else if (l == 1) {
+        root = _doc(this._operands[0]);
+      };
+
+      var e = this.element();
+      if (e.firstChild)
+        e.replaceChild(root, e.firstChild);
+      else
+        e.appendChild(root);
+        
+      return this;
+    }      
+  }
+});