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 | const isServer = typeof window === 'undefined';
|
28 |
|
29 |
|
30 | const requestFrame = (function() {
|
31 | if (isServer) return;
|
32 | const raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
|
33 | function(fn) {
|
34 | return window.setTimeout(fn, 20);
|
35 | };
|
36 | return function(fn) {
|
37 | return raf(fn);
|
38 | };
|
39 | })();
|
40 |
|
41 |
|
42 | const cancelFrame = (function() {
|
43 | if (isServer) return;
|
44 | const cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.clearTimeout;
|
45 | return function(id) {
|
46 | return cancel(id);
|
47 | };
|
48 | })();
|
49 |
|
50 |
|
51 | const resetTrigger = function(element) {
|
52 | const trigger = element.__resizeTrigger__;
|
53 | const expand = trigger.firstElementChild;
|
54 | const contract = trigger.lastElementChild;
|
55 | const expandChild = expand.firstElementChild;
|
56 |
|
57 | contract.scrollLeft = contract.scrollWidth;
|
58 | contract.scrollTop = contract.scrollHeight;
|
59 | expandChild.style.width = expand.offsetWidth + 1 + 'px';
|
60 | expandChild.style.height = expand.offsetHeight + 1 + 'px';
|
61 | expand.scrollLeft = expand.scrollWidth;
|
62 | expand.scrollTop = expand.scrollHeight;
|
63 | };
|
64 |
|
65 |
|
66 | const checkTriggers = function(element) {
|
67 | return element.offsetWidth !== element.__resizeLast__.width || element.offsetHeight !== element.__resizeLast__.height;
|
68 | };
|
69 |
|
70 |
|
71 | const scrollListener = function(event) {
|
72 | resetTrigger(this);
|
73 | if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
|
74 | this.__resizeRAF__ = requestFrame(() => {
|
75 | if (checkTriggers(this)) {
|
76 | this.__resizeLast__.width = this.offsetWidth;
|
77 | this.__resizeLast__.height = this.offsetHeight;
|
78 | this.__resizeListeners__.forEach((fn) => {
|
79 | fn.call(this, event);
|
80 | });
|
81 | }
|
82 | });
|
83 | };
|
84 |
|
85 |
|
86 | const attachEvent = isServer ? {} : document.attachEvent;
|
87 | const DOM_PREFIXES = 'Webkit Moz O ms'.split(' ');
|
88 | const START_EVENTS = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' ');
|
89 | const RESIZE_ANIMATION_NAME = 'resizeanim';
|
90 | let animation = false;
|
91 | let keyFramePrefix = '';
|
92 | let animationStartEvent = 'animationstart';
|
93 |
|
94 |
|
95 | if (!attachEvent && !isServer) {
|
96 | const testElement = document.createElement('fakeelement');
|
97 | if (testElement.style.animationName !== undefined) {
|
98 | animation = true;
|
99 | }
|
100 |
|
101 | if (animation === false) {
|
102 | let prefix = '';
|
103 | for (var i = 0; i < DOM_PREFIXES.length; i++) {
|
104 | if (testElement.style[DOM_PREFIXES[i] + 'AnimationName'] !== undefined) {
|
105 | prefix = DOM_PREFIXES[i];
|
106 | keyFramePrefix = '-' + prefix.toLowerCase() + '-';
|
107 | animationStartEvent = START_EVENTS[i];
|
108 | animation = true;
|
109 | break;
|
110 | }
|
111 | }
|
112 | }
|
113 | }
|
114 |
|
115 | let stylesCreated = false;
|
116 |
|
117 | const createStyles = function() {
|
118 | if (!stylesCreated && !isServer) {
|
119 | const animationKeyframes = `@${keyFramePrefix}keyframes ${RESIZE_ANIMATION_NAME} { from { opacity: 0; } to { opacity: 0; } } `;
|
120 | const animationStyle = `${keyFramePrefix}animation: 1ms ${RESIZE_ANIMATION_NAME};`;
|
121 |
|
122 |
|
123 | const css = `${animationKeyframes}
|
124 | .resize-triggers { ${animationStyle} visibility: hidden; opacity: 0; }
|
125 | .resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; z-index: -1 }
|
126 | .resize-triggers > div { background: #eee; overflow: auto; }
|
127 | .contract-trigger:before { width: 200%; height: 200%; }`;
|
128 |
|
129 | const head = document.head || document.getElementsByTagName('head')[0];
|
130 | const style = document.createElement('style');
|
131 |
|
132 | style.type = 'text/css';
|
133 | if (style.styleSheet) {
|
134 | style.styleSheet.cssText = css;
|
135 | } else {
|
136 | style.appendChild(document.createTextNode(css));
|
137 | }
|
138 |
|
139 | head.appendChild(style);
|
140 | stylesCreated = true;
|
141 | }
|
142 | };
|
143 |
|
144 |
|
145 | export const addResizeListener = function(element, fn) {
|
146 | if (isServer) return;
|
147 | if (attachEvent) {
|
148 | element.attachEvent('onresize', fn);
|
149 | } else {
|
150 | if (!element.__resizeTrigger__) {
|
151 | if (getComputedStyle(element).position === 'static') {
|
152 | element.style.position = 'relative';
|
153 | }
|
154 | createStyles();
|
155 | element.__resizeLast__ = {};
|
156 | element.__resizeListeners__ = [];
|
157 |
|
158 | const resizeTrigger = element.__resizeTrigger__ = document.createElement('div');
|
159 | resizeTrigger.className = 'resize-triggers';
|
160 | resizeTrigger.innerHTML = '<div class="expand-trigger"><div></div></div><div class="contract-trigger"></div>';
|
161 | element.appendChild(resizeTrigger);
|
162 |
|
163 | resetTrigger(element);
|
164 | element.addEventListener('scroll', scrollListener, true);
|
165 |
|
166 |
|
167 | if (animationStartEvent) {
|
168 | resizeTrigger.addEventListener(animationStartEvent, function(event) {
|
169 | if (event.animationName === RESIZE_ANIMATION_NAME) {
|
170 | resetTrigger(element);
|
171 | }
|
172 | });
|
173 | }
|
174 | }
|
175 | element.__resizeListeners__.push(fn);
|
176 | }
|
177 | };
|
178 |
|
179 |
|
180 | export const removeResizeListener = function(element, fn) {
|
181 | if (attachEvent) {
|
182 | element.detachEvent('onresize', fn);
|
183 | } else {
|
184 | element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
|
185 | if (!element.__resizeListeners__.length) {
|
186 | element.removeEventListener('scroll', scrollListener);
|
187 | element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__);
|
188 | }
|
189 | }
|
190 | }; |
\ | No newline at end of file |