Improve querycreator to single-quote-escape more tokens

Change-Id: I4db4f2f90f647ec49368b5e0fd3ad21d0a186a48
diff --git a/Changes b/Changes
index 78dcd2d..ebe373e 100755
--- a/Changes
+++ b/Changes
@@ -3,6 +3,8 @@
         - Updated dependency on M::P::Notifications to
           be compatible with recent versions of Mojolicious.
         - Introduce cuts in token views.
+        - Improve QueryCreator to single-quote-escape special
+          characters in orth-line and include more symbols.
 
 0.33 2019-03-28
         - Fix problem with serialization and deserialization
diff --git a/dev/js/spec/queryCreatorSpec.js b/dev/js/spec/queryCreatorSpec.js
index 70f3f34..c0953ba 100644
--- a/dev/js/spec/queryCreatorSpec.js
+++ b/dev/js/spec/queryCreatorSpec.js
@@ -63,7 +63,7 @@
     "          <th>Layer</th>" +
     "          <th>Der</th>" +
     "          <th>älteste</th>" +
-    "          <th>lebende</th>" +
+    "          <th>lebende und sterbende</th>" +
     "          <th class=\"mark\">Baum</th>" +
     "        </tr>" +
     "      </thead>" +
@@ -93,6 +93,14 @@
     "          <td></td>" +
     "          <td class=\"mark\">NN</td>" +
     "        </tr>" +
+    "        <tr tabindex=\"0\">" +
+    "          <th>tt</th>" +
+    "          <th>l</th>" +
+    "          <td>Lese|Lesen</td>" +
+    "          <td>a b</td>" +
+    "          <td></td>" +
+    "          <td class=\"mark\">NN</td>" +
+    "        </tr>" +
     "      </tbody>" +
     "    </table>";
   var info = document.createElement('div');
@@ -508,11 +516,11 @@
       expect(qc.element().className).toEqual("query fragment");
 
       var cell = matchTable.querySelector("thead > tr > th:nth-child(5)");
-      expect(cell.innerString()).toEqual("lebende");
+      expect(cell.innerString()).toEqual("lebende und sterbende");
       expect(cell.classList.contains("chosen")).toBe(false);
       cell.click();
       expect(cell.classList.contains("chosen")).toBeTruthy();
-      expect(qc.toString()).toEqual("[orth=lebende]");
+      expect(qc.toString()).toEqual("[orth='lebende und sterbende']");
 
       // Check complex cell
       cell = matchTable.querySelector("tbody > tr:nth-child(1) > td:nth-child(6)");
@@ -520,7 +528,7 @@
       expect(cell.classList.contains("chosen")).toBe(false);
       cell.click();
       expect(cell.classList.contains("chosen")).toBe(false);
-      expect(qc.toString()).toEqual("[orth=lebende]");
+      expect(qc.toString()).toEqual("[orth='lebende und sterbende']");
 
       // Check complex cell div
       cell = matchTable.querySelector("tbody > tr:nth-child(1) > td:nth-child(6) > div:nth-child(1)");
@@ -528,7 +536,7 @@
       expect(cell.classList.contains("chosen")).toBe(false);
       cell.click();
       expect(cell.classList.contains("chosen")).toBe(true);
-      expect(qc.toString()).toEqual("[orth=lebende][corenlp/p=case:nom]");
+      expect(qc.toString()).toEqual("[orth='lebende und sterbende'][corenlp/p=case:nom]");
       var cell = cell;
 
       cell = matchTable.querySelector("tbody > tr:nth-child(1) > td:nth-child(6) > div:nth-child(3)");
@@ -536,7 +544,7 @@
       expect(cell.classList.contains("chosen")).toBe(false);
       cell.click();
       expect(cell.classList.contains("chosen")).toBe(true);
-      expect(qc.toString()).toEqual("[orth=lebende][corenlp/p=case:nom & corenlp/p=number:sg]");
+      expect(qc.toString()).toEqual("[orth='lebende und sterbende'][corenlp/p=case:nom & corenlp/p=number:sg]");
       var cell2 = cell;
 
       cell = matchTable.querySelector("tbody > tr:nth-child(1) > td:nth-child(6) > div:nth-child(2)");
@@ -544,7 +552,7 @@
       expect(cell.classList.contains("chosen")).toBe(false);
       cell.click();
       expect(cell.classList.contains("chosen")).toBe(true);
-      expect(qc.toString()).toEqual("[orth=lebende][(corenlp/p=gender:fem | corenlp/p=gender:masc) & corenlp/p=case:nom & corenlp/p=number:sg]");
+      expect(qc.toString()).toEqual("[orth='lebende und sterbende'][(corenlp/p=gender:fem | corenlp/p=gender:masc) & corenlp/p=case:nom & corenlp/p=number:sg]");
       var cell3 = cell;
 
       // Remove cell again
@@ -553,7 +561,7 @@
       expect(cell.classList.contains("chosen")).toBe(true);
       cell.click();
       expect(cell.classList.contains("chosen")).toBe(false);
-      expect(qc.toString()).toEqual("[orth=lebende][(corenlp/p=gender:fem | corenlp/p=gender:masc) & corenlp/p=case:nom]");
+      expect(qc.toString()).toEqual("[orth='lebende und sterbende'][(corenlp/p=gender:fem | corenlp/p=gender:masc) & corenlp/p=case:nom]");
 
       // Remove cell again
       cell = cell3;
@@ -561,7 +569,7 @@
       expect(cell.classList.contains("chosen")).toBe(true);
       cell.click();
       expect(cell.classList.contains("chosen")).toBe(false);
-      expect(qc.toString()).toEqual("[orth=lebende][corenlp/p=case:nom]");
+      expect(qc.toString()).toEqual("[orth='lebende und sterbende'][corenlp/p=case:nom]");
     });
 
 
@@ -614,6 +622,27 @@
       cell.click();
       expect(cell.classList.contains("chosen")).toBeTruthy();
       expect(qc.toString()).toEqual("[opennlp/p='morphemes:.::_SORSZ \\\\ZERO::NOM \\\'period::PUNCT\\\'']");
+      cell.click()
+      expect(cell.classList.contains("chosen")).toBe(false);
+      expect(qc.toString()).toEqual("");
+
+      cell = matchTable.querySelector("tbody > tr:nth-child(3) > td:nth-child(3)");
+      expect(cell.classList.contains("chosen")).toBe(false);
+      cell.click();
+      expect(cell.classList.contains("chosen")).toBeTruthy();
+      expect(qc.toString()).toEqual("[tt/l='Lese|Lesen']");
+      cell.click()
+      expect(cell.classList.contains("chosen")).toBe(false);
+      expect(qc.toString()).toEqual("");
+
+      cell = matchTable.querySelector("tbody > tr:nth-child(3) > td:nth-child(4)");
+      expect(cell.classList.contains("chosen")).toBe(false);
+      cell.click();
+      expect(cell.classList.contains("chosen")).toBeTruthy();
+      expect(qc.toString()).toEqual("[tt/l='a b']");
+      cell.click()
+      expect(cell.classList.contains("chosen")).toBe(false);
+      expect(qc.toString()).toEqual("");
     });
 
     it('should respect marked elements', function () {
diff --git a/dev/js/src/match/querycreator.js b/dev/js/src/match/querycreator.js
index e54ff65..8c60ff8 100644
--- a/dev/js/src/match/querycreator.js
+++ b/dev/js/src/match/querycreator.js
@@ -19,7 +19,7 @@
   const loc = KorAP.Locale;
   loc.NEW_QUERY = loc.NEW_QUERY || 'New Query';
 
-  var esc = RegExp("[ \.\'\\\\]");
+  var esc = RegExp("[ \.\'\\\\\|\&]");
   
   function _getKeyValue (keyValue) {
     if (keyValue.match(esc) != null) {
@@ -108,7 +108,7 @@
 
     // Realease a click event on the annotation table
     clickOnAnno : function (event) {
-
+      
       // Listen for clicks on table cells
       if (event.target !== event.currentTarget) {
 
@@ -206,7 +206,7 @@
 
             // Target is an orth
             if (i >= 0) {
-              this.toggleInToken(target, i, 'orth=' + target.innerText);
+              this.toggleInToken(target, i, _getAnnotation("orth=",target));
             }            
           }