-
Notifications
You must be signed in to change notification settings - Fork 19
/
index.js
103 lines (93 loc) · 2.67 KB
/
index.js
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
98
99
100
101
102
103
/* global MutationObserver */
const document = require('global/document')
const window = require('global/window')
const watch = Object.create(null)
const KEY_ID = 'onloadid' + Math.random().toString(36).slice(2)
const KEY_ATTR = 'data-' + KEY_ID
let INDEX = 0
if (window && window.MutationObserver) {
const observer = new MutationObserver(function (mutations) {
if (!isHashValid(watch)) return
let i = mutations.length
while (i--) {
if (mutations[i].attributeName === KEY_ATTR) {
eachAttr(mutations[i], turnon, turnoff)
continue
}
eachMutation(mutations[i].removedNodes, function (index, el) {
if (!document.documentElement.contains(el)) turnoff(index, el)
})
eachMutation(mutations[i].addedNodes, function (index, el) {
if (document.documentElement.contains(el)) turnon(index, el)
})
}
})
observer.observe(document.documentElement, {
childList: true,
subtree: true,
attributes: true,
attributeOldValue: true,
attributeFilter: [KEY_ATTR]
})
}
module.exports = function onload (el, on, off, caller) {
on = on || function () {}
off = off || function () {}
el.setAttribute(KEY_ATTR, 'o' + INDEX)
watch['o' + INDEX] = [on, off, 0, caller || onload.caller]
INDEX += 1
return el
}
module.exports.KEY_ATTR = KEY_ATTR
module.exports.KEY_ID = KEY_ID
function turnon (index, el) {
if (watch[index][0] && watch[index][2] === 0) {
watch[index][0](el)
watch[index][2] = 1
}
}
function turnoff (index, el) {
if (watch[index][1] && watch[index][2] === 1) {
watch[index][1](el)
watch[index][2] = 0
}
}
function eachAttr (mutation, on, off) {
const newValue = mutation.target.getAttribute(KEY_ATTR)
if (sameOrigin(mutation.oldValue, newValue)) {
watch[newValue][2] = watch[mutation.oldValue][2]
return
}
if (watch[mutation.oldValue]) {
off(mutation.oldValue, mutation.target)
}
if (watch[newValue]) {
on(newValue, mutation.target)
}
}
function sameOrigin (oldValue, newValue) {
if (!oldValue || !newValue) return false
return watch[oldValue][3] === watch[newValue][3]
}
function eachMutation (nodes, fn) {
const keys = Object.keys(watch)
for (let i = 0; i < nodes.length; i++) {
if (nodes[i] && nodes[i].getAttribute && nodes[i].getAttribute(KEY_ATTR)) {
const onloadid = nodes[i].getAttribute(KEY_ATTR)
keys.forEach(function (k) {
if (onloadid === k) {
fn(k, nodes[i])
}
})
}
if (nodes[i] && nodes[i].childNodes.length > 0) {
eachMutation(nodes[i].childNodes, fn)
}
}
}
function isHashValid (hash) {
/* eslint-disable no-unreachable-loop */
for (const k in hash) {
return k
}
}