@webalternatif/js-core 1.6.0 → 1.6.4
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/README.md +3 -3
- package/dist/cjs/Mouse.js +6 -1
- package/dist/cjs/Translator.js +7 -1
- package/dist/cjs/array.js +7 -25
- package/dist/cjs/dom.js +819 -210
- package/dist/cjs/eventDispatcher.js +6 -1
- package/dist/cjs/index.js +6 -13
- package/dist/cjs/is.js +49 -6
- package/dist/cjs/math.js +56 -31
- package/dist/cjs/onOff.js +2 -2
- package/dist/cjs/random.js +6 -6
- package/dist/cjs/string.js +19 -17
- package/dist/cjs/traversal.js +1 -2
- package/dist/cjs/utils.js +155 -38
- package/dist/esm/Mouse.js +8 -2
- package/dist/esm/Translator.js +9 -3
- package/dist/esm/array.js +10 -29
- package/dist/esm/dom.js +821 -211
- package/dist/esm/eventDispatcher.js +9 -3
- package/dist/esm/index.js +7 -8
- package/dist/esm/is.js +49 -6
- package/dist/esm/math.js +60 -34
- package/dist/esm/onOff.js +6 -6
- package/dist/esm/random.js +6 -6
- package/dist/esm/string.js +23 -21
- package/dist/esm/stringPrototype.js +2 -2
- package/dist/esm/traversal.js +2 -3
- package/dist/esm/utils.js +158 -41
- package/dist/umd/Translator.umd.js +1 -0
- package/dist/umd/dom.umd.js +1 -0
- package/dist/umd/eventDispatcher.umd.js +1 -0
- package/dist/umd/mouse.umd.js +1 -0
- package/dist/umd/webf.umd.js +1 -0
- package/docs/array.md +90 -0
- package/docs/dom.md +1477 -0
- package/docs/eventDispatcher.md +15 -0
- package/docs/is.md +259 -0
- package/docs/math.md +127 -0
- package/docs/mouse.md +58 -0
- package/docs/random.md +15 -0
- package/docs/string.md +145 -0
- package/docs/translator.md +95 -0
- package/docs/traversal.md +159 -0
- package/docs/utils.md +228 -0
- package/package.json +37 -5
- package/src/Mouse.js +73 -0
- package/src/Translator.js +148 -0
- package/src/array.js +136 -0
- package/src/dom.js +1553 -0
- package/src/eventDispatcher.js +118 -0
- package/src/index.js +106 -0
- package/src/is.js +201 -0
- package/src/math.js +113 -0
- package/src/onOff.js +313 -0
- package/src/random.js +38 -0
- package/src/string.js +662 -0
- package/src/stringPrototype.js +16 -0
- package/src/traversal.js +236 -0
- package/src/utils.js +242 -0
- package/types/Translator.d.ts +6 -5
- package/types/array.d.ts +1 -2
- package/types/dom.d.ts +763 -204
- package/types/index.d.ts +23 -22
- package/types/is.d.ts +3 -0
- package/types/math.d.ts +6 -5
- package/types/utils.d.ts +4 -4
- package/types/i18n.d.ts +0 -4
package/src/onOff.js
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { isFunction, isTouchDevice } from './is.js'
|
|
2
|
+
import { foreach, map } from './traversal.js'
|
|
3
|
+
import { inArray } from './array.js'
|
|
4
|
+
import Mouse from './Mouse.js'
|
|
5
|
+
|
|
6
|
+
const LISTENERS = new Map()
|
|
7
|
+
const CUSTOM_EVENTS = ['longtap', 'dbltap']
|
|
8
|
+
const ENABLED_EVENTS = new Set()
|
|
9
|
+
|
|
10
|
+
let teardownLongTap = null
|
|
11
|
+
let teardownDblTap = null
|
|
12
|
+
|
|
13
|
+
const supplyEvent = function (event) {
|
|
14
|
+
if (ENABLED_EVENTS?.has(event)) return
|
|
15
|
+
|
|
16
|
+
if (event === 'longtap') enableLongTap()
|
|
17
|
+
if (event === 'dbltap') enableDblTap()
|
|
18
|
+
|
|
19
|
+
ENABLED_EVENTS.add(event)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const enableLongTap = function () {
|
|
23
|
+
const LONGPRESS_DELAY = 800
|
|
24
|
+
const MOVE_TOLERANCE = 40
|
|
25
|
+
|
|
26
|
+
let timer = null
|
|
27
|
+
let startX = 0
|
|
28
|
+
let startY = 0
|
|
29
|
+
let target = null
|
|
30
|
+
|
|
31
|
+
const start = (ev) => {
|
|
32
|
+
target = ev.target
|
|
33
|
+
|
|
34
|
+
const pos = Mouse.getViewportPosition(ev)
|
|
35
|
+
startX = pos.x
|
|
36
|
+
startY = pos.y
|
|
37
|
+
|
|
38
|
+
timer = setTimeout(() => {
|
|
39
|
+
target.dispatchEvent(
|
|
40
|
+
new CustomEvent('longtap', {
|
|
41
|
+
bubbles: true,
|
|
42
|
+
cancelable: true,
|
|
43
|
+
detail: { originalEvent: ev },
|
|
44
|
+
}),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
timer = null
|
|
48
|
+
}, LONGPRESS_DELAY)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const move = (ev) => {
|
|
52
|
+
// if (!timer) return;
|
|
53
|
+
|
|
54
|
+
const pos = Mouse.getViewportPosition(ev)
|
|
55
|
+
|
|
56
|
+
if (Math.hypot(pos.x - startX, pos.y - startY) > MOVE_TOLERANCE) {
|
|
57
|
+
clearTimeout(timer)
|
|
58
|
+
timer = null
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const end = () => {
|
|
63
|
+
clearTimeout(timer)
|
|
64
|
+
timer = null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
document.addEventListener('touchstart', start, { passive: true })
|
|
68
|
+
document.addEventListener('touchmove', move, { passive: true })
|
|
69
|
+
document.addEventListener('touchend', end)
|
|
70
|
+
document.addEventListener('touchcancel', end)
|
|
71
|
+
|
|
72
|
+
teardownLongTap = () => {
|
|
73
|
+
document.removeEventListener('touchstart', start, { passive: true })
|
|
74
|
+
document.removeEventListener('touchmove', move, { passive: true })
|
|
75
|
+
document.removeEventListener('touchend', end)
|
|
76
|
+
document.removeEventListener('touchcancel', end)
|
|
77
|
+
teardownLongTap = null
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const enableDblTap = function () {
|
|
82
|
+
const DBLTAP_DELAY = 300
|
|
83
|
+
const MOVE_TOLERANCE = 40
|
|
84
|
+
let lastTapTime = 0
|
|
85
|
+
let lastPos = null
|
|
86
|
+
|
|
87
|
+
if (isTouchDevice()) {
|
|
88
|
+
document.addEventListener(
|
|
89
|
+
'dblclick',
|
|
90
|
+
(ev) => {
|
|
91
|
+
ev.preventDefault()
|
|
92
|
+
ev.stopPropagation()
|
|
93
|
+
ev.stopImmediatePropagation()
|
|
94
|
+
},
|
|
95
|
+
{ capture: true },
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const start = (ev) => {
|
|
100
|
+
const target = ev.target
|
|
101
|
+
|
|
102
|
+
if (Date.now() - lastTapTime > DBLTAP_DELAY) {
|
|
103
|
+
lastTapTime = Date.now()
|
|
104
|
+
lastPos = Mouse.getViewportPosition(ev)
|
|
105
|
+
} else {
|
|
106
|
+
const pos = Mouse.getViewportPosition(ev)
|
|
107
|
+
|
|
108
|
+
if (Math.hypot(pos.x - lastPos.x, pos.y - lastPos.y) <= MOVE_TOLERANCE) {
|
|
109
|
+
target.dispatchEvent(
|
|
110
|
+
new CustomEvent('dbltap', {
|
|
111
|
+
bubbles: true,
|
|
112
|
+
cancelable: true,
|
|
113
|
+
detail: { originalEvent: ev },
|
|
114
|
+
}),
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
lastTapTime = Date.now()
|
|
119
|
+
lastPos = pos
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
document.addEventListener('touchstart', start, { passive: true })
|
|
124
|
+
|
|
125
|
+
teardownDblTap = () => {
|
|
126
|
+
document.removeEventListener('touchstart', start, { passive: true })
|
|
127
|
+
teardownDblTap = null
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {Element} target
|
|
133
|
+
* @param {Element} el
|
|
134
|
+
* @returns {Element[]}
|
|
135
|
+
*/
|
|
136
|
+
function buildTree(target, el) {
|
|
137
|
+
const path = []
|
|
138
|
+
let node = target.nodeType === 3 ? target.parentNode : target
|
|
139
|
+
|
|
140
|
+
while (node) {
|
|
141
|
+
path.push(node)
|
|
142
|
+
if (node === el) break
|
|
143
|
+
node = node.parentNode
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return path
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function createWrappedEvent(ev, currentTarget) {
|
|
150
|
+
const wrappedEv = {
|
|
151
|
+
_immediateStopped: false,
|
|
152
|
+
_propagationStopped: false,
|
|
153
|
+
originalEvent: ev,
|
|
154
|
+
currentTarget,
|
|
155
|
+
|
|
156
|
+
stopPropagation: (...args) => {
|
|
157
|
+
wrappedEv._propagationStopped = true
|
|
158
|
+
ev.stopPropagation(...args)
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
stopImmediatePropagation: (...args) => {
|
|
162
|
+
wrappedEv._immediateStopped = true
|
|
163
|
+
wrappedEv._propagationStopped = true
|
|
164
|
+
ev.stopImmediatePropagation(...args)
|
|
165
|
+
},
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return new Proxy(wrappedEv, {
|
|
169
|
+
get(target, prop, receiver) {
|
|
170
|
+
if (prop in target) {
|
|
171
|
+
return Reflect.get(target, prop, receiver)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const value = ev[prop]
|
|
175
|
+
return isFunction(value) ? value.bind(ev) : value
|
|
176
|
+
},
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @param {Element|Document|Window} el
|
|
182
|
+
* @param {string} events
|
|
183
|
+
* @param {string|Element|function} selector
|
|
184
|
+
* @param {function|AddEventListenerOptions|boolean} [handler]
|
|
185
|
+
* @param {AddEventListenerOptions|boolean} [options]
|
|
186
|
+
* @returns {Element}
|
|
187
|
+
*/
|
|
188
|
+
export function on(el, events, selector, handler, options) {
|
|
189
|
+
if (isFunction(selector)) {
|
|
190
|
+
options = handler
|
|
191
|
+
handler = selector
|
|
192
|
+
selector = null
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
foreach(events.split(' '), (rawEvent) => {
|
|
196
|
+
const [event, namespace] = rawEvent.split('.')
|
|
197
|
+
|
|
198
|
+
const listener = (ev) => {
|
|
199
|
+
if (ev.cancelBubble) return
|
|
200
|
+
|
|
201
|
+
const tree = buildTree(ev.target, el)
|
|
202
|
+
|
|
203
|
+
const binds = [...LISTENERS.get(el)]
|
|
204
|
+
|
|
205
|
+
for (const node of tree) {
|
|
206
|
+
let propagationStoppedOnThisNode = false
|
|
207
|
+
|
|
208
|
+
for (const bind of binds) {
|
|
209
|
+
if (bind.event !== ev.type) continue
|
|
210
|
+
|
|
211
|
+
if (bind.selector) {
|
|
212
|
+
if (!node.matches(bind.selector)) continue
|
|
213
|
+
} else {
|
|
214
|
+
if (node !== el) continue
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const wrappedEv = createWrappedEvent(ev, node)
|
|
218
|
+
bind.handler.call(node, wrappedEv)
|
|
219
|
+
|
|
220
|
+
if (wrappedEv._immediateStopped) return
|
|
221
|
+
|
|
222
|
+
if (wrappedEv._propagationStopped) {
|
|
223
|
+
propagationStoppedOnThisNode = true
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (propagationStoppedOnThisNode) return
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
let store = LISTENERS.get(el)
|
|
232
|
+
if (!store) {
|
|
233
|
+
store = []
|
|
234
|
+
LISTENERS.set(el, store)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (inArray(event, CUSTOM_EVENTS)) {
|
|
238
|
+
supplyEvent(event)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const events = map(store, (_, entry) => entry.event)
|
|
242
|
+
|
|
243
|
+
if (!inArray(event, events)) {
|
|
244
|
+
el.addEventListener(event, listener, options)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
store.push({ event, handler, selector, listener, namespace, options })
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
return el
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* @param {Element|Document|Window} el
|
|
255
|
+
* @param {string} [events]
|
|
256
|
+
* @param {string|Element|function} [selector]
|
|
257
|
+
* @param {function|AddEventListenerOptions|boolean} [handler]
|
|
258
|
+
* @param {AddEventListenerOptions|boolean} [options]
|
|
259
|
+
* @returns {Element}
|
|
260
|
+
*/
|
|
261
|
+
export function off(el, events, selector, handler, options) {
|
|
262
|
+
if (isFunction(selector)) {
|
|
263
|
+
options = handler
|
|
264
|
+
handler = selector
|
|
265
|
+
selector = null
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const store = LISTENERS.get(el)
|
|
269
|
+
if (!store) return el
|
|
270
|
+
|
|
271
|
+
const evts = events ? events.split(' ') : [undefined]
|
|
272
|
+
|
|
273
|
+
foreach(evts, (rawEvent) => {
|
|
274
|
+
let [event, namespace] =
|
|
275
|
+
undefined === rawEvent ? [undefined, undefined] : rawEvent.split('.')
|
|
276
|
+
|
|
277
|
+
event = !event ? undefined : event
|
|
278
|
+
|
|
279
|
+
const hasEvent = undefined !== event
|
|
280
|
+
const hasNs = undefined !== namespace
|
|
281
|
+
|
|
282
|
+
foreach([...store].reverse(), (l) => {
|
|
283
|
+
const match =
|
|
284
|
+
(!hasEvent && !hasNs) ||
|
|
285
|
+
(hasEvent && !hasNs && l.event === event) ||
|
|
286
|
+
(!hasEvent && hasNs && l.namespace === namespace) ||
|
|
287
|
+
(hasEvent && hasNs && l.event === event && l.namespace === namespace)
|
|
288
|
+
|
|
289
|
+
if (
|
|
290
|
+
match &&
|
|
291
|
+
(undefined === event || l.event === event) &&
|
|
292
|
+
(undefined === handler || l.handler === handler) &&
|
|
293
|
+
(undefined === selector || l.selector === selector) &&
|
|
294
|
+
(undefined === namespace || l.namespace === namespace) &&
|
|
295
|
+
(undefined === options || l.options === options)
|
|
296
|
+
) {
|
|
297
|
+
const index = store.indexOf(l)
|
|
298
|
+
index !== -1 && store.splice(index, 1)
|
|
299
|
+
|
|
300
|
+
if (!map(store, (_, entry) => (entry.event === event ? entry : null))[0])
|
|
301
|
+
el.removeEventListener(l.event, l.listener, l.options)
|
|
302
|
+
}
|
|
303
|
+
})
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
return el
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export function __resetCustomEventsForTests() {
|
|
310
|
+
ENABLED_EVENTS.clear()
|
|
311
|
+
teardownLongTap?.()
|
|
312
|
+
teardownDblTap?.()
|
|
313
|
+
}
|
package/src/random.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export const randAlpha = function (n) {
|
|
2
|
+
return rand('abcdefghijklmnopqrstuvwxyz'.split(''), n)
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export const randAlphaCs = function (n) {
|
|
6
|
+
return rand('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), n)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const randAlphaNum = function (n) {
|
|
10
|
+
return rand('0123456789abcdefghijklmnopqrstuvwxyz'.split(''), n)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const randAlphaNumCs = function (n) {
|
|
14
|
+
return rand('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), n)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const randNum = function (n) {
|
|
18
|
+
return rand('0123456789'.split(''), n)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const rand = function (range, n) {
|
|
22
|
+
let rand = ''
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i < n; i++) {
|
|
25
|
+
rand += range[Math.floor(Math.random() * 1000) % range.length]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return rand
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const uniqid = (function () {
|
|
32
|
+
let uid = 0
|
|
33
|
+
|
|
34
|
+
return function (prefix = '') {
|
|
35
|
+
uid++
|
|
36
|
+
return `${prefix}${Date.now().toString(36)}_${uid.toString(36)}_${randAlphaNum(5)}`
|
|
37
|
+
}
|
|
38
|
+
})()
|