@maplat/ui 0.10.6 → 0.11.1
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.
- package/LICENSE +223 -223
- package/README.md +128 -91
- package/assets/locales/de/translation.json +71 -0
- package/{locales → assets/locales}/en/translation.json +70 -64
- package/{locales → assets/locales}/ja/translation.json +70 -64
- package/{locales → assets/locales}/ko/translation.json +71 -65
- package/assets/locales/vi/translation.json +71 -0
- package/{locales → assets/locales}/zh/translation.json +71 -65
- package/{locales → assets/locales}/zh-TW/translation.json +71 -65
- package/assets/parts/attr.png +0 -0
- package/assets/parts/border.png +0 -0
- package/assets/parts/compass.png +0 -0
- package/assets/parts/gps.png +0 -0
- package/assets/parts/help.png +0 -0
- package/assets/parts/hide_marker.png +0 -0
- package/assets/parts/home.png +0 -0
- package/assets/parts/marker_list.png +0 -0
- package/assets/parts/share.png +0 -0
- package/dist/absolute_url.d.ts +1 -0
- package/dist/assets/locales/de/translation.json +71 -0
- package/dist/assets/locales/en/translation.json +70 -64
- package/dist/assets/locales/ja/translation.json +70 -64
- package/dist/assets/locales/ko/translation.json +71 -65
- package/dist/assets/locales/vi/translation.json +71 -0
- package/dist/assets/locales/zh/translation.json +71 -65
- package/dist/assets/locales/zh-TW/translation.json +71 -65
- package/dist/contextmenu.d.ts +5 -0
- package/dist/function.d.ts +2 -0
- package/dist/icons.d.ts +7 -0
- package/dist/index.d.ts +65 -0
- package/dist/maplat-ui.es.js +33551 -0
- package/dist/maplat-ui.umd.js +4934 -0
- package/dist/maplat_control.d.ts +55 -0
- package/dist/pointer_images.d.ts +2 -0
- package/dist/swiper_ex.d.ts +2 -0
- package/dist/types.d.ts +185 -0
- package/dist/ui_init.d.ts +4 -0
- package/dist/ui_marker.d.ts +9 -0
- package/dist/ui_utils.d.ts +9 -0
- package/less/bootstrap.less +7010 -7010
- package/less/contextmenu.css +8 -0
- package/less/font-awesome.less +51 -31
- package/less/iziToast.less +1732 -1732
- package/less/maplat-specific.less +1038 -652
- package/less/swiper4.css +715 -0
- package/less/ui.less +11 -11
- package/less/ui_packed.less +10 -10
- package/package.json +80 -79
- package/src/{absolute_url.js → absolute_url.ts} +1 -1
- package/src/contextmenu/base.ts +170 -0
- package/src/contextmenu/constants.ts +66 -0
- package/src/contextmenu/cssVars.ts +13 -0
- package/src/contextmenu/helpers/dom.ts +295 -0
- package/src/contextmenu/helpers/mix.ts +120 -0
- package/src/contextmenu/html.ts +161 -0
- package/src/contextmenu/internal.ts +293 -0
- package/src/contextmenu.ts +40 -0
- package/src/function.ts +36 -0
- package/src/icons.ts +46 -0
- package/src/index.ts +521 -0
- package/src/maplat_control.ts +629 -0
- package/src/pointer_images.ts +101 -0
- package/src/{service-worker.js → service-worker/index.ts} +5 -6
- package/src/swiper_augment.d.ts +13 -0
- package/src/{swiper_ex.js → swiper_ex.ts} +14 -10
- package/src/types.d.ts +31 -0
- package/src/types.ts +202 -0
- package/src/ui_init.ts +1175 -0
- package/src/ui_marker.ts +376 -0
- package/src/ui_utils.ts +87 -0
- package/dist/assets/fonts/a8c0074cf70b152b56105e6c4b227bd8.woff +0 -0
- package/dist/assets/fonts/cfeff2e898a64ebe7e6b5ec078b174c3.woff +0 -0
- package/dist/assets/images/09c3ce5a86d600e24f8e85de3a019853.png +0 -0
- package/dist/assets/images/0beac2cb41dfab43ddfd9df80b32b85d.png +0 -0
- package/dist/assets/images/1354b4f40dd58bb0f2a4871cb4ff81d8.png +0 -0
- package/dist/assets/images/2a61e310e46b50b5f8ddd5e905ba9db9.png +0 -0
- package/dist/assets/images/3131423d782cd3ea89a81247065e7f9d.png +0 -0
- package/dist/assets/images/41b2cf0fa604d3f196ca52337d238219.jpg +0 -0
- package/dist/assets/images/558bc7e8b9b6c5f41a7141cddb8cdb5e.png +0 -0
- package/dist/assets/images/56f7003805ed02f8a21199947651db2e.png +0 -0
- package/dist/assets/images/5ba349e3596aca094c41c56966b45dc7.png +0 -0
- package/dist/assets/images/6111b8076a2cf81c73f0e46f41a3af60.png +0 -0
- package/dist/assets/images/6345ee67d554fbfbf484ba4035ad19d9.jpg +0 -0
- package/dist/assets/images/649fce122b354de2ac725ba5f2661955.png +0 -0
- package/dist/assets/images/6a580287dea82c2fb9b214321a375145.png +0 -0
- package/dist/assets/images/6c5dba7f7d76e74c3a8c7c5b1c3fc544.png +0 -0
- package/dist/assets/images/6e1f2f2f6fed3c5cddeb925e7ae75aba.png +0 -0
- package/dist/assets/images/799a0177b0dc540682fa4a2e349a8f4f.png +0 -0
- package/dist/assets/images/7bef6f357e921c43f4f800cfcb757872.png +0 -0
- package/dist/assets/images/7d9d643a903df6f57b8b7386316021e5.png +0 -0
- package/dist/assets/images/7df82bae917b68159f84998182f2fdc6.png +0 -0
- package/dist/assets/images/8e5d0335f6598b8d874ba23ea9fb295f.png +0 -0
- package/dist/assets/images/90c32e751366be22777f3fe40a53fe06.png +0 -0
- package/dist/assets/images/9247459937b9c882303962e42bd8d989.png +0 -0
- package/dist/assets/images/927c34e7b9b2f95c82ba477993117eaf.png +0 -0
- package/dist/assets/images/95e9ca8285131f8ccb6da5052093173c.png +0 -0
- package/dist/assets/images/9a243e0cb0fc43e2a016d5d3aaa330d5.png +0 -0
- package/dist/assets/images/9ac6d81f417d6a5626b7c8d5a087c32b.png +0 -0
- package/dist/assets/images/9d3a01c866095b8b3e8e63f9cf11dd51.png +0 -0
- package/dist/assets/images/9df733bcb29a746cb16b47eedea9fc3a.png +0 -0
- package/dist/assets/images/acc6eab0ba9c470ae20fb4b74135e865.png +0 -0
- package/dist/assets/images/b9ae27f0a01228380dff76a33b605707.jpg +0 -0
- package/dist/assets/images/ba48b220f61a6e1028f1854326f43acd.png +0 -0
- package/dist/assets/images/bf67cc860289b85c0402a4d4f890a3bd.png +0 -0
- package/dist/assets/images/c49f2344772e33256ba24d64b59b20d1.png +0 -0
- package/dist/assets/images/ca6b77b234b18e7bb9b1ccda774da286.png +0 -0
- package/dist/assets/images/cd213169df16398b0017450e31788d73.png +0 -0
- package/dist/assets/images/f101a0974972eeab41189185a5c5b225.png +0 -0
- package/dist/assets/images/f115726e6249018905cca51653e1262c.png +0 -0
- package/dist/assets/images/f7acb820d978ab2dd69e8bf695c574d1.png +0 -0
- package/dist/assets/images/ffea4dd10bf2506aa1e0cd4c61426b42.png +0 -0
- package/dist/assets/maplat.css +0 -19
- package/dist/assets/maplat.css.map +0 -1
- package/dist/assets/maplat.js +0 -3
- package/dist/assets/maplat.js.LICENSE.txt +0 -43
- package/dist/assets/maplat.js.map +0 -1
- package/dist/index.html +0 -125
- package/dist/service-worker.js +0 -3
- package/dist/service-worker.js.LICENSE.txt +0 -1
- package/dist/service-worker.js.map +0 -1
- package/fonts/clarenbd-webfont.woff +0 -0
- package/fonts/fontawesome-webfont.woff +0 -0
- package/legacy/bootstrap-native.js +0 -1935
- package/legacy/detect-element-resize.js +0 -153
- package/legacy/iziToast.js +0 -1301
- package/legacy/page.js +0 -1153
- package/legacy/qrcode.js +0 -616
- package/legacy/sprintf.js +0 -285
- package/less/font-face.less +0 -11
- package/less/font-face_packed.less +0 -11
- package/parts/attr.png +0 -0
- package/parts/blue_marker.png +0 -0
- package/parts/bluedot.png +0 -0
- package/parts/bluedot_small.png +0 -0
- package/parts/bluedot_transparent.png +0 -0
- package/parts/border.png +0 -0
- package/parts/compass.png +0 -0
- package/parts/defaultpin.png +0 -0
- package/parts/defaultpin_selected.png +0 -0
- package/parts/gps.png +0 -0
- package/parts/gsi.jpg +0 -0
- package/parts/gsi_ortho.jpg +0 -0
- package/parts/help.png +0 -0
- package/parts/hide_marker.png +0 -0
- package/parts/home.png +0 -0
- package/parts/osm.jpg +0 -0
- package/parts/red_marker.png +0 -0
- package/parts/redcircle.png +0 -0
- package/parts/share.png +0 -0
- package/src/contextmenu.js +0 -29
- package/src/freeze_locales.js +0 -337
- package/src/function.js +0 -22
- package/src/index.js +0 -1778
- package/src/index_packed.js +0 -8
- package/src/maplat_control.js +0 -808
- package/src/pointer_images.js +0 -81
- /package/{parts → assets/parts}/Maplat.png +0 -0
- /package/{parts → assets/parts}/all_right_reserved.png +0 -0
- /package/{parts → assets/parts}/basemap.png +0 -0
- /package/{parts → assets/parts}/cc0.png +0 -0
- /package/{parts → assets/parts}/cc_by-nc-nd.png +0 -0
- /package/{parts → assets/parts}/cc_by-nc-sa.png +0 -0
- /package/{parts → assets/parts}/cc_by-nc.png +0 -0
- /package/{parts → assets/parts}/cc_by-nd.png +0 -0
- /package/{parts → assets/parts}/cc_by-sa.png +0 -0
- /package/{parts → assets/parts}/cc_by.png +0 -0
- /package/{parts → assets/parts}/favicon.png +0 -0
- /package/{parts → assets/parts}/fullscreen.png +0 -0
- /package/{parts → assets/parts}/loading.png +0 -0
- /package/{parts → assets/parts}/loading_image.png +0 -0
- /package/{parts → assets/parts}/minus.png +0 -0
- /package/{parts → assets/parts}/no_image.png +0 -0
- /package/{parts → assets/parts}/overlay.png +0 -0
- /package/{parts → assets/parts}/pd.png +0 -0
- /package/{parts → assets/parts}/plus.png +0 -0
- /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, "&")
|
|
218
|
+
.replace(/</g, "<")
|
|
219
|
+
.replace(/>/g, ">")
|
|
220
|
+
.replace(/"/g, """)
|
|
221
|
+
.replace(/'/g, "'");
|
|
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
|
+
}
|