1 | import Point from '@mapbox/point-geometry';
|
2 |
|
3 | import assert from 'assert';
|
4 |
|
5 | export default class DOM {
|
6 | private static readonly docStyle = typeof window !== 'undefined' && window.document && window.document.documentElement.style;
|
7 |
|
8 | private static userSelect: string;
|
9 |
|
10 | private static selectProp = DOM.testProp(['userSelect', 'MozUserSelect', 'WebkitUserSelect', 'msUserSelect']);
|
11 |
|
12 | private static transformProp = DOM.testProp(['transform', 'WebkitTransform']);
|
13 |
|
14 | private static testProp(props: string[]): string {
|
15 | if (!DOM.docStyle) return props[0];
|
16 | for (let i = 0; i < props.length; i++) {
|
17 | if (props[i] in DOM.docStyle) {
|
18 | return props[i];
|
19 | }
|
20 | }
|
21 | return props[0];
|
22 | }
|
23 |
|
24 | public static create<K extends keyof HTMLElementTagNameMap>(tagName: K, className?: string, container?: HTMLElement): HTMLElementTagNameMap[K] {
|
25 | const el = window.document.createElement(tagName);
|
26 | if (className !== undefined) el.className = className;
|
27 | if (container) container.appendChild(el);
|
28 | return el;
|
29 | }
|
30 |
|
31 | public static createNS(namespaceURI: string, tagName: string) {
|
32 | const el = window.document.createElementNS(namespaceURI, tagName);
|
33 | return el;
|
34 | }
|
35 |
|
36 | public static disableDrag() {
|
37 | if (DOM.docStyle && DOM.selectProp) {
|
38 | DOM.userSelect = DOM.docStyle[DOM.selectProp];
|
39 | DOM.docStyle[DOM.selectProp] = 'none';
|
40 | }
|
41 | }
|
42 |
|
43 | public static enableDrag() {
|
44 | if (DOM.docStyle && DOM.selectProp) {
|
45 | DOM.docStyle[DOM.selectProp] = DOM.userSelect;
|
46 | }
|
47 | }
|
48 |
|
49 | public static setTransform(el: HTMLElement, value: string) {
|
50 | el.style[DOM.transformProp] = value;
|
51 | }
|
52 |
|
53 | public static addEventListener(target: any, type: any, callback: any, options: {
|
54 | passive?: boolean;
|
55 | capture?: boolean;
|
56 | } = {}) {
|
57 | if ('passive' in options) {
|
58 | target.addEventListener(type, callback, options);
|
59 | } else {
|
60 | target.addEventListener(type, callback, options.capture);
|
61 | }
|
62 | }
|
63 |
|
64 | public static removeEventListener(target: any, type: any, callback: any, options: {
|
65 | passive?: boolean;
|
66 | capture?: boolean;
|
67 | } = {}) {
|
68 | if ('passive' in options) {
|
69 | target.removeEventListener(type, callback, options);
|
70 | } else {
|
71 | target.removeEventListener(type, callback, options.capture);
|
72 | }
|
73 | }
|
74 |
|
75 |
|
76 | private static suppressClickInternal(e) {
|
77 | e.preventDefault();
|
78 | e.stopPropagation();
|
79 | window.removeEventListener('click', DOM.suppressClickInternal, true);
|
80 | }
|
81 |
|
82 | public static suppressClick() {
|
83 | window.addEventListener('click', DOM.suppressClickInternal, true);
|
84 | window.setTimeout(() => {
|
85 | window.removeEventListener('click', DOM.suppressClickInternal, true);
|
86 | }, 0);
|
87 | }
|
88 |
|
89 | public static mousePos(el: HTMLElement, e: MouseEvent | Touch) {
|
90 | const rect = el.getBoundingClientRect();
|
91 | return new Point(
|
92 | e.clientX - rect.left - el.clientLeft,
|
93 | e.clientY - rect.top - el.clientTop
|
94 | );
|
95 | }
|
96 |
|
97 | public static touchPos(el: HTMLElement, touches: TouchList) {
|
98 | const rect = el.getBoundingClientRect();
|
99 | const points: Point[] = [];
|
100 | for (let i = 0; i < touches.length; i++) {
|
101 | points.push(new Point(
|
102 | touches[i].clientX - rect.left - el.clientLeft,
|
103 | touches[i].clientY - rect.top - el.clientTop
|
104 | ));
|
105 | }
|
106 | return points;
|
107 | }
|
108 |
|
109 | public static mouseButton(e: MouseEvent) {
|
110 | assert(e.type === 'mousedown' || e.type === 'mouseup');
|
111 | return e.button;
|
112 | }
|
113 |
|
114 | public static remove(node: HTMLElement) {
|
115 | if (node.parentNode) {
|
116 | node.parentNode.removeChild(node);
|
117 | }
|
118 | }
|
119 | }
|