@maplat/ui 0.10.5 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +38 -1
  2. package/assets/locales/de/translation.json +71 -0
  3. package/{locales → assets/locales}/en/translation.json +12 -6
  4. package/{locales → assets/locales}/ja/translation.json +12 -6
  5. package/{locales → assets/locales}/ko/translation.json +12 -6
  6. package/assets/locales/vi/translation.json +71 -0
  7. package/{locales → assets/locales}/zh/translation.json +12 -6
  8. package/{locales → assets/locales}/zh-TW/translation.json +12 -6
  9. package/assets/parts/attr.png +0 -0
  10. package/assets/parts/border.png +0 -0
  11. package/assets/parts/compass.png +0 -0
  12. package/assets/parts/gps.png +0 -0
  13. package/assets/parts/help.png +0 -0
  14. package/assets/parts/hide_marker.png +0 -0
  15. package/assets/parts/home.png +0 -0
  16. package/assets/parts/marker_list.png +0 -0
  17. package/assets/parts/share.png +0 -0
  18. package/dist/absolute_url.d.ts +1 -0
  19. package/dist/assets/locales/de/translation.json +71 -0
  20. package/dist/assets/locales/en/translation.json +12 -6
  21. package/dist/assets/locales/ja/translation.json +12 -6
  22. package/dist/assets/locales/ko/translation.json +12 -6
  23. package/dist/assets/locales/vi/translation.json +71 -0
  24. package/dist/assets/locales/zh/translation.json +12 -6
  25. package/dist/assets/locales/zh-TW/translation.json +12 -6
  26. package/dist/contextmenu.d.ts +5 -0
  27. package/dist/function.d.ts +2 -0
  28. package/dist/icons.d.ts +7 -0
  29. package/dist/index.d.ts +64 -0
  30. package/dist/maplat-ui.es.js +9383 -0
  31. package/dist/maplat-ui.umd.js +205 -0
  32. package/dist/maplat_control.d.ts +55 -0
  33. package/dist/pointer_images.d.ts +2 -0
  34. package/dist/swiper_ex.d.ts +2 -0
  35. package/dist/types.d.ts +173 -0
  36. package/dist/ui_init.d.ts +4 -0
  37. package/dist/ui_marker.d.ts +9 -0
  38. package/dist/ui_utils.d.ts +9 -0
  39. package/less/contextmenu.css +8 -0
  40. package/less/font-awesome.less +48 -28
  41. package/less/maplat-specific.less +452 -66
  42. package/less/swiper4.css +715 -0
  43. package/less/ui.less +5 -5
  44. package/less/ui_packed.less +3 -3
  45. package/package.json +107 -106
  46. package/src/{absolute_url.js → absolute_url.ts} +1 -1
  47. package/src/contextmenu/base.ts +170 -0
  48. package/src/contextmenu/constants.ts +66 -0
  49. package/src/contextmenu/cssVars.ts +13 -0
  50. package/src/contextmenu/helpers/dom.ts +295 -0
  51. package/src/contextmenu/helpers/mix.ts +120 -0
  52. package/src/contextmenu/html.ts +161 -0
  53. package/src/contextmenu/internal.ts +293 -0
  54. package/src/contextmenu.ts +40 -0
  55. package/src/function.ts +36 -0
  56. package/src/icons.ts +46 -0
  57. package/src/index.ts +520 -0
  58. package/src/maplat_control.ts +686 -0
  59. package/src/pointer_images.ts +101 -0
  60. package/src/{service-worker.js → service-worker/index.ts} +5 -6
  61. package/src/swiper_augment.d.ts +13 -0
  62. package/src/{swiper_ex.js → swiper_ex.ts} +14 -10
  63. package/src/types.d.ts +31 -0
  64. package/src/types.ts +202 -0
  65. package/src/ui_init.ts +1066 -0
  66. package/src/ui_marker.ts +376 -0
  67. package/src/ui_utils.ts +87 -0
  68. package/dist/assets/fonts/a8c0074cf70b152b56105e6c4b227bd8.woff +0 -0
  69. package/dist/assets/fonts/cfeff2e898a64ebe7e6b5ec078b174c3.woff +0 -0
  70. package/dist/assets/images/09c3ce5a86d600e24f8e85de3a019853.png +0 -0
  71. package/dist/assets/images/0beac2cb41dfab43ddfd9df80b32b85d.png +0 -0
  72. package/dist/assets/images/1354b4f40dd58bb0f2a4871cb4ff81d8.png +0 -0
  73. package/dist/assets/images/2a61e310e46b50b5f8ddd5e905ba9db9.png +0 -0
  74. package/dist/assets/images/3131423d782cd3ea89a81247065e7f9d.png +0 -0
  75. package/dist/assets/images/41b2cf0fa604d3f196ca52337d238219.jpg +0 -0
  76. package/dist/assets/images/558bc7e8b9b6c5f41a7141cddb8cdb5e.png +0 -0
  77. package/dist/assets/images/56f7003805ed02f8a21199947651db2e.png +0 -0
  78. package/dist/assets/images/5ba349e3596aca094c41c56966b45dc7.png +0 -0
  79. package/dist/assets/images/6111b8076a2cf81c73f0e46f41a3af60.png +0 -0
  80. package/dist/assets/images/6345ee67d554fbfbf484ba4035ad19d9.jpg +0 -0
  81. package/dist/assets/images/649fce122b354de2ac725ba5f2661955.png +0 -0
  82. package/dist/assets/images/6a580287dea82c2fb9b214321a375145.png +0 -0
  83. package/dist/assets/images/6c5dba7f7d76e74c3a8c7c5b1c3fc544.png +0 -0
  84. package/dist/assets/images/6e1f2f2f6fed3c5cddeb925e7ae75aba.png +0 -0
  85. package/dist/assets/images/799a0177b0dc540682fa4a2e349a8f4f.png +0 -0
  86. package/dist/assets/images/7bef6f357e921c43f4f800cfcb757872.png +0 -0
  87. package/dist/assets/images/7d9d643a903df6f57b8b7386316021e5.png +0 -0
  88. package/dist/assets/images/7df82bae917b68159f84998182f2fdc6.png +0 -0
  89. package/dist/assets/images/8e5d0335f6598b8d874ba23ea9fb295f.png +0 -0
  90. package/dist/assets/images/90c32e751366be22777f3fe40a53fe06.png +0 -0
  91. package/dist/assets/images/9247459937b9c882303962e42bd8d989.png +0 -0
  92. package/dist/assets/images/927c34e7b9b2f95c82ba477993117eaf.png +0 -0
  93. package/dist/assets/images/95e9ca8285131f8ccb6da5052093173c.png +0 -0
  94. package/dist/assets/images/9a243e0cb0fc43e2a016d5d3aaa330d5.png +0 -0
  95. package/dist/assets/images/9ac6d81f417d6a5626b7c8d5a087c32b.png +0 -0
  96. package/dist/assets/images/9d3a01c866095b8b3e8e63f9cf11dd51.png +0 -0
  97. package/dist/assets/images/9df733bcb29a746cb16b47eedea9fc3a.png +0 -0
  98. package/dist/assets/images/acc6eab0ba9c470ae20fb4b74135e865.png +0 -0
  99. package/dist/assets/images/b9ae27f0a01228380dff76a33b605707.jpg +0 -0
  100. package/dist/assets/images/ba48b220f61a6e1028f1854326f43acd.png +0 -0
  101. package/dist/assets/images/bf67cc860289b85c0402a4d4f890a3bd.png +0 -0
  102. package/dist/assets/images/c49f2344772e33256ba24d64b59b20d1.png +0 -0
  103. package/dist/assets/images/ca6b77b234b18e7bb9b1ccda774da286.png +0 -0
  104. package/dist/assets/images/cd213169df16398b0017450e31788d73.png +0 -0
  105. package/dist/assets/images/f101a0974972eeab41189185a5c5b225.png +0 -0
  106. package/dist/assets/images/f115726e6249018905cca51653e1262c.png +0 -0
  107. package/dist/assets/images/f7acb820d978ab2dd69e8bf695c574d1.png +0 -0
  108. package/dist/assets/images/ffea4dd10bf2506aa1e0cd4c61426b42.png +0 -0
  109. package/dist/assets/maplat.css +0 -19
  110. package/dist/assets/maplat.css.map +0 -1
  111. package/dist/assets/maplat.js +0 -3
  112. package/dist/assets/maplat.js.LICENSE.txt +0 -43
  113. package/dist/assets/maplat.js.map +0 -1
  114. package/dist/index.html +0 -39
  115. package/dist/service-worker.js +0 -3
  116. package/dist/service-worker.js.LICENSE.txt +0 -1
  117. package/dist/service-worker.js.map +0 -1
  118. package/fonts/clarenbd-webfont.woff +0 -0
  119. package/fonts/fontawesome-webfont.woff +0 -0
  120. package/legacy/bootstrap-native.js +0 -1935
  121. package/legacy/detect-element-resize.js +0 -153
  122. package/legacy/iziToast.js +0 -1301
  123. package/legacy/page.js +0 -1153
  124. package/legacy/qrcode.js +0 -616
  125. package/legacy/sprintf.js +0 -285
  126. package/less/font-face.less +0 -11
  127. package/less/font-face_packed.less +0 -11
  128. package/parts/attr.png +0 -0
  129. package/parts/blue_marker.png +0 -0
  130. package/parts/bluedot.png +0 -0
  131. package/parts/bluedot_small.png +0 -0
  132. package/parts/bluedot_transparent.png +0 -0
  133. package/parts/border.png +0 -0
  134. package/parts/compass.png +0 -0
  135. package/parts/defaultpin.png +0 -0
  136. package/parts/defaultpin_selected.png +0 -0
  137. package/parts/gps.png +0 -0
  138. package/parts/gsi.jpg +0 -0
  139. package/parts/gsi_ortho.jpg +0 -0
  140. package/parts/help.png +0 -0
  141. package/parts/hide_marker.png +0 -0
  142. package/parts/home.png +0 -0
  143. package/parts/osm.jpg +0 -0
  144. package/parts/red_marker.png +0 -0
  145. package/parts/redcircle.png +0 -0
  146. package/parts/share.png +0 -0
  147. package/src/contextmenu.js +0 -29
  148. package/src/freeze_locales.js +0 -337
  149. package/src/function.js +0 -22
  150. package/src/index.js +0 -1762
  151. package/src/index_packed.js +0 -8
  152. package/src/maplat_control.js +0 -814
  153. package/src/pointer_images.js +0 -81
  154. /package/{parts → assets/parts}/Maplat.png +0 -0
  155. /package/{parts → assets/parts}/all_right_reserved.png +0 -0
  156. /package/{parts → assets/parts}/basemap.png +0 -0
  157. /package/{parts → assets/parts}/cc0.png +0 -0
  158. /package/{parts → assets/parts}/cc_by-nc-nd.png +0 -0
  159. /package/{parts → assets/parts}/cc_by-nc-sa.png +0 -0
  160. /package/{parts → assets/parts}/cc_by-nc.png +0 -0
  161. /package/{parts → assets/parts}/cc_by-nd.png +0 -0
  162. /package/{parts → assets/parts}/cc_by-sa.png +0 -0
  163. /package/{parts → assets/parts}/cc_by.png +0 -0
  164. /package/{parts → assets/parts}/favicon.png +0 -0
  165. /package/{parts → assets/parts}/fullscreen.png +0 -0
  166. /package/{parts → assets/parts}/loading.png +0 -0
  167. /package/{parts → assets/parts}/loading_image.png +0 -0
  168. /package/{parts → assets/parts}/minus.png +0 -0
  169. /package/{parts → assets/parts}/no_image.png +0 -0
  170. /package/{parts → assets/parts}/overlay.png +0 -0
  171. /package/{parts → assets/parts}/pd.png +0 -0
  172. /package/{parts → assets/parts}/plus.png +0 -0
  173. /package/{parts → assets/parts}/slider.png +0 -0
@@ -0,0 +1,295 @@
1
+ import { isNumeric } from "./mix";
2
+
3
+ /**
4
+ * @param {Element|Array<Element>} element DOM node or array of nodes.
5
+ * @param {String|Array<String>} classname Class or array of classes.
6
+ * For example: 'class1 class2' or ['class1', 'class2']
7
+ * @param {Number|undefined} timeout Timeout to remove a class.
8
+ */
9
+ export function addClass(
10
+ element: HTMLElement | HTMLElement[],
11
+ classname: string | string[],
12
+ timeout: number | null = null
13
+ ) {
14
+ if (Array.isArray(element)) {
15
+ element.forEach(each => addClass(each, classname, null));
16
+ return;
17
+ }
18
+
19
+ const array = Array.isArray(classname) ? classname : classname.split(/\s+/);
20
+ let i = array.length;
21
+
22
+ while (i--) {
23
+ if (!hasClass(element, array[i])) {
24
+ _addClass(element, array[i], timeout);
25
+ }
26
+ }
27
+ }
28
+
29
+ /**
30
+ * @param {Element|Array<Element>} element DOM node or array of nodes.
31
+ * @param {String|Array<String>} classname Class or array of classes.
32
+ * For example: 'class1 class2' or ['class1', 'class2']
33
+ * @param {Number|undefined} timeout Timeout to add a class.
34
+ */
35
+ export function removeClass(
36
+ element: HTMLElement | HTMLElement[],
37
+ classname: string | string[],
38
+ timeout: number | null = null
39
+ ) {
40
+ if (Array.isArray(element)) {
41
+ element.forEach(each => removeClass(each, classname, timeout));
42
+ return;
43
+ }
44
+
45
+ const array = Array.isArray(classname) ? classname : classname.split(/\s+/);
46
+ let i = array.length;
47
+
48
+ while (i--) {
49
+ if (hasClass(element, array[i])) {
50
+ _removeClass(element, array[i], timeout);
51
+ }
52
+ }
53
+ }
54
+
55
+ /**
56
+ * @param {Element} element DOM node.
57
+ * @param {String} classname Classname.
58
+ * @return {Boolean}
59
+ */
60
+ export function hasClass(element: HTMLElement, c: string) {
61
+ // use native if available
62
+ return element.classList
63
+ ? element.classList.contains(c)
64
+ : classRegex(c).test(element.className);
65
+ }
66
+
67
+ /**
68
+ * @param {Element|Array<Element>} element DOM node or array of nodes.
69
+ * @param {String} classname Classe.
70
+ */
71
+ export function toggleClass(
72
+ element: HTMLElement | HTMLElement[],
73
+ classname: string
74
+ ) {
75
+ if (Array.isArray(element)) {
76
+ element.forEach(each => toggleClass(each, classname));
77
+ return;
78
+ }
79
+
80
+ // use native if available
81
+ if (element.classList) {
82
+ element.classList.toggle(classname);
83
+ } else if (hasClass(element, classname)) {
84
+ _removeClass(element, classname, null);
85
+ } else {
86
+ _addClass(element, classname, null);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Abstraction to querySelectorAll for increased
92
+ * performance and greater usability
93
+ * @param {String} selector
94
+ * @param {Element} context (optional)
95
+ * @param {Boolean} find_all (optional)
96
+ * @return (find_all) {Element} : {Array}
97
+ */
98
+ export function find(
99
+ selector: string,
100
+ context: Element | Document = window.document,
101
+ find_all: boolean = false
102
+ ): HTMLElement | HTMLElement[] | undefined {
103
+ const simpleRe = /^(#?[\w-]+|\.[\w-.]+)$/,
104
+ periodRe = /\./g,
105
+ slice = Array.prototype.slice;
106
+ let matches: HTMLElement[] = [];
107
+
108
+ // Redirect call to the more performant function
109
+ // if it's a simple selector and return an array
110
+ // for easier usage
111
+ if (simpleRe.test(selector)) {
112
+ switch (selector[0]) {
113
+ case "#": {
114
+ const el = $(selector.substr(1));
115
+ matches = el ? [el] : [];
116
+ break;
117
+ }
118
+ case ".":
119
+ matches = slice.call(
120
+ context.getElementsByClassName(
121
+ selector.substr(1).replace(periodRe, " ")
122
+ )
123
+ );
124
+ break;
125
+ default:
126
+ matches = slice.call(context.getElementsByTagName(selector));
127
+ }
128
+ } else {
129
+ // If not a simple selector, query the DOM as usual
130
+ // and return an array for easier usage
131
+ matches = slice.call(context.querySelectorAll(selector));
132
+ }
133
+
134
+ return find_all ? matches : matches[0];
135
+ }
136
+
137
+ export function $(id: string) {
138
+ id = id[0] === "#" ? id.substr(1, id.length) : id;
139
+ return document.getElementById(id);
140
+ }
141
+
142
+ export function isElement(obj: unknown) {
143
+ // DOM, Level2
144
+ if ("HTMLElement" in window) {
145
+ return !!obj && obj instanceof HTMLElement;
146
+ }
147
+ // Older browsers
148
+ return (
149
+ !!obj &&
150
+ typeof obj === "object" &&
151
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
152
+ (obj as any).nodeType === 1 &&
153
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
154
+ !!(obj as any).nodeName
155
+ );
156
+ }
157
+
158
+ export function offset(element: HTMLElement) {
159
+ const rect = element.getBoundingClientRect();
160
+ const docEl = document.documentElement;
161
+ return {
162
+ left: rect.left + window.pageXOffset - docEl.clientLeft,
163
+ top: rect.top + window.pageYOffset - docEl.clientTop,
164
+ width: element.offsetWidth,
165
+ height: element.offsetHeight
166
+ };
167
+ }
168
+
169
+ export function getViewportSize() {
170
+ return {
171
+ w: window.innerWidth || document.documentElement.clientWidth,
172
+ h: window.innerHeight || document.documentElement.clientHeight
173
+ };
174
+ }
175
+
176
+ export function getAllChildren(node: Element, tag: string) {
177
+ return [].slice.call(node.getElementsByTagName(tag));
178
+ }
179
+
180
+ export function removeAllChildren(node: Node) {
181
+ while (node.firstChild) node.removeChild(node.firstChild);
182
+ }
183
+
184
+ export function removeAll(collection: HTMLElement[]) {
185
+ let node;
186
+
187
+ while ((node = collection[0])) node.parentNode!.removeChild(node);
188
+ }
189
+
190
+ export function getChildren(node: Node, tag: string | null) {
191
+ return [].filter.call(node.childNodes, (el: Node) =>
192
+ tag
193
+ ? el.nodeType === 1 && (el as Element).tagName.toLowerCase() === tag
194
+ : el.nodeType === 1
195
+ );
196
+ }
197
+
198
+ export function createFragment(html: string) {
199
+ const frag = document.createDocumentFragment(),
200
+ temp = document.createElement("div");
201
+ temp.innerHTML = html;
202
+ while (temp.firstChild) {
203
+ frag.appendChild(temp.firstChild);
204
+ }
205
+ return frag;
206
+ }
207
+
208
+ export function template(html: string, _row: Record<string, string>) {
209
+ return html.replace(/\{ *([\w_-]+) *\}/g, (_htm: string, key: string) => {
210
+ const value = _row[key] === undefined ? "" : _row[key];
211
+ return htmlEscape(value);
212
+ });
213
+ }
214
+
215
+ export function htmlEscape(str: string | number) {
216
+ return String(str)
217
+ .replace(/&/g, "&amp;")
218
+ .replace(/</g, "&lt;")
219
+ .replace(/>/g, "&gt;")
220
+ .replace(/"/g, "&quot;")
221
+ .replace(/'/g, "&#039;");
222
+ }
223
+
224
+ export function createElement(
225
+ node:
226
+ | string
227
+ | [
228
+ string,
229
+ {
230
+ id?: string;
231
+ classname?: string;
232
+ attr?:
233
+ | { name: string; value: string }
234
+ | { name: string; value: string }[];
235
+ }
236
+ ],
237
+ html: string
238
+ ) {
239
+ let elem: HTMLElement;
240
+ if (Array.isArray(node)) {
241
+ elem = document.createElement(node[0]);
242
+ const attrs = node[1];
243
+
244
+ if (attrs.id) elem.id = attrs.id;
245
+ if (attrs.classname) elem.className = attrs.classname;
246
+
247
+ if (attrs.attr) {
248
+ const attr = attrs.attr;
249
+ if (Array.isArray(attr)) {
250
+ let i = -1;
251
+ while (++i < attr.length) {
252
+ elem.setAttribute(attr[i].name, attr[i].value);
253
+ }
254
+ } else {
255
+ elem.setAttribute(attr.name, attr.value);
256
+ }
257
+ }
258
+ } else {
259
+ elem = document.createElement(node);
260
+ }
261
+ elem.innerHTML = html;
262
+ const frag = document.createDocumentFragment();
263
+
264
+ while (elem.childNodes[0]) frag.appendChild(elem.childNodes[0]);
265
+ elem.appendChild(frag);
266
+ return elem;
267
+ }
268
+
269
+ function classRegex(classname: string) {
270
+ return new RegExp(`(^|\\s+) ${classname} (\\s+|$)`);
271
+ }
272
+
273
+ function _addClass(el: HTMLElement, klass: string, timeout: number | null) {
274
+ // use native if available
275
+ if (el.classList) {
276
+ el.classList.add(klass);
277
+ } else {
278
+ el.className = `${el.className} ${klass}`.trim();
279
+ }
280
+
281
+ if (timeout && isNumeric(timeout)) {
282
+ window.setTimeout(() => _removeClass(el, klass, null), timeout);
283
+ }
284
+ }
285
+
286
+ function _removeClass(el: HTMLElement, klass: string, timeout: number | null) {
287
+ if (el.classList) {
288
+ el.classList.remove(klass);
289
+ } else {
290
+ el.className = el.className.replace(classRegex(klass), " ").trim();
291
+ }
292
+ if (timeout && isNumeric(timeout)) {
293
+ window.setTimeout(() => _addClass(el, klass, null), timeout);
294
+ }
295
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Overwrites obj1's values with obj2's and adds
3
+ * obj2's if non existent in obj1
4
+ * @returns obj3 a new object based on obj1 and obj2
5
+ */
6
+
7
+ export function mergeOptions(
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ obj1: Record<string, any>,
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ obj2: Record<string, any>
12
+ ) {
13
+ const obj3: Record<string, unknown> = {};
14
+ for (const attr1 in obj1) obj3[attr1] = obj1[attr1];
15
+ for (const attr2 in obj2) obj3[attr2] = obj2[attr2];
16
+ return obj3;
17
+ }
18
+
19
+ export function assert(
20
+ condition: boolean,
21
+ message: string = "Assertion failed"
22
+ ) {
23
+ if (!condition) {
24
+ if (typeof Error !== "undefined") throw new Error(message);
25
+ throw message; // Fallback
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Does str contain test?
31
+ * @param {String} str_test
32
+ * @param {String} str
33
+ * @returns Boolean
34
+ */
35
+ export function contains(str_test: string, str: string) {
36
+ return !!~str.indexOf(str_test);
37
+ }
38
+
39
+ export function getUniqueId(prefix: string = "id_") {
40
+ return `${prefix}${Math.random().toString(36).substring(2, 11)}`;
41
+ }
42
+
43
+ export function assertEqual(a: unknown, b: unknown, message: string) {
44
+ if (a !== b) {
45
+ throw new Error(`${message} mismatch: ${a} != ${b}`);
46
+ }
47
+ }
48
+
49
+ export function now() {
50
+ // Polyfill for window.performance.now()
51
+ // @license http://opensource.org/licenses/MIT
52
+ // copyright Paul Irish 2015
53
+ // https://gist.github.com/paulirish/5438650
54
+ if ("performance" in window === false) {
55
+ interface Performance {
56
+ now?: () => number;
57
+ }
58
+ (window as unknown as { performance: Performance }).performance = {};
59
+ }
60
+
61
+ Date.now =
62
+ Date.now ||
63
+ function () {
64
+ // thanks IE8
65
+ return new Date().getTime();
66
+ };
67
+
68
+ if ("now" in window.performance === false) {
69
+ let nowOffset = Date.now();
70
+
71
+ if (performance.timing && performance.timing.navigationStart) {
72
+ nowOffset = performance.timing.navigationStart;
73
+ }
74
+
75
+ interface PerformanceWithNow extends Performance {
76
+ now: () => number;
77
+ }
78
+ (window.performance as PerformanceWithNow).now = () =>
79
+ Date.now() - nowOffset;
80
+ }
81
+
82
+ return window.performance.now();
83
+ }
84
+
85
+ export function randomId(prefix: string) {
86
+ const id = now().toString(36);
87
+ return prefix ? prefix + id : id;
88
+ }
89
+
90
+ export function isNumeric(str: string | number) {
91
+ return /^\d+$/.test(String(str));
92
+ }
93
+
94
+ export function isEmpty(str: string | undefined | null) {
95
+ return !str || 0 === str.length;
96
+ }
97
+
98
+ export function emptyArray(array: unknown[]) {
99
+ while (array.length) array.pop();
100
+ }
101
+
102
+ export function anyMatchInArray(source: unknown[], target: unknown[]) {
103
+ return source.some((each: unknown) => target.indexOf(each) >= 0);
104
+ }
105
+
106
+ export function everyMatchInArray(arr1: unknown[], arr2: unknown[]) {
107
+ return arr2.every((each: unknown) => arr1.indexOf(each) >= 0);
108
+ }
109
+
110
+ export function anyItemHasValue(
111
+ obj: Record<string, unknown>,
112
+ has: boolean = false
113
+ ) {
114
+ const keys = Object.keys(obj);
115
+ keys.forEach(key => {
116
+ const value = obj[key];
117
+ if (!isEmpty(typeof value === "string" ? value : null)) has = true;
118
+ });
119
+ return has;
120
+ }
@@ -0,0 +1,161 @@
1
+ import ContextMenuBase, { createContainer } from "./base";
2
+ import { ContextMenuItem } from "../types";
3
+ import { CSS_VARS, DEFAULT_ITEMS } from "./constants";
4
+ import { createFragment, find } from "./helpers/dom";
5
+ import { contains, getUniqueId } from "./helpers/mix";
6
+
7
+ /**
8
+ * @class Html
9
+ */
10
+ export class Html {
11
+ Base: ContextMenuBase;
12
+ container: HTMLElement;
13
+
14
+ /**
15
+ * @constructor
16
+ * @param {ContextMenuBase} base Base class.
17
+ */
18
+ constructor(base: ContextMenuBase) {
19
+ this.Base = base;
20
+ this.container = this.Base.container;
21
+ return this;
22
+ }
23
+
24
+ createMenu() {
25
+ let items: ContextMenuItem[] = [];
26
+
27
+ if ("items" in this.Base.options) {
28
+ items =
29
+ (this.Base.options.defaultItems
30
+ ? (this.Base.options.items || []).concat(DEFAULT_ITEMS)
31
+ : this.Base.options.items) || [];
32
+ } else if (this.Base.options.defaultItems) {
33
+ items = DEFAULT_ITEMS;
34
+ }
35
+ // no item
36
+ if (items.length === 0) return false;
37
+ // create entries
38
+ items.forEach(this.addMenuEntry, this);
39
+ }
40
+
41
+ addMenuEntry(item: ContextMenuItem) {
42
+ if (item.items && Array.isArray(item.items)) {
43
+ // submenu - only a second level
44
+ item.classname = item.classname || "";
45
+ if (!contains(CSS_VARS.submenu, item.classname)) {
46
+ item.classname = item.classname.length
47
+ ? ` ${CSS_VARS.submenu}`
48
+ : CSS_VARS.submenu;
49
+ }
50
+
51
+ const li = this.generateHtmlAndPublish(this.container, item);
52
+ const sub = createContainer(false, this.Base.options.width || 150);
53
+ sub.style.left =
54
+ this.Base.Internal.submenu.lastLeft || this.Base.Internal.submenu.left;
55
+ li.appendChild(sub);
56
+
57
+ item.items!.forEach((each: ContextMenuItem) => {
58
+ this.generateHtmlAndPublish(sub, each, true);
59
+ });
60
+ } else {
61
+ this.generateHtmlAndPublish(this.container, item);
62
+ }
63
+ }
64
+
65
+ generateHtmlAndPublish(
66
+ parent: HTMLElement,
67
+ item: ContextMenuItem | string,
68
+ submenu: boolean | undefined = undefined
69
+ ) {
70
+ const index = getUniqueId();
71
+ let html,
72
+ frag: DocumentFragment,
73
+ element: HTMLElement,
74
+ separator = false;
75
+
76
+ // separator
77
+ if (typeof item === "string" && item.trim() === "-") {
78
+ html = `<li id="${index}" class="${CSS_VARS.separator}"><hr></li>`;
79
+ frag = createFragment(html);
80
+ // http://stackoverflow.com/a/13347298/4640499
81
+ // http://stackoverflow.com/a/13347298/4640499
82
+ element = [].slice.call(frag.childNodes, 0)[0] as HTMLElement;
83
+ if (parent.firstChild) {
84
+ parent.firstChild.appendChild(frag);
85
+ } else {
86
+ parent.appendChild(frag);
87
+ }
88
+ // to exclude from lineHeight calculation
89
+ separator = true;
90
+ } else {
91
+ const cItem = item as ContextMenuItem;
92
+ cItem.classname = cItem.classname || "";
93
+ html = `<span>${cItem.text}</span>`;
94
+ frag = createFragment(html);
95
+ element = document.createElement("li");
96
+
97
+ if (cItem.icon) {
98
+ if (cItem.classname === "") {
99
+ cItem.classname = CSS_VARS.icon;
100
+ } else if (cItem.classname.indexOf(CSS_VARS.icon) === -1) {
101
+ cItem.classname += ` ${CSS_VARS.icon}`;
102
+ }
103
+ element.setAttribute("style", `background-image:url(${cItem.icon})`);
104
+ }
105
+
106
+ element.id = index;
107
+ element.className = cItem.classname;
108
+ element.appendChild(frag);
109
+ if (parent.firstChild) {
110
+ (parent.firstChild as HTMLElement).appendChild(element);
111
+ } else {
112
+ parent.appendChild(element); // Fallback if no firstChild
113
+ }
114
+ }
115
+
116
+ const cItem = item as ContextMenuItem;
117
+ this.Base.Internal.items[index] = {
118
+ id: index,
119
+ submenu: submenu ? 1 : 0,
120
+ separator,
121
+ callback: cItem.callback,
122
+ data: cItem.data || null
123
+ };
124
+ this.Base.Internal.setItemListener(element, index);
125
+ return element;
126
+ }
127
+
128
+ removeMenuEntry(index: string) {
129
+ const element = find(
130
+ `#${index}`,
131
+ this.container.firstChild as HTMLElement,
132
+ false
133
+ ) as HTMLElement;
134
+ if (element && this.container.firstChild) {
135
+ this.container.firstChild.removeChild(element);
136
+ }
137
+ delete this.Base.Internal.items[index];
138
+ }
139
+
140
+ cloneAndGetLineHeight() {
141
+ // for some reason I have to calculate with 2 items
142
+ const cloned = this.container.cloneNode() as HTMLElement;
143
+ const frag = createFragment("<span>Foo</span>");
144
+ const frag2 = createFragment("<span>Foo</span>");
145
+ const element = document.createElement("li");
146
+ const element2 = document.createElement("li");
147
+
148
+ element.appendChild(frag);
149
+ element2.appendChild(frag2);
150
+ cloned.appendChild(element);
151
+ cloned.appendChild(element2);
152
+
153
+ if (this.container.parentNode) {
154
+ this.container.parentNode.appendChild(cloned);
155
+ const height = cloned.offsetHeight / 2;
156
+ this.container.parentNode.removeChild(cloned);
157
+ return height;
158
+ }
159
+ return 0;
160
+ }
161
+ }