Open menus in buttongroups at different positions
Change-Id: Ica00912ebbd670680dadb65e3480342572895701
diff --git a/Changes b/Changes
index 27c9af0..24aebd0 100755
--- a/Changes
+++ b/Changes
@@ -30,6 +30,7 @@
- Fold all top-level navigation items.
- Add plugin service to redirect to a certain location.
- Add support for pagination information to retrieve by plugins.
+ - Buttongroup menus can be opened at different positions.
0.42 2021-06-18
- Added GitHub based CI for perl.
diff --git a/dev/js/spec/buttongroupSpec.js b/dev/js/spec/buttongroupSpec.js
index c92832e..258d847 100644
--- a/dev/js/spec/buttongroupSpec.js
+++ b/dev/js/spec/buttongroupSpec.js
@@ -1,4 +1,4 @@
-define(['buttongroup','state'], function (buttonGroupClass, stateClass) {
+define(['buttongroup','buttongroup/menu','menu/item','state'], function (buttonGroupClass, buttonGroupMenuClass, defaultItemClass, stateClass) {
var FunObj = {
count : 0,
@@ -285,4 +285,46 @@
expect(btn.tagName).toEqual('C3');
});
});
+
+ describe('KorAP.ButtonGroup.Menu', function () {
+ it('should reposition', function () {
+ const menu = buttonGroupMenuClass.create([["hallo", undefined, function () {}]], defaultItemClass);
+ const div = document.createElement('div');
+
+ document.body.appendChild(div);
+
+ div.style.position = 'absolute';
+ div.style.display = 'block';
+ div.style.left = '14px';
+ div.style.top = '20px';
+ div.style.width = '40px';
+ div.style.height = '30px';
+
+ menu.show();
+
+ // 000
+ menu._repos(div);
+ let elem = menu.element();
+ const fffl = elem.style.left;
+ const ffft = elem.style.top;
+
+ // 100
+ menu.openAt(true, false, false);
+ menu._repos(div);
+ elem = menu.element();
+ const tffl = elem.style.left;
+ expect(tffl).not.toEqual(fffl);
+
+
+ // 011
+ menu.openAt(false, true, true);
+ menu._repos(div);
+ elem = menu.element();
+ const fttt = elem.style.top;
+ expect(fttt).not.toEqual(ffft);
+
+ document.body.removeChild(div);
+ document.body.removeChild(elem);
+ });
+ });
});
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";
}
};
});