Introduce widget class

Change-Id: I949cd46c48b9176c0b013c1c65f1fba949413c8e
diff --git a/dev/js/src/plugin/client.js b/dev/js/src/plugin/client.js
index f14a7f7..6918da4 100644
--- a/dev/js/src/plugin/client.js
+++ b/dev/js/src/plugin/client.js
@@ -8,6 +8,19 @@
  * @author Nils Diewald
  */
 
+/*
+* TODO:
+*   Some methods require bidirectional
+*   calling, like
+*   - getKoralQuery()
+*   this probably should be done using a callback,
+*   like fetch({data}, function () {}, '*'), that will
+*   add a unique ID to the message and will call on the cb
+*   once the answer to that message arrives.
+*/
+
+var cs = document.currentScript;
+
 (function () {
   "use strict";
 
@@ -24,16 +37,18 @@
      * Initialize plugin
      */
     _init : function () {
-      console.log('Init');
+      this.widgetID = window.name;
+      this.server = cs.getAttribute('data-server') || '*';
       this.resize();
       return this;
     },
 
     // Send a message
     _sendMsg : function (data) {
+      data["originID"] = this.widgetID;
 
       // TODO: This should send a correct origin
-      window.parent.postMessage(data, '*');
+      window.parent.postMessage(data, this.server);
     },
 
     /**
@@ -54,8 +69,6 @@
     resize : function () {
       var body = document.body;
 
-      console.log('Resize');
-
       // recognize margin of first element
       // (don't know why in FF)
       var cs = getComputedStyle(body.children[0]);
diff --git a/dev/js/src/plugin/server.js b/dev/js/src/plugin/server.js
index 01dddac..db59422 100644
--- a/dev/js/src/plugin/server.js
+++ b/dev/js/src/plugin/server.js
@@ -8,9 +8,20 @@
  * @author Nils Diewald
  */
 
-define(["util"], function () {
+define(["plugin/widget", "util"], function (widgetClass) {
   "use strict";
 
+  // TODO:
+  //   This is a counter to limit acceptable incoming messages
+  //   to hundred. For every message, this will be decreased
+  //   (down to 0), for every second this will be increased
+  //   (up to 100).
+  var c = 100;
+
+  // Contains all widgets to address with
+  // messages to them
+  var widgets = {};
+
   return {
 
     /**
@@ -35,17 +46,22 @@
 
     /**
      * Open a new widget on a certain element
-     * TODO: and register
      */
     addWidget : function (element, src) {
 
-      // Spawn new iframe
-      var iframe = element.addE('iframe');
-      iframe.setAttribute('allowTransparency',"true");
-      iframe.setAttribute('frameborder',0);
-      iframe.setAttribute('sandbox','allow-scripts');
-      iframe.classList.add('widget');
-      iframe.setAttribute('src', src);
+      // Create a unique random ID per widget
+      var id = 'id-' + this._randomID();
+
+      // Create a new widget
+      var widget = widgetClass.create(src, id);
+
+      // Store the widget based on the identifier
+      widgets[id] = widget;
+
+      // Open widget in frontend
+      element.appendChild(
+        widget.element()
+      );
     },
 
     // Receive a call from an embedded iframe
@@ -53,30 +69,37 @@
       // Get event data
       var d = e.data;
 
-      // TODO: Check for e.origin!
+      // e.origin is probably set and okay
 
-      // TODO: Deal with mad iframes
-   
+      // TODO:
+      //   Deal with mad iframes
+
+      // Get the widget
+      var widget = widgets[d["originID"]];
+
+      // If the addressed widget does not exist - fail
+      if (!widget)
+        return;
+
+
       // Resize the iframe
       if (d.action === 'resize') {
 
-        // TODO: Check which iframe it was
-        // var iframe = document.getElementById('?');
-
-        // this.resize(iframe, d);
-        console.log('Resizing not yet implemented');
+        widget.resize(d);
       }
 
       // Log message from iframe
       else if (d.action === 'log') {
         KorAP.log(d.code, d.msg);
-      }
+      };
+
+      // TODO:
+      //   Close
     },
 
-
-    // Resize the calling iframe
-    resize : function (iframe, d) {
-      iframe.style.height = d.height + 'px';
+    // Get a random identifier
+    _randomID : function () {
+      return randomID(20);
     }
   }
 });
diff --git a/dev/js/src/plugin/widget.js b/dev/js/src/plugin/widget.js
new file mode 100644
index 0000000..4c2f09c
--- /dev/null
+++ b/dev/js/src/plugin/widget.js
@@ -0,0 +1,54 @@
+/**
+ * The plugin system is based
+ * on registered widgets (iframes) from
+ * foreign services.
+ * The widget component represents a single iframe.
+ *
+ * @author Nils Diewald
+ */
+
+define(["util"], function () {
+  "use strict";
+
+  return {
+
+    /**
+     * Create new widget
+     */
+    create : function (src, id) {
+      return Object.create(this)._init(src, id);
+    },
+
+    _init : function (src, id) {
+      this.src = src;
+      this.id = id;
+      return this;
+    },
+
+    /**
+     * The element of the widget
+     */
+    element : function () {
+
+      if (this._element)
+        return this._element;
+
+      // Spawn new iframe
+      var i = document.createElement('iframe');
+      i.setAttribute('allowTransparency',"true");
+      i.setAttribute('frameborder', 0);
+      i.setAttribute('sandbox','allow-scripts');
+      i.classList.add('widget');
+      i.setAttribute('name', this.id);
+      i.setAttribute('src', this.src);
+      this._element = i;
+
+      return i;
+    },
+
+    // Resize iframe
+    resize : function (data) {
+      this._element.style.height = data.height + 'px';
+    }
+  }
+});