blob: 8edc7ef5f02ca4ebbe5da9bb7269d081b5a0483b [file] [log] [blame]
Akrone51eaa32020-11-10 09:35:53 +01001/**
2 * Menu to choose from in a button group.
3 */
4"use strict";
Akron24aa0052020-11-10 11:00:34 +01005
Akron37ea1192021-07-28 10:40:14 +02006// TODO:
7// Add addToggle() method
8
Akron52ed22d2018-07-11 17:05:19 +02009define(['menu'], function (menuClass) {
Nils Diewald0e6992a2015-04-14 20:13:52 +000010
11 return {
Nils Diewald7148c6f2015-05-04 15:07:53 +000012
13 /**
14 * Create new menu object.
Akron20b6d312021-07-26 15:14:42 +020015 * Pass the list of items and the itemClass.
Nils Diewald7148c6f2015-05-04 15:07:53 +000016 */
Akron52ed22d2018-07-11 17:05:19 +020017 create : function (list, itemClass) {
Akronbf713fc2020-10-13 10:44:35 +020018 const obj = Object.create(menuClass)
19 .upgradeTo(this)
20 ._init(list, {itemClass : itemClass});
Nils Diewald0e6992a2015-04-14 20:13:52 +000021 obj.limit(6);
Akroneaba63e2018-01-26 19:49:30 +010022
Akronbf713fc2020-10-13 10:44:35 +020023 const e = obj.element();
Nils Diewald0e6992a2015-04-14 20:13:52 +000024
25 // This is only domspecific
Akroneaba63e2018-01-26 19:49:30 +010026 e.addEventListener('blur', function (e) {
Akron20b6d312021-07-26 15:14:42 +020027 this.menu.hide();
Nils Diewald0e6992a2015-04-14 20:13:52 +000028 });
Akroneaba63e2018-01-26 19:49:30 +010029
Akron52ed22d2018-07-11 17:05:19 +020030 e.classList.add('button-group-list');
Akroneaba63e2018-01-26 19:49:30 +010031
32 // Add menu to body
33 document.getElementsByTagName('body')[0].appendChild(e);
34
Akron4510a3e2021-09-10 15:09:56 +020035 this._left = false;
36 this._below = false;
37 this._outside = false;
38
Nils Diewald0e6992a2015-04-14 20:13:52 +000039 return obj;
40 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000041
Akron4510a3e2021-09-10 15:09:56 +020042 /**
43 * Open the menu at a certain position
44 * relative to the button.
45 */
46 openAt : function (left, below, outside) {
47 this._left = left ? true : false;
48 this._below = below ? true : false;
49 this._outside = outside ? true : false;
50 },
Akronbf713fc2020-10-13 10:44:35 +020051
Nils Diewald7148c6f2015-05-04 15:07:53 +000052 /**
Akron20b6d312021-07-26 15:14:42 +020053 * The panel object of the menu,
54 * in case the menu was spawned by a panel.
Nils Diewald7148c6f2015-05-04 15:07:53 +000055 */
Akron20b6d312021-07-26 15:14:42 +020056 panel : function (panelVar) {
Akron7f9a6a32018-07-18 15:05:23 +020057 if (panelVar !== undefined)
58 this._panel = panelVar;
Akroneaba63e2018-01-26 19:49:30 +010059
Akron7f9a6a32018-07-18 15:05:23 +020060 return this._panel;
Akroneaba63e2018-01-26 19:49:30 +010061 },
62
Akronbf713fc2020-10-13 10:44:35 +020063
Akronbec4a6a2018-07-10 14:45:15 +020064 // Attach menu to button
Akron52ed22d2018-07-11 17:05:19 +020065 button : function (btn) {
Akron257aa852018-02-06 19:29:51 +010066
Akron1801c5c2018-07-16 18:15:48 +020067 this._button = btn;
68
Akron1801c5c2018-07-16 18:15:48 +020069 this._repos(this._button);
Akron257aa852018-02-06 19:29:51 +010070 this.slider().reInit();
71
72 /*
73 * This is a suboptimal scrolling solution, see
74 * see https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects
75 */
76 if (this._onscroll !== undefined) {
77 window.removeEventListener('scroll', this._onscroll);
78 };
79
80 this._onscroll = function () {
Akron1801c5c2018-07-16 18:15:48 +020081 this._repos(this._button);
Akron257aa852018-02-06 19:29:51 +010082 }.bind(this);
83
84 window.addEventListener('scroll', this._onscroll);
85 },
86
Akron20b6d312021-07-26 15:14:42 +020087
88 /**
89 * Add button in order
90 *
91 * Returns the button element
92 */
93 add : function (title, data, cb) {
94
95 let that = this;
96
97 const cbWrap = function (e) {
98
99 // Call callback
100 let obj = that._bind || this;
101 obj.button = b;
102 cb.apply(obj)
103 };
104
105 // TODO:
106 // support classes, data-icon and state in itemClass!
107 const b = this.itemClass().create([title, title, cbWrap]);
108 this.append(b);
109 return b;
110 },
Akronbf713fc2020-10-13 10:44:35 +0200111
Akron257aa852018-02-06 19:29:51 +0100112 // Overwrite onHide method
113 onHide : function () {
114
115 // Remove listener
116 if (this._onscroll !== undefined) {
117 window.removeEventListener('scroll', this._onscroll);
118 };
Akronc296ca22018-04-24 16:35:26 +0200119 this.element().blur();
Akron257aa852018-02-06 19:29:51 +0100120 },
121
122 _repos : function (e) {
Akronbf713fc2020-10-13 10:44:35 +0200123 const bounding = e.getBoundingClientRect();
Akron4510a3e2021-09-10 15:09:56 +0200124 const s = this._el.style;
125
126 let left = window.pageXOffset;
127 let top = 0;
128
129 s.right = 'auto';
130 s.bottom = 'auto';
131
132 left += bounding.left;
133
134 if (this._left) {
135 left += bounding.width - this._el.clientWidth
136 };
137
138 if (this._below) {
139 top += bounding.bottom;
140
141 if (!this._outside) {
142 top -= bounding.height;
143 };
144
145 } else {
146 top -= this._el.clientHeight;
147 if (this._outside) {
148 top += bounding.top;
149 } else {
150 top += bounding.bottom;
151 };
152 };
153
154 s.left = left + "px";
155 s.top = top + "px";
Nils Diewald0e6992a2015-04-14 20:13:52 +0000156 }
157 };
158});