UNPKG

3.93 kBPlain TextView Raw
1import Point from '@mapbox/point-geometry';
2
3import assert from 'assert';
4
5export 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 // Suppress the next click, but only if it's immediate.
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}