Add stringification to corpusByMatch query

Change-Id: I223e838d622465994ed0177e29bd7a73db9a0728
diff --git a/dev/js/spec/corpusByMatchSpec.js b/dev/js/spec/corpusByMatchSpec.js
index d2588b0..6984d1d 100644
--- a/dev/js/spec/corpusByMatchSpec.js
+++ b/dev/js/spec/corpusByMatchSpec.js
@@ -3,15 +3,16 @@
  */
 
 function metaTableFactory () {
-  var meta = document.createElement('div');
-  meta.className = 'view metaTable';
+  let meta = document.createElement('div');
+  meta.className = 'metatable';
   meta.innerHTML =
     "    <dl class=\"flex\">" +
     "      <div>" +
-    "        <dt title=\"author\">author</dt>" +
+    "        <dt title=\"author\" data-type=\"type:string\">author</dt>" +
     "        <dd>Sprachpfleger, u.a.</dd>" +
     "      </div>" +
     "      <div>" +
+    "        <dt title=\"foundries\" data-type=\"type:keywords\">foundries</dt>" +
     "        <dd class=\"metakeyvalues\">" +
     "          <div>corenlp</div>" +
     "          <div>corenlp/constituency</div>" +
@@ -26,13 +27,15 @@
     "        </dd>" +
     "      </div>" +
     "    </dl>";
-  var parent = document.createElement("div");
+  let parent = document.createElement("div");
+  parent.className = 'metatable view';
   parent.appendChild(meta);
   return meta;
 };
 
 define(['match/corpusByMatch'], function (cbmClass) {  
   describe('KorAP.CorpusByMatch', function () {
+
     it('should be initializable', function () {
       expect(function () {
         cbmClass.create()
@@ -44,7 +47,26 @@
         }
       ).toThrow(new Error("Requires element"));
 
-      expect(cbmClass.create(metaTableFactory()).toString()).toEqual("");
+      expect(cbmClass.create(metaTableFactory()).toQuery()).toEqual("");
+    });
+
+    it('should open the corpusByMatch assistant', function () {
+      let metaTable = metaTableFactory();
+      let cbm = cbmClass.create(metaTable);
+      expect(cbm.toQuery()).toEqual("");
+
+      expect(metaTable.parentNode.querySelector("div.vc.fragment")).toBeNull();
+
+      // click on author:
+      metaTable.querySelector("dl dt[title=author] + dd").click();
+      expect(metaTable.parentNode.querySelector("div.vc.fragment")).not.toBeNull();
+
+      expect(cbm.toQuery()).toEqual('(author = "Sprachpfleger, u.a.")');
+
+      // click on list:
+      metaTable.querySelector("dl dt[title=foundries] + dd div:nth-of-type(3)").click();
+
+      expect(cbm.toQuery()).toEqual('(author = "Sprachpfleger, u.a." & foundries = "corenlp/morpho")');
     });
   });
 });
diff --git a/dev/js/spec/matchSpec.js b/dev/js/spec/matchSpec.js
index 4b865bc..b27ddbd 100644
--- a/dev/js/spec/matchSpec.js
+++ b/dev/js/spec/matchSpec.js
@@ -710,49 +710,48 @@
 	  	  
 	  // Meta information should be parsed into a list
 	  it('should parse in a meta view', function(){
-		expect(mel.tagName).toEqual('DL');
-		expect(mel.children[0].tagName).toEqual('DIV');
-		expect(mel.children[0].children[0].tagName).toEqual('DT');
-		expect(mel.children[0].children[0].attributes[0].name).toEqual('title');
-    expect(mel.children[0].children[1].tagName).toEqual('DD');
-    expect(mel.children[0].children[1].getAttribute('data-type')).toEqual('type:text')
+		  expect(mel.tagName).toEqual('DL');
+		  expect(mel.children[0].tagName).toEqual('DIV');
+		  expect(mel.children[0].children[0].tagName).toEqual('DT');
+		  expect(mel.children[0].children[0].attributes[0].name).toEqual('title');
+      expect(mel.children[0].children[1].tagName).toEqual('DD');
+      expect(mel.children[0].children[1].getAttribute('data-type')).toEqual('type:text')
 		
-		expect(mel.children[0].children[0].firstChild.nodeValue).toEqual('author');
-		expect(mel.children[0].children[1].firstChild.nodeValue).toEqual('Sprachpfleger, u.a.');
-		expect(mel.children[0].children[0].attributes[0].value).toEqual('author');
+		  expect(mel.children[0].children[0].firstChild.nodeValue).toEqual('author');
+		  expect(mel.children[0].children[1].firstChild.nodeValue).toEqual('Sprachpfleger, u.a.');
+		  expect(mel.children[0].children[0].attributes[0].value).toEqual('author');
 	  });
 	  
 	  
-	 /* The keywords in the meta information list should be formatted to be able  
-	 to chose each keyword separately in the corpusByMatch assistant. */
-	 it('keywords should be formatted', function(){
+	  /* The keywords in the meta information list should be formatted to be able  
+	     to chose each keyword separately in the corpusByMatch assistant. */
+	  it('keywords should be formatted', function(){
 		
-		 //type:string or type:keyword should b not relevant
-     expect(mel.children[1].children[1].getAttribute('data-type')).toEqual('type:string')
-		 expect(mel.children[1].children[1].classList.contains('metakeyvalues')).toBeTruthy;
-		 expect(mel.children[1].children[1].children[0].tagName).toEqual('DIV');
-		 expect(mel.children[1].children[1].children[0].firstChild.nodeValue).toEqual('corenlp');
-		 expect(mel.children[1].children[1].children[1].tagName).toEqual('DIV');
-		 expect(mel.children[1].children[1].children[1].firstChild.nodeValue).toEqual('corenlp\/constituency');
-		 
-		 expect(mel.children[2].children[1].classList.contains('metakeyvalues')).toBeTruthy;
-		 expect(mel.children[2].children[1].children[0].tagName).toEqual('DIV');
-		 expect(mel.children[2].children[1].children[0].firstChild.nodeValue).toEqual('kultur');
-		 expect(mel.children[2].children[1].children[1].tagName).toEqual('DIV');
-		 expect(mel.children[2].children[1].children[1].firstChild.nodeValue).toEqual('film');		 
+		  //type:string or type:keyword should b not relevant
+      expect(mel.children[1].children[1].getAttribute('data-type')).toEqual('type:string')
+		  expect(mel.children[1].children[1].classList.contains('metakeyvalues')).toBeTruthy;
+		  expect(mel.children[1].children[1].children[0].tagName).toEqual('DIV');
+		  expect(mel.children[1].children[1].children[0].firstChild.nodeValue).toEqual('corenlp');
+		  expect(mel.children[1].children[1].children[1].tagName).toEqual('DIV');
+		  expect(mel.children[1].children[1].children[1].firstChild.nodeValue).toEqual('corenlp\/constituency');
+		  
+		  expect(mel.children[2].children[1].classList.contains('metakeyvalues')).toBeTruthy;
+		  expect(mel.children[2].children[1].children[0].tagName).toEqual('DIV');
+		  expect(mel.children[2].children[1].children[0].firstChild.nodeValue).toEqual('kultur');
+		  expect(mel.children[2].children[1].children[1].tagName).toEqual('DIV');
+		  expect(mel.children[2].children[1].children[1].firstChild.nodeValue).toEqual('film');		 
 	  }); 
   
   
-	 // Meta information should be sorted alphabetically
-  it('should be alphabetically sorted', function(){
-  	var a = mel.children[0].children[0].firstChild.nodeValue;
-  	var b = mel.children[1].children[0].firstChild.nodeValue;
-  	var c = mel.children[2].children[0].firstChild.nodeValue;
-  	expect(a.localeCompare(b)).toBe(-1);
-  	expect(b.localeCompare(c)).toBe(-1);
+	  // Meta information should be sorted alphabetically
+    it('should be alphabetically sorted', function(){
+  	  var a = mel.children[0].children[0].firstChild.nodeValue;
+  	  var b = mel.children[1].children[0].firstChild.nodeValue;
+  	  var c = mel.children[2].children[0].firstChild.nodeValue;
+  	  expect(a.localeCompare(b)).toBe(-1);
+  	  expect(b.localeCompare(c)).toBe(-1);
+    });  
   });
-  
-});
   // table = view.toTable();
   // table.sortBy('');
   // table.element();
diff --git a/dev/js/src/match/corpusByMatch.js b/dev/js/src/match/corpusByMatch.js
index 59038a0..050ecb7 100644
--- a/dev/js/src/match/corpusByMatch.js
+++ b/dev/js/src/match/corpusByMatch.js
@@ -49,14 +49,14 @@
       // Meta information is a single value
       if (target.tagName === 'DD') {
         type = target.getAttribute("data-type");
-        key  = target.previousSibling.innerText;
+        key  = target.previousElementSibling.innerText;
         value = target.innerText;
       }
 
       // Meta information is in a list
       else if (target.tagName === 'DIV') {
         type = target.parentNode.getAttribute("data-type");
-        key = target.parentNode.previousSibling.innerText;
+        key = target.parentNode.previousElementSibling.innerText;
         value = target.innerText;
       };
 
@@ -64,6 +64,8 @@
       if (type === "type:store")
         return;
 
+      type = type || "type:string";
+      
       // Add or remove the constraint to the fragment
       if (key && value) {
         if (target.classList.contains("chosen")) {
@@ -94,8 +96,8 @@
     },
 
     // Stringify annotation
-    toString : function () {
-      return '';
+    toQuery : function () {
+      return this._fragment.toQuery();
     }
   };
 });
diff --git a/dev/js/src/vc/fragment.js b/dev/js/src/vc/fragment.js
index a623549..a03e845 100644
--- a/dev/js/src/vc/fragment.js
+++ b/dev/js/src/vc/fragment.js
@@ -145,6 +145,19 @@
         e.appendChild(root);
         
       return this;
-    }      
+    },
+
+    toQuery : function () {
+      if (this._operands.length === 0)
+        return '';
+
+      let str = '(' + this._operands.map(
+        function (item) {
+          return item[0] + ' = "' + new String(item[1]).quote() + '"';
+        }
+      ).join(" & ");
+      
+      return str + ')';
+    }
   }
 });