Merge "Added example plugin registry"
diff --git a/dev/demo/plugin-server.html b/dev/demo/plugin-server.html
index 0d4a454..d91b9e2 100644
--- a/dev/demo/plugin-server.html
+++ b/dev/demo/plugin-server.html
@@ -16,7 +16,7 @@
         <ol>
           <li class="active">
             <div id="container"></div>
-            <a onclick="KorAP.Plugin.addWidget(document.getElementById('container'), 'Example', 'http://localhost:3003/demo/plugin-client.html')">Open widget</a>
+            <div id="buttons"></div>
           </li>
         </ol>
       </div>
diff --git a/dev/demo/plugin-serverdemo.js b/dev/demo/plugin-serverdemo.js
index d5f07f8..a6ba4a2 100644
--- a/dev/demo/plugin-serverdemo.js
+++ b/dev/demo/plugin-serverdemo.js
@@ -5,8 +5,39 @@
   }
 });
 
-define(['app/en','plugin/server','lib/domReady','init','hint/foundries/cnx'], function (lang, pluginClass, domReady) {
+define(['app/en','buttongroup', 'plugin/server','lib/domReady','init','hint/foundries/cnx'], function (lang, buttonGroupClass, pluginClass, domReady) {
   domReady(function () {
+
     KorAP.Plugin = pluginClass.create();
+
+    KorAP.Plugin.register({
+      'name' : 'Example New',
+      'desc' : 'Some content about cats',
+      // 'about' : 'https://localhost:5678/',
+      'embed' : [{
+        'buttonGroup' : 'match',
+        'title' : 'Translate',
+        'classes' : ['translate'],
+        'onClick' : {
+          'action' : 'addWidget',
+          'panel' : 'container',
+          'template' : 'http://localhost:3003/demo/plugin-client.html',
+        }
+      }]
+    });
+
+    
+    var btns = buttonGroupClass.create();
+    document.getElementById('buttons').appendChild(btns.element());
+
+    // Are there plugin buttons defined
+    var matchButtons = KorAP.Plugin.buttonGroup("match");
+    if (matchButtons) {
+
+      // Add all matchbuttons in order
+      for (i in matchButtons) {
+        btns.add.apply(btns, matchButtons[i]);
+      }
+    };  
   });
 });
diff --git a/dev/js/spec/pluginSpec.js b/dev/js/spec/pluginSpec.js
index fa74486..62aa3c7 100644
--- a/dev/js/spec/pluginSpec.js
+++ b/dev/js/spec/pluginSpec.js
@@ -13,7 +13,8 @@
       var div = document.createElement("div");
       var id = manager.addWidget(div, 'about:blank');
       expect(id).toMatch(/^id-/);
-      expect(div.firstChild.tagName).toEqual("IFRAME");
+      expect(div.firstChild.classList.contains('widget')).toBeTruthy();
+      expect(div.firstChild.firstChild.tagName).toEqual("IFRAME");
       manager.destroy();
     });
   });
diff --git a/dev/js/src/plugin/server.js b/dev/js/src/plugin/server.js
index d4190fb..6689529 100644
--- a/dev/js/src/plugin/server.js
+++ b/dev/js/src/plugin/server.js
@@ -14,6 +14,10 @@
   // Contains all widgets to address with
   // messages to them
   var widgets = {};
+  var plugins = {};
+  var buttons = {
+    match : []
+  };
 
   // This is a counter to limit acceptable incoming messages
   // to a certain amount. For every message, this counter will
@@ -45,6 +49,96 @@
     },
 
     /**
+     * Register a plugin described as a JSON object.
+     *
+     * This is work in progress.
+     */
+    register : function (obj) {
+
+      /* Example:
+
+         KorAP.Plugin.register({
+           'name' : 'CatContent',
+           'desc' : 'Some content about cats',
+           'about' : 'https://localhost:5678/',
+           'embed' : [{
+             'buttonGroup' : 'match',
+             'title' : loc.TRANSLATE,
+             'classes' : ['translate']
+             'onClick' : {
+               'action' : 'addWidget',
+               'panel' : 'match',
+               'template' : 'https://localhost:5678/?match={matchid}',
+             }
+           }]
+         });
+      */
+
+      // TODO:
+      //   These fields need to be localized by a structure like
+      //   {
+      //     de : {
+      //       name : '..'
+      //     }
+      //     en : ...
+      //   }
+      // for display
+      var name = obj["name"];
+
+      // Register plugin by name
+      var plugin = plugins[name] = {
+        name : name,
+        desc : obj["desc"],
+        about : obj["about"],
+        widgets : []
+      };
+ 
+      // Embed all embeddings of the plugin
+      for (var i in obj["embed"]) {
+        var embed = obj["embed"][i];
+        var addTo = embed["buttonGroup"];
+        var onClick = embed["onClick"];
+
+        // Needs to be localized as well
+        var title = embed["title"];
+
+        // The embedding will open a widget
+        if (onClick["action"] == "addWidget") {
+
+          var panel = onClick["panel"];
+          var that = this;
+          var cb = function (e) {
+
+            // Get the URL of the widget
+            var url = onClick["template"]; // that._interpolateURI(onClick["template"], this.match);
+
+            // Add the widget to the panel
+            var id = that.addWidget(document.getElementById(panel), name, url);
+            plugin["widgets"].push(id);
+          };
+
+          buttons["match"].push([title, embed["classes"], cb]);
+        };
+      };
+    },
+
+
+    // TODO:
+    //   Interpolate URIs similar to https://tools.ietf.org/html/rfc6570
+    //   but as simple as possible
+    _interpolateURI : function (uri, obj) {
+      // ...
+    },
+
+
+    /**
+     * Get named button group
+     */
+    buttonGroup : function (name) {
+      return buttons[name];
+    },
+    
+    /**
      * Open a new widget as a child to a certain element
      */
     addWidget : function (element, name, src) {
@@ -79,6 +173,8 @@
       limits[id] = maxMessages;
 
       // Open widget in frontend
+      // TODO:
+      //   Instead of an "element" this should probably be a 'panel' object!
       element.appendChild(
         widget.element()
       );
@@ -119,6 +215,9 @@
 
         // Kill widget
         KorAP.log(0, 'Suspicious action by widget', widget.src);
+
+        // TODO:
+        //   Potentially kill the whole plugin!
         this.closeWidget(widget);
         return;
       };
diff --git a/dev/js/src/util.js b/dev/js/src/util.js
index cb60c2a..27c3d8d 100644
--- a/dev/js/src/util.js
+++ b/dev/js/src/util.js
@@ -83,6 +83,9 @@
   KorAP.API = KorAP.API || {};
   KorAP.Locale = KorAP.Locale || {};
 
+  // This should load plugin/server
+  KorAP.Plugin = KorAP.Plugin || {};
+
   const loc = KorAP.Locale;
   loc.OR  = loc.OR  || 'or';
   loc.AND = loc.AND || 'and';