-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathevents.js
More file actions
92 lines (88 loc) · 3.17 KB
/
events.js
File metadata and controls
92 lines (88 loc) · 3.17 KB
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
import noop from '../shared/noop'
import { camelize } from '../shared/string'
import router from './router'
export const eventCallbacks = new WeakMap()
export const eventSubjects = new WeakMap()
export const eventDebouncer = new WeakMap()
export function generateSubject(selector, attributes, name) {
if (Array.isArray(attributes[name])) {
for (let i = 0; i < attributes[name].length; i++) {
if (typeof attributes[name][i] === 'object') {
let changeset = attributes[name][i]
attributes[name][i] = () => Object.assign(attributes.source, changeset)
}
}
} else if (typeof attributes[name] === 'object') {
let changeset = attributes[name]
attributes[name] = () => Object.assign(attributes.source, changeset)
}
eventSubjects.set(selector, attributes)
}
function debounce(selector, name, time, callback) {
if (!time) {
callback()
} else {
const eventMap = eventDebouncer.get(selector) || {}
clearTimeout(eventMap[name])
eventMap[name] = setTimeout(callback, time)
eventDebouncer.set(selector, eventMap)
}
}
export function generateCallback(selector, name) {
let eventNames = eventCallbacks.get(selector)
if (!eventNames) {
eventNames = {}
eventCallbacks.set(selector, eventNames)
}
const callback = function eventCallback(event) {
const subject = eventSubjects.get(selector)
if (!subject) return
if (subject.href) {
if (!event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
event.preventDefault()
router.url = subject.href
}
} else if (subject.default !== true) {
event.preventDefault()
}
debounce(selector, name, subject.debounce, () => {
const data = { ...subject.data }
for (const attribute in subject) {
if (attribute.startsWith('data-')) {
const key = camelize(attribute.slice(5))
data[key] = subject[attribute]
}
}
if (subject?.bind !== undefined) {
const valueName = subject.type === 'checkbox' || subject.type === 'radio' ? 'checked' : 'value'
const object = subject.bind.object
const property = subject.bind.property
if (valueName === 'checked') {
object[property] = event.target[valueName]
} else if (object[property] === true || object[property] === false) {
object[property] = event.target[valueName] === 'true'
} else if (typeof object[property] === 'number') {
object[property] = +event.target[valueName] || 0
} else if (object[property] instanceof Date) {
const [yyyy, mm, dd] = event.target[valueName].split('-')
object[property].setFullYear(yyyy)
object[property].setMonth(+mm - 1)
object[property].setDate(dd)
object[property] = object[property]
} else {
object[property] = event.target[valueName]
}
}
if (subject[name] === noop) return
if (Array.isArray(subject[name])) {
for (const subcallback of subject[name]) {
subcallback({ ...subject, event, data })
}
} else {
subject[name]({ ...subject, event, data })
}
})
}
eventNames[name] = callback
return callback
}