Open menus in buttongroups at different positions

Change-Id: Ica00912ebbd670680dadb65e3480342572895701
diff --git a/dev/js/src/buttongroup.js b/dev/js/src/buttongroup.js
index 040637f..721fdcb 100644
--- a/dev/js/src/buttongroup.js
+++ b/dev/js/src/buttongroup.js
@@ -25,6 +25,21 @@
       const cl = e.classList;
       if (classes) {
         cl.add.apply(cl,classes);
+        classes.forEach(i => {
+          switch (i) {
+          case "open-menu-below" : {
+            this._omBelow = true;
+            break;
+          }
+          case "open-menu-outside" : {
+            this._omOutside = true;
+            break;
+          }
+          case "open-menu-left" : {
+            this._omLeft = true;
+          }
+          }
+        })
       };
       cl.add('button-group');
       this._el = e;
@@ -119,6 +134,13 @@
      */
     addList : function (title, data, itemClass = defaultItemClass) {
       const list = treeMenuClass.create([], itemClass);
+
+      list.openAt(
+        this._omLeft ? true : false,
+        this._omBelow ? true : false,
+        this._omOutside ? true : false,
+      );
+      
       this.add(title, data, function (e) {
         list.show();
         list.button(this.button);
diff --git a/dev/js/src/buttongroup/menu.js b/dev/js/src/buttongroup/menu.js
index 4a4abfc..8edc7ef 100644
--- a/dev/js/src/buttongroup/menu.js
+++ b/dev/js/src/buttongroup/menu.js
@@ -32,9 +32,22 @@
       // Add menu to body
       document.getElementsByTagName('body')[0].appendChild(e);
 
+      this._left = false;
+      this._below = false;
+      this._outside = false;
+
       return obj;
     },
 
+    /**
+     * Open the menu at a certain position
+     * relative to the button.
+     */
+    openAt : function (left, below, outside) {
+      this._left = left ? true : false;
+      this._below = below ? true : false;
+      this._outside = outside ? true : false;
+    },
 
     /**
      * The panel object of the menu,
@@ -108,12 +121,38 @@
 
     _repos : function (e) {
       const bounding = e.getBoundingClientRect();
-      this._el.style.left = bounding.left + "px";
-      this._el.style.top = (
-        bounding.top +
-          bounding.height -
-          this._el.clientHeight
-      ) + "px";
+      const s = this._el.style;
+
+      let left = window.pageXOffset;
+      let top = 0;
+
+      s.right = 'auto';
+      s.bottom = 'auto';
+
+      left += bounding.left;
+      
+      if (this._left) {
+        left += bounding.width - this._el.clientWidth
+      };
+
+      if (this._below) {
+        top += bounding.bottom;
+        
+        if (!this._outside) {
+          top -= bounding.height;
+        };
+
+      } else {
+        top -= this._el.clientHeight;
+        if (this._outside) {
+          top += bounding.top;
+        } else {
+          top += bounding.bottom;
+        };
+      };
+
+      s.left = left + "px";
+      s.top = top + "px";
     }
   };
 });