-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils-html.mjs
97 lines (88 loc) · 2.62 KB
/
utils-html.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { L } from './utils-debug.mjs'
/**
* @param {string} e
* @returns {HTMLElement}
*/
export const $=e=>/**@type {HTMLElement}*/(document.querySelector(e))
/**
* @param {string} e
* @returns {NodeListOf<HTMLElement>}
*/
export const $$=e=>document.querySelectorAll(e)
/**
* Searches through the DOM, and any attached shadow DOMs.
*
* NOTE: Doesn't support nested selectors e.g. 'title-bar .back'
*
* @param {string} selector
* @param {Document | DocumentFragment | HTMLElement} base
* @returns {Array<HTMLElement>}
*/
export function $$shadow(selector, base=document) {
let els = [...base.querySelectorAll(selector)]
// base.querySelectorAll('*').forEach(e=>e.shadowRoot && (els=[...els,...$$(selector,e.shadowRoot)]))
base.querySelectorAll('*').forEach(e=>e.shadowRoot && (els=els.concat($$shadow(selector,e.shadowRoot))))
return /**@type {Array<HTMLElement>}*/(els)
}
/**
* @param {string} e
* @returns {HTMLInputElement} - hack type so doesn't show errors if elements are missing
*/
export const $input=e=>/**@type {HTMLInputElement}*/(document.querySelector(e))
/**
* @param {string} e
* @returns {HTMLFormElement} - hack type so doesn't show errors if elements are missing
*/
export const $form=e=>/**@type {HTMLFormElement}*/(document.querySelector(e))
/**
* @param {string} e
* @returns {NodeListOf<HTMLInputElement>}
*/
export const $$input=e=>document.querySelectorAll(e)
/**
* @param {string} str
* @returns {string}
*/
export function escapeHtmlAttribute(str) {
return str.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
}
/**
* Position cursor after end of text in el
*
* @param {HTMLInputElement} el
*/
export function cursorEnd(el) {
L('utils-html.mjs cursorEnd()')
// el.focus()
if ('INPUT'===el.nodeName || 'TEXTAREA'===el.nodeName) {
// input & textarea elements
const l = el.value.length
el.setSelectionRange(l, l)
} else if (el.contentEditable === 'true') {
// contenteditable div
const r = document.createRange()
const s = window.getSelection()
r.selectNodeContents(el)
r.collapse(false)
s?.removeAllRanges()
s?.addRange(r)
}
}
/**
* True if child is contained within parent. Also if the child IS the parent, hmmm.
*
* @param {HTMLElement} child
* @param {string} parentSelector
* @returns {HTMLElement} - parent
*/
export function getParent(child, parentSelector) {
while (child && child !== document.body) {
if (child && child.matches(parentSelector)) return child
child = child.parentElement
}
return undefined
}