Introduce button group

Change-Id: Ic9d158e77f76aabfc92ce54093d768a0e92b3560
diff --git a/dev/js/runner/buttongroup.html b/dev/js/runner/buttongroup.html
new file mode 100644
index 0000000..78b6a94
--- /dev/null
+++ b/dev/js/runner/buttongroup.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Spec Runner for ButtonGroup Helper</title>
+  <link rel="shortcut icon" type="image/png" href="../lib/jasmine-2.1.1/jasmine_favicon.png">
+  <link rel="stylesheet" href="../lib/jasmine-2.1.1/jasmine.css">
+  <script src="../lib/require.js"></script>
+  <script src="../lib/jasmine-2.1.1/jasmine.js"></script>
+  <script src="../lib/jasmine-2.1.1/jasmine-html.js"></script>
+  <script src="../lib/jasmine-2.1.1/boot.js"></script>
+  <script>
+    require.config({
+      baseUrl: "../src",
+      paths: {
+        "lib" : "../lib",
+        "spec" : "../spec"
+      }
+    });
+    require([
+      'spec/buttongroupSpec'
+    ],
+    function () {
+      if (jsApiReporter.finished === true)
+        jasmine.getEnv().execute();
+    });
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/dev/js/spec/buttongroupSpec.js b/dev/js/spec/buttongroupSpec.js
new file mode 100644
index 0000000..fa5a888
--- /dev/null
+++ b/dev/js/spec/buttongroupSpec.js
@@ -0,0 +1,73 @@
+define(['buttongroup'], function (buttonGroupClass) {
+
+  var FunObj = {
+    count : 0,
+    create : function () {
+      return Object.create(this);
+    },
+    incr : function () {
+      this.count++;
+    }
+  };
+  
+  describe('KorAP.ButtonGroup', function () {
+
+    it('should be initializable', function () {
+      var group = buttonGroupClass.create(['action', 'bottom']);
+      var el = group.element();
+      expect(el.tagName).toEqual('DIV');
+      expect(el.firstChild).toBeNull();
+      expect(el.classList.contains('action')).toBeTruthy();
+      expect(el.classList.contains('bottom')).toBeTruthy();
+      expect(el.classList.contains('button-group')).toBeTruthy();
+    });
+
+    it('should be expandable', function () {
+      var group = buttonGroupClass.create();
+      expect(group.element().classList.contains('button-group')).toBeTruthy();
+
+      group.add('Meta', ['meta', 'top'], function (e) {});
+
+      var btn = group.element().firstChild;
+      expect(btn.tagName).toEqual('SPAN');
+      expect(btn.classList.contains('meta')).toBeTruthy();
+      expect(btn.classList.contains('top')).toBeTruthy();
+      expect(btn.innerText).toEqual('Meta');
+    });
+
+    it('should listen to button clicks', function () {
+      var group = buttonGroupClass.create();
+
+      var count = 0;
+
+      group.add('Meta', undefined, function () {
+        count++;
+      });
+
+      expect(count).toEqual(0);
+
+      // Click on the button
+      group.element().firstChild.click();
+
+      expect(count).toEqual(1);
+    });
+
+    it('should respect binds', function () {
+      var group = buttonGroupClass.create();
+      fun = FunObj.create();
+      expect(fun.count).toEqual(0);
+
+      // Bind group to another object
+      group.bind(fun);
+
+      group.add('Incr', undefined, function (e) {
+        // increment on bind object
+        this.incr()
+      });
+
+      // Click on the button
+      group.element().firstChild.click();
+      expect(fun.count).toEqual(1);
+    });
+  });
+});
diff --git a/dev/js/src/buttongroup.js b/dev/js/src/buttongroup.js
new file mode 100644
index 0000000..b33c13a
--- /dev/null
+++ b/dev/js/src/buttongroup.js
@@ -0,0 +1,61 @@
+define(['util'], function () {
+  return {
+    /**
+     * Create button group
+     */
+    create : function (classes) {
+      return Object.create(this)._init(classes);
+    },
+    
+    // Initialize button group
+    _init : function (classes) {
+      var e = document.createElement('div');
+      var cl = e.classList;
+      if (classes !== undefined) {
+        cl.add.apply(cl,classes);
+      };
+      cl.add('button-group');
+      this._element = e;
+      return this;
+    },
+
+    /**
+     * Return main element
+     */
+    element : function () {
+      return this._element;
+    },
+
+    /**
+     * Add button in order
+     */
+    add : function (title, classes, cb) {
+      var b = this._element.addE('span');
+      b.addT(title);
+      b.setAttribute('title',title);
+      if (classes !== undefined) {
+        b.classList.add.apply(b.classList, classes);
+      };
+
+      var that = this;
+      b.addEventListener('click', function (e) {
+
+        // Do not bubble
+        e.halt();
+        
+        // Call callback
+        cb.apply(that._bind || this, e)
+      });
+    },
+
+    /**
+     * Bind an object to all callbacks of the button group
+     */
+    bind : function (obj) {
+      if (obj !== undefined) {
+        this._bind = obj;
+      };
+      return this._bind || this;
+    }
+  }
+});