1
- import { on } from './events' ;
1
+ import { on , once } from './events' ;
2
2
import { debounceFrame } from './delays' ;
3
3
4
- export function observeVisibility ( items , once ) {
5
- if ( ! items || ! items . length ) return { off : ( ) => { } } ;
6
-
7
- const observer = new IntersectionObserver ( ( entries ) => {
8
- console . log ( 'IntersectionObserver 2' , entries ) ;
9
- entries . forEach ( entry => {
10
- if ( entry . isIntersecting ) {
11
- console . log ( 'is Intersecting' , entry ) ;
12
- entry . target . classList . add ( 'is-in-view' ) ;
13
- if ( once ) {
14
- observer . unobserve ( entry . target ) ;
15
- }
16
- } else {
17
- console . log ( 'not Intersecting' , entry ) ;
18
- entry . target . classList . remove ( 'is-in-view' ) ;
19
- }
20
- } ) ;
21
- } , {
22
- threshold : 0.5
4
+ /* global Promise */
5
+ export function observeVisibility ( items , doOnce ) {
6
+ if ( ! items || ! items . length ) return { off : ( ) => { } } ;
7
+
8
+ const observer = new IntersectionObserver ( ( entries ) => {
9
+ //console.log('IntersectionObserver 2', entries);
10
+ entries . forEach ( entry => {
11
+ if ( entry . isIntersecting ) {
12
+ //console.log('is Intersecting', entry);
13
+ entry . target . classList . add ( 'is-in-view' ) ;
14
+ if ( doOnce ) {
15
+ observer . unobserve ( entry . target ) ;
16
+ }
17
+ } else {
18
+ //console.log('not Intersecting', entry);
19
+ entry . target . classList . remove ( 'is-in-view' ) ;
20
+ }
23
21
} ) ;
22
+ } , { threshold : 0.5 } ) ;
24
23
25
- if ( items && items . length ) {
26
- for ( let i = 0 ; i < items . length ; i ++ ) {
27
- observer . observe ( items [ i ] ) ;
28
- }
24
+ if ( items && items . length ) {
25
+ for ( let i = 0 ; i < items . length ; i ++ ) {
26
+ observer . observe ( items [ i ] ) ;
29
27
}
28
+ }
30
29
31
- return {
32
- off : ( ) => {
33
- observer . disconnect ( ) ;
34
- }
35
- } ;
30
+ return {
31
+ off : ( ) => {
32
+ observer . disconnect ( ) ;
33
+ }
34
+ } ;
36
35
}
37
36
38
37
let vpW = window . innerWidth ;
39
38
let vpH = window . innerHeight ;
40
39
function elementIsVisible ( el ) {
41
- // FIXME: performance issue, cache this somewhere
42
- const rect = el . getBoundingClientRect ( ) ;
43
- if ( rect . top <= - rect . height || rect . top >= vpH ) {
44
- return false ;
45
- }
40
+ // FIXME: performance issue, cache this somewhere
41
+ const rect = el . getBoundingClientRect ( ) ;
42
+ if ( rect . top <= - rect . height || rect . top >= vpH ) {
43
+ return false ;
44
+ }
46
45
47
- if ( rect . left <= - rect . width || rect . left >= vpW ) {
48
- return false ;
49
- }
46
+ if ( rect . left <= - rect . width || rect . left >= vpW ) {
47
+ return false ;
48
+ }
50
49
51
- return true ;
50
+ return true ;
52
51
}
53
52
54
- function detectVisibility ( items , once ) {
55
- items . forEach ( el => {
56
- if ( once && el . classList . contains ( 'is-in-view' ) ) {
57
- return ;
58
- }
59
-
60
- if ( elementIsVisible ( el ) ) {
61
- el . classList . add ( 'is-in-view' ) ;
62
- } else {
63
- el . classList . remove ( 'is-in-view' ) ;
64
- }
53
+ const isInView = el => el . classList . contains ( 'is-in-view' ) ;
54
+
55
+ function detectVisibility ( items , doOnce ) {
56
+ return Promise . all ( items . map ( el => {
57
+ return new Promise ( ( resolve ) => {
58
+ if ( doOnce && isInView ( el ) ) {
59
+ //console.log('This probably should not happen');
60
+ resolve ( ) ;
61
+ return ;
62
+ }
63
+
64
+ if ( el . classList . contains ( 'is-animating' ) ) {
65
+ resolve ( ) ;
66
+ return ;
67
+ }
68
+
69
+ if ( ! elementIsVisible ( el ) ) {
70
+ el . classList . remove ( 'is-in-view' ) ;
71
+ resolve ( ) ;
72
+ } else if ( ! isInView ( el ) ) {
73
+ once ( el , 'animationend' , ( ) => {
74
+ el . classList . remove ( 'is-animating' ) ;
75
+ resolve ( ) ;
76
+ } ) ;
77
+ el . classList . add ( 'is-animating' , 'is-in-view' ) ;
78
+ } else {
79
+ resolve ( ) ;
80
+ }
65
81
} ) ;
82
+ } ) ) ;
66
83
}
67
84
68
85
const listenerQueue = { } ;
69
86
function detectAnimationVisibility ( ) {
70
- //console.log('detectAnimationVisibility');
87
+ //console.log('detectAnimationVisibility');
71
88
72
- Object . keys ( listenerQueue ) . map ( key => listenerQueue [ key ] ) . forEach ( _ => {
73
- detectVisibility ( _ . items , _ . once ) ;
74
- } ) ;
89
+ Object . keys ( listenerQueue ) . forEach ( key => {
90
+ const _ = listenerQueue [ key ] ;
91
+
92
+ const p = detectVisibility ( _ . items , _ . once )
93
+
94
+ if ( _ . once ) {
95
+ p . then ( ( ) => {
96
+ _ . items = _ . items . filter ( el => ! isInView ( el ) ) ;
97
+
98
+ if ( ! _ . items . length && listenerQueue [ key ] ) {
99
+ //console.log(key, 'has none left');
100
+ delete listenerQueue [ key ] ;
101
+ }
102
+ } ) ;
103
+ }
104
+ } ) ;
75
105
}
76
106
77
107
const debouncedDetectAnimationVisibility = debounceFrame ( ( ) => {
78
- detectAnimationVisibility ( ) ;
108
+ detectAnimationVisibility ( ) ;
79
109
} ) ;
80
110
81
111
let activeVisibility ;
82
112
function listenOnChanges ( ) {
83
- if ( ! activeVisibility ) {
84
- let events = [
85
- on ( window , 'resize' , ( ) => {
86
- //console.log('resize');
87
- vpW = window . innerWidth ;
88
- vpH = window . innerHeight ;
89
- debouncedDetectAnimationVisibility ( ) ;
90
- } ) ,
91
- on ( window , 'scroll' , ( ) => {
92
- //console.log('scroll');
93
- debouncedDetectAnimationVisibility ( ) ;
94
- } )
95
- ] ;
96
-
113
+ if ( ! activeVisibility ) {
114
+ const events = [
115
+ on ( window , 'resize' , ( ) => {
116
+ //console.log('resize');
117
+ vpW = window . innerWidth ;
118
+ vpH = window . innerHeight ;
119
+ debouncedDetectAnimationVisibility ( ) ;
120
+ } ) ,
121
+ on ( window , 'scroll' , ( ) => {
122
+ //console.log('scroll');
97
123
debouncedDetectAnimationVisibility ( ) ;
124
+ } )
125
+ ] ;
98
126
99
- activeVisibility = {
100
- off : ( ) => {
101
- events . forEach ( _ => _ . off ( ) ) ;
102
- }
103
- } ;
104
- }
127
+ debouncedDetectAnimationVisibility ( ) ;
105
128
106
- return activeVisibility ;
129
+ activeVisibility = {
130
+ off : ( ) => {
131
+ events . forEach ( _ => _ . off ( ) ) ;
132
+ }
133
+ } ;
134
+ }
135
+
136
+ return activeVisibility ;
107
137
}
108
138
109
- export function monitorVisibility ( selector , once ) {
110
- if ( ! listenerQueue . hasOwnProperty ( selector ) ) {
111
- const els = document . querySelectorAll ( selector ) ;
112
- if ( els && els . length ) {
113
- listenerQueue [ selector ] = {
114
- items : els ,
115
- once : once || false
116
- } ;
117
- listenOnChanges ( ) ;
118
- }
139
+ export function monitorVisibility ( selector , doOnce ) {
140
+ if ( ! listenerQueue . hasOwnProperty ( selector ) ) {
141
+ const els = Array . prototype . slice . call ( document . querySelectorAll ( selector ) ) ;
142
+ if ( els && els . length ) {
143
+ listenerQueue [ selector ] = {
144
+ items : els ,
145
+ once : doOnce || false
146
+ } ;
147
+ listenOnChanges ( ) ;
119
148
}
149
+ }
120
150
121
- return {
122
- off : function ( ) {
123
- activeVisibility && activeVisibility . off ( ) ;
124
- }
125
- } ;
126
- }
151
+ return {
152
+ off : function ( ) {
153
+ activeVisibility && activeVisibility . off ( ) ;
154
+ }
155
+ } ;
156
+ }
0 commit comments