1 |
|
2 |
|
3 | import { window, isServer } from "./platform"
|
4 | import { noop } from "./utils"
|
5 |
|
6 |
|
7 |
|
8 | const requestAnimationFrame = isServer
|
9 | ? noop
|
10 | : window.requestAnimationFrame ||
|
11 | window.mozRequestAnimationFrame ||
|
12 | window.webkitRequestAnimationFrame ||
|
13 | ((fn) => { window.setTimeout(fn, 20) })
|
14 |
|
15 | const cancelAnimationFrame = isServer
|
16 | ? noop
|
17 | : window.cancelAnimationFrame ||
|
18 | window.mozCancelAnimationFrame ||
|
19 | window.webkitCancelAnimationFrame ||
|
20 | window.clearTimeout
|
21 |
|
22 | const isIE = isServer ? false : navigator.userAgent.match(/Trident/)
|
23 |
|
24 | const namespace = "__resizeDetector__"
|
25 |
|
26 |
|
27 |
|
28 | const uninitialize = (el) => {
|
29 | el[namespace].destroy()
|
30 | el[namespace] = undefined
|
31 | }
|
32 |
|
33 |
|
34 |
|
35 | const createElementHack = () => {
|
36 | const el = document.createElement("object")
|
37 | el.className = "resize-sensor"
|
38 | el.setAttribute("style", "display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;")
|
39 | el.setAttribute("class", "resize-sensor")
|
40 | el.type = "text/html"
|
41 | el.data = "about:blank"
|
42 | return el
|
43 | }
|
44 |
|
45 |
|
46 |
|
47 | const initialize = (el) => {
|
48 |
|
49 | const detector = el[namespace] = {}
|
50 | detector.listeners = []
|
51 |
|
52 | const onResize = (e) => {
|
53 | |
54 |
|
55 | if (detector.resizeRAF) cancelAnimationFrame(detector.resizeRAF)
|
56 | detector.resizeRAF = requestAnimationFrame(() => {
|
57 | detector.listeners.forEach((fn) => { fn(e) })
|
58 | })
|
59 | }
|
60 |
|
61 | if (isIE) {
|
62 | |
63 |
|
64 | el.addEventListener("onresize", onResize)
|
65 | detector.destroy = () => {
|
66 | el.removeEventListener("onresize", onResize)
|
67 | }
|
68 | } else {
|
69 | if (getComputedStyle(el).position === "static") {
|
70 | detector.elWasStaticPosition = true
|
71 | el.style.position = "relative"
|
72 | }
|
73 | const objEl = createElementHack()
|
74 | objEl.onload = function (/* event */) {
|
75 | this.contentDocument.defaultView.addEventListener("resize", onResize)
|
76 | }
|
77 | detector.destroy = () => {
|
78 | if (detector.elWasStaticPosition) el.style.position = ""
|
79 |
|
80 |
|
81 | el.removeChild(objEl)
|
82 | }
|
83 |
|
84 | el.appendChild(objEl)
|
85 | }
|
86 | }
|
87 |
|
88 |
|
89 |
|
90 | const on = (el, fn) => {
|
91 |
|
92 | |
93 |
|
94 |
|
95 | if (el === window) {
|
96 | window.addEventListener("resize", fn)
|
97 | return
|
98 | }
|
99 |
|
100 |
|
101 |
|
102 | if (!el[namespace]) initialize(el)
|
103 | el[namespace].listeners.push(fn)
|
104 | }
|
105 |
|
106 |
|
107 |
|
108 | const off = (el, fn) => {
|
109 | if (el === window) {
|
110 | window.removeEventListener("resize", fn)
|
111 | return
|
112 | }
|
113 | const detector = el[namespace]
|
114 | if (!detector) return
|
115 | const i = detector.listeners.indexOf(fn)
|
116 | if (i !== -1) detector.listeners.splice(i, 1)
|
117 | if (!detector.listeners.length) uninitialize(el)
|
118 | }
|
119 |
|
120 |
|
121 |
|
122 | export default {
|
123 | on,
|
124 | off,
|
125 | addEventListener: on,
|
126 | removeEventListener: off,
|
127 | }
|
128 | export {
|
129 | on,
|
130 | off,
|
131 | on as addEventListener,
|
132 | off as removeEventListener,
|
133 | }
|