Improve support for keyvalues in query-selector

Change-Id: I1cc03772f8e1e595e8a7b6c7cb2ff81b586cd0a5
diff --git a/dev/demo/query-creator.html b/dev/demo/query-creator.html
index 35a3b74..3649abd 100644
--- a/dev/demo/query-creator.html
+++ b/dev/demo/query-creator.html
@@ -33,12 +33,20 @@
               <td>ART</td>
               <td>ADJA</td>
               <td>ADJA<br>ADJD</td>
-              <td>NN</td>
+              <td class="matchkeyvalues">
+                <div>case:nom</div>
+                <div>gender:masc<br/>gender:fem</div>
+                <div>number:sg</div>
+              </td>
             </tr>
             <tr tabindex="0">
               <th>opennlp</th>
               <th>p</th>
-              <td>ART</td>
+              <td class="matchkeyvalues">
+                <div>case:nom</div>
+                <div>gender:masc</div>
+                <div>number:sg</div>
+              </td>
               <td>ADJA</td>
               <td></td>
               <td>NN</td>
diff --git a/dev/js/src/match/querycreator.js b/dev/js/src/match/querycreator.js
index fbabed0..179b10c 100644
--- a/dev/js/src/match/querycreator.js
+++ b/dev/js/src/match/querycreator.js
@@ -6,6 +6,10 @@
 define(['util'], function () {
   "use strict";
 
+  /*
+   * TODO:
+   *   Cache foundry and layer information per row.
+   */
   var loc = KorAP.Locale;
   loc.NEW_QUERY = loc.NEW_QUERY || 'New Query';
 
@@ -104,6 +108,10 @@
           if (target.innerText == '')
             return;
 
+          if (target.classList.contains('matchkeyvalues'))
+            return;
+
+
           // Check foundry and layer
           var head    = target.parentNode.getElementsByTagName('th');
           var foundry = head[0].innerText;
@@ -130,6 +138,42 @@
           };
         }
 
+        // The annotation is part of a key-value-pair
+        else if (target.tagName == 'SPAN' || target.tagName == 'DIV') {
+          if (target.innerText == '')
+            return;
+
+          if (target.tagName == 'SPAN') {
+            target = target.parentNode;
+          };
+
+          // Check foundry and layer
+          var parentCell = target.parentNode;
+          var head    = parentCell.parentNode.getElementsByTagName('th');
+          var foundry = head[0].innerText;
+          var layer   = head[1].innerText;
+
+          // Check index position of parent cell
+          var i = -2;
+          var sib = parentCell;
+          while((sib = sib.previousSibling) != null) {
+            if (sib.nodeType === 1)
+              i++;
+          };
+
+          var prefix = foundry + '/' + layer + '=';
+          var annotation = '';
+
+          // Get annotation value from cell
+          var annotation = _getAnnotation(prefix, target);
+
+          if (annotation !== '') {
+
+            // Add term
+            this.toggleInToken(target, i, annotation);
+          }
+        }
+
         // Get orth values
         else if (target.tagName == 'TH') {
 
@@ -150,6 +194,7 @@
           }
 
           // The head refers to the complete row
+          // Mark the complete row!
           else {
 
             // Check foundry and layer
@@ -165,15 +210,37 @@
               if (sib.nodeType !== 1 || sib.tagName === 'TH')
                 continue;
 
-              // Get annotation value from cell
-              var annotation = _getAnnotation(prefix, sib);
+              // Is a key-value-cell
+              if (sib.classList.contains('matchkeyvalues')) {
+                var divs = sib.getElementsByTagName('div');
+                for (var j = 0; j < divs.length; j++) {
+                  var keyvaluepair = divs[j];
 
-              if (annotation !== '') {
+                  // Get annotation value from cell
+                  var annotation = _getAnnotation(prefix, keyvaluepair);
 
-                // Add annotation to string
-                this.addToToken(i, annotation);
-                sib.className = 'chosen';
-              };
+                  if (annotation !== '') {
+
+                    // Add annotation to string
+                    this.addToToken(i, annotation);
+                    keyvaluepair.className = 'chosen';
+                  };
+                };
+              }
+
+              // Normal cell
+              else {
+
+                // Get annotation value from cell
+                var annotation = _getAnnotation(prefix, sib);
+
+                if (annotation !== '') {
+
+                  // Add annotation to string
+                  this.addToToken(i, annotation);
+                  sib.className = 'chosen';
+                };
+              }
 
               i++;
             };
@@ -207,6 +274,7 @@
       this.show();
     },
 
+
     // Remove term from token
     removeFromToken : function (index, term) {
       var token = this._query[index];
diff --git a/dev/scss/main/matchinfo.scss b/dev/scss/main/matchinfo.scss
index f5651f3..dab1d83 100644
--- a/dev/scss/main/matchinfo.scss
+++ b/dev/scss/main/matchinfo.scss
@@ -141,8 +141,9 @@
   }
   tr {
     outline: none;
-    > td.chosen,
-    > th.chosen {
+    td.chosen,
+    th.chosen,
+    div.chosen {
       background-color: $light-green !important;
       color: $nearly-white;
       // transition: color 0.1s, background-color 0.15s ease-out;
@@ -212,9 +213,36 @@
     white-space: nowrap;
     vertical-align: top;
     text-align: center;
+    div {
+      background-color: $light-orange; // $nearly-white;
+    }
   }
   tr:nth-child(even) > td {
     background-color: $light-orange;
+    div:nth-child(even) {
+      background-color: $middle-orange;
+    }
+  }
+
+  tr:nth-child(odd) > td > div:nth-child(odd) {
+    background-color: $middle-orange;
+  }
+
+
+  // table for key-value pairs
+  td.matchkeyvalues {
+    padding: 0;
+    > div {
+      @include cell-info;
+      > span {
+        color: $darkest-orange;
+        text-align: right;
+        &::after {
+          content: ":"
+        }
+        padding-right: .5em;
+      }
+    }
   }
 }