Added query panel for plugin capabilities

Change-Id: I5766cf45aa711ebea9a6f9f3dfa51e706ebd0d0d
diff --git a/dev/js/src/init.js b/dev/js/src/init.js
index bafa473..82d9de9 100644
--- a/dev/js/src/init.js
+++ b/dev/js/src/init.js
@@ -26,6 +26,7 @@
   'session',
   'selectMenu',
   'panel/result',
+  'panel/query',
   'tour/tours',
   'api',
   'mailToChiffre',
@@ -40,6 +41,7 @@
              sessionClass,
              selectMenuClass,
              resultPanelClass,
+             queryPanelClass,
              tourClass) {
 
   const d = document;
@@ -376,6 +378,22 @@
     // Add the hinthelper to the KorAP object to make it manipulatable globally
     KorAP.Hint = obj.hint;
 
+
+    /**
+     * Add query panel
+     */
+    var queryPanel = queryPanelClass.create();
+
+    // Get input field
+    var sform = d.getElementById("searchform");
+    var vcView = d.getElementById('vc-view')
+    if (sform && vcView) {
+      // The views are below the query bar
+      sform.insertBefore(queryPanel.element(), vcView);
+      KorAP.Panel = KorAP.Panel || {};
+      KorAP.Panel['query'] = queryPanel;
+    }
+    
     return obj;
   });
   
diff --git a/dev/js/src/panel/query.js b/dev/js/src/panel/query.js
new file mode 100644
index 0000000..aed2a91
--- /dev/null
+++ b/dev/js/src/panel/query.js
@@ -0,0 +1,39 @@
+/**
+ * The query panel
+ *
+ * @author Nils Diewald
+ */
+define([
+  'panel'
+], function (panelClass) {
+
+  const d = document;
+
+  // Localization values
+  const loc = KorAP.Locale;
+  
+  return {
+    create : function (opened) {
+      return Object.create(panelClass)._init(['query']).upgradeTo(this)._init(opened);
+    },
+
+    // Initialize panel
+    _init : function (opened) {
+      this._opened = opened;
+
+      // If plugins are enabled, add all buttons for the query panel
+      if (KorAP.Plugin) {
+        var queryButtons = KorAP.Plugin.buttonGroup("query");
+
+        // Add all matchbuttons in order
+        for (i in queryButtons) {
+          a.add.apply(a, queryButtons[i]);
+        };
+
+        KorAP.Plugin.clearButtons("query")
+      };
+      
+      return this;
+    }
+  }
+});
diff --git a/dev/js/src/plugin/server.js b/dev/js/src/plugin/server.js
index 1afc747..69318b0 100644
--- a/dev/js/src/plugin/server.js
+++ b/dev/js/src/plugin/server.js
@@ -11,6 +11,8 @@
 define(["plugin/widget", "util"], function (widgetClass) {
   "use strict";
 
+  KorAP.Panel = KorAP.Panel || {};
+
   // Contains all widgets to address with
   // messages to them
   var widgets = {};
@@ -19,12 +21,18 @@
   // TODO:
   //   These should better be panels and every panel
   //   has a buttonGroup
+
+  // List of panels with dynamic buttons, i.e.
+  // panels that may occur multiple times.
   var buttons = {
     match : []
   };
-  var panels = {
-    match : 1
-  };
+
+  // List of panels with static buttons, i.e.
+  // panels that occur only once.
+  var buttonsSingle = {
+    query : []
+  }
   
   // This is a counter to limit acceptable incoming messages
   // to a certain amount. For every message, this counter will
@@ -110,7 +118,7 @@
 
         var panel = embed["panel"];
 
-        if (!panel || !buttons[panel])
+        if (!panel || !(buttons[panel] || buttonsSingle[panel]))
           throw new Error("Panel for plugin is invalid");
 
         var onClick = embed["onClick"];
@@ -134,7 +142,20 @@
             plugin["widgets"].push(id);
           };
 
-          buttons[panel].push([title, embed["classes"], cb]);
+          // Add to dynamic button list (e.g. for matches)
+          if (buttons[panel]) {
+            buttons[panel].push([title, embed["classes"], cb]);
+          }
+
+          // Add to static button list (e.g. for query) already loaded
+          else if (KorAP.Panel[panel]) {
+            KorAP.Panel[panel].actions.add(title, embed["classes"], cb);
+          }
+
+          // Add to static button list (e.g. for query) not yet loaded
+          else {
+            buttonsSingle[panel].push([title, embed["classes"], cb]);
+          }
         };
       };
     },
@@ -152,7 +173,23 @@
      * Get named button group - better rename to "action"
      */
     buttonGroup : function (name) {
-      return buttons[name];
+      if (buttons[name] != undefined) {
+        return buttons[name];
+      } else if (buttonsSingle[name] != undefined) {
+        return buttonsSingle[name];
+      };
+      return [];
+    },
+
+    /**
+     * Clear named button group - better rename to "action"
+     */
+    clearButtonGroup : function (name) {
+      if (buttons[name] != undefined) {
+        buttons[name] = [];
+      } else if (buttonsSingle[name] != undefined) {
+        buttonsSingle[name] = [];
+      }
     },
     
     /**
@@ -298,6 +335,12 @@
         widgets[w].close();
       };
       widgets = {};
+      for (let b in buttons) {
+        buttons[b] = [];
+      };
+      for (let b in buttonsSingle) {
+        buttonsSingle[b] = [];
+      };
       this._removeListener();
     }
   };