11import parseUnit from 'parse-unit'
22import eases from 'eases'
33
4- const instances = [ ]
4+ const scrollContainers = [ ]
55const isBrowser = typeof window !== 'undefined'
66
77/**
@@ -29,9 +29,9 @@ const debounce = function(fn, duration) {
2929 * @param {Array } instances
3030 * @returns {Array } instances - Active instances.
3131 */
32- const getActiveInstances = function ( instances ) {
32+ const getActiveInstances = function ( container ) {
3333
34- return instances . filter ( ( instance ) => instance != null && instance . isActive ( ) )
34+ return container . instances . filter ( ( instance ) => instance != null && instance . isActive ( ) )
3535
3636}
3737
@@ -40,21 +40,22 @@ const getActiveInstances = function(instances) {
4040 * @param {Array } instances
4141 * @returns {Array } instances - Tracked instances.
4242 */
43- const getTrackedInstances = function ( instances ) {
43+ const getTrackedInstances = function ( container ) {
4444
45- return instances . filter ( ( instance ) => instance != null && instance . getData ( ) . track )
45+ return container . instances . filter ( ( instance ) => instance != null && instance . getData ( ) . track )
4646
4747}
4848
4949
5050/**
5151 * Returns the number of scrolled pixels.
52+ * @param {Object } scrollingElement - Scrolling container.
5253 * @returns {Number } scrollTop
5354 */
54- const getScrollTop = function ( ) {
55+ const getScrollTop = function ( scrollingElement ) {
5556
5657 // Use scrollTop because it's faster than getBoundingClientRect()
57- return ( document . scrollingElement || document . documentElement ) . scrollTop
58+ return scrollingElement . scrollTop
5859
5960}
6061
@@ -127,12 +128,12 @@ const mapDirectToProperty = function(direct, properties) {
127128 * Converts a relative value to an absolute value.
128129 * @param {String } value
129130 * @param {Node } elem - Anchor of the relative value.
130- * @param {?Integer } scrollTop - Pixels scrolled in document .
131+ * @param {Object } scrollingElement - Scrolling container .
131132 * @param {?Integer } viewportHeight - Height of the viewport.
132133 * @returns {String } value - Absolute value.
133134 */
134- const relativeToAbsoluteValue = function ( value , elem , scrollTop = getScrollTop ( ) , viewportHeight = getViewportHeight ( ) ) {
135-
135+ const relativeToAbsoluteValue = function ( value , elem , scrollingElement , viewportHeight = getViewportHeight ( ) ) {
136+ const scrollTop = getScrollTop ( scrollingElement )
136137 const elemSize = elem . getBoundingClientRect ( )
137138
138139 const elemAnchor = value . match ( / ^ [ a - z ] + / ) [ 0 ]
@@ -157,7 +158,7 @@ const relativeToAbsoluteValue = function(value, elem, scrollTop = getScrollTop()
157158 * @param {?Object } data
158159 * @returns {Object } data - Validated data.
159160 */
160- const validate = function ( data = { } ) {
161+ const validate = function ( data = { } , scrollingElement ) {
161162
162163 // Copy root object to avoid changes by reference
163164 data = Object . assign ( { } , data )
@@ -184,8 +185,8 @@ const validate = function(data = {}) {
184185
185186 } else {
186187
187- if ( isRelativeValue ( data . from ) === true ) data . from = relativeToAbsoluteValue ( data . from , data . elem )
188- if ( isRelativeValue ( data . to ) === true ) data . to = relativeToAbsoluteValue ( data . to , data . elem )
188+ if ( isRelativeValue ( data . from ) === true ) data . from = relativeToAbsoluteValue ( data . from , data . elem , scrollingElement )
189+ if ( isRelativeValue ( data . to ) === true ) data . to = relativeToAbsoluteValue ( data . to , data . elem , scrollingElement )
189190
190191 }
191192
@@ -224,12 +225,13 @@ const validate = function(data = {}) {
224225/**
225226 * Calculates the props of an instance.
226227 * @param {Object } instance
227- * @param {?Integer } scrollTop - Pixels scrolled in document .
228+ * @param {Object } scrollingElement - Scrolling container .
228229 * @returns {Object } Calculated props and the element to apply styles to.
229230 */
230- const getProps = function ( instance , scrollTop = getScrollTop ( ) ) {
231-
232- const data = instance . getData ( )
231+ const getProps = function ( instance ) {
232+ const data = instance . getData ( )
233+
234+ const scrollTop = getScrollTop ( instance . scrollingElement )
233235
234236 // 100% in pixel
235237 const total = data . to . value - data . from . value
@@ -322,49 +324,44 @@ const setProps = function(elem, props) {
322324 * Gets and sets new props when the user has scrolled and when there are active instances.
323325 * This part get executed with every frame. Make sure it's performant as hell.
324326 * @param {Object } style - Style object.
325- * @param {?Integer } previousScrollTop
326327 * @returns {?* }
327328 */
328- const loop = function ( style , previousScrollTop ) {
329+ const loop = function ( style ) {
329330
330331 // Continue loop
331332 const repeat = ( ) => {
332-
333- // It depends on the browser, but it turns out that closures
334- // are sometimes faster than .bind or .apply.
335- requestAnimationFrame ( ( ) => loop ( style , previousScrollTop ) )
336-
333+ scrollContainers . forEach ( container => {
334+ // console.log(1)
335+ // Get all active instances
336+
337+ const activeInstances = getActiveInstances ( container )
338+
339+ if ( activeInstances . length ) {
340+ const scrollTop = getScrollTop ( container . element )
341+
342+ if ( container . scrollTop !== scrollTop ) {
343+ activeInstances
344+ . map ( ( instance ) => getProps ( instance ) )
345+ . forEach ( ( { elem, props } ) => setProps ( elem , props ) )
346+
347+ container . previousScrollTop = scrollTop
348+ }
349+ }
350+ } )
351+ requestAnimationFrame ( repeat )
337352 }
338-
339- // Get all active instances
340- const activeInstances = getActiveInstances ( instances )
341-
342- // Only continue when active instances available
343- if ( activeInstances . length === 0 ) return repeat ( )
344-
345- const scrollTop = getScrollTop ( )
346-
347- // Only continue when scrollTop has changed
348- if ( previousScrollTop === scrollTop ) return repeat ( )
349- else previousScrollTop = scrollTop
350-
351- // Get and set new props of each instance
352- activeInstances
353- . map ( ( instance ) => getProps ( instance , scrollTop ) )
354- . forEach ( ( { elem, props } ) => setProps ( elem , props ) )
355-
356- repeat ( )
357-
353+ requestAnimationFrame ( repeat )
358354}
359355
360356/**
361357 * Creates a new instance.
362358 * @param {Object } data
363359 * @returns {Object } instance
364360 */
365- export const create = function ( data ) {
366-
361+ export const create = function ( data , scrollingElement = null ) {
367362 // Store the parsed data
363+ if ( ! scrollingElement ) scrollingElement = ( document . scrollingElement || document . documentElement )
364+ const _scrollingElement = scrollingElement
368365 let _data = null
369366
370367 // Store if instance is started or stopped
@@ -387,13 +384,13 @@ export const create = function(data) {
387384 // Parses and calculates data
388385 const _calculate = function ( ) {
389386
390- _data = validate ( data )
387+ _data = validate ( data , _scrollingElement )
391388
392389 }
393390
394391 // Update props
395392 const _update = ( ) => {
396-
393+
397394 // Get new props
398395 const { elem, props } = getProps ( instance )
399396
@@ -423,13 +420,17 @@ export const create = function(data) {
423420
424421 // Replace instance instead of deleting the item to avoid
425422 // that the index of other instances changes.
426- instances [ index ] = undefined
427-
423+ scrollContainers . forEach ( container => {
424+ if ( container . element == scrollingElement ) {
425+ container . instances [ index ] = undefined
426+ }
427+ } )
428428 }
429429
430430 // Assign instance to a variable so the instance can be used
431431 // elsewhere in the current function.
432432 const instance = {
433+ scrollingElement : scrollingElement ,
433434 isActive : _isActive ,
434435 getData : _getData ,
435436 calculate : _calculate ,
@@ -440,8 +441,28 @@ export const create = function(data) {
440441 }
441442
442443 // Store instance in global array and save the index
443- const index = instances . push ( instance ) - 1
444-
444+ let index = 0
445+
446+ // Store the scroll container to get their value
447+ let found = false
448+ scrollContainers . forEach ( container => {
449+ if ( container . element == scrollingElement ) {
450+ index = container . instances . push ( instance ) - 1
451+ found = true
452+ }
453+ } )
454+ if ( ! found ) {
455+ scrollContainers . push ( {
456+ element : scrollingElement ,
457+ instances : [
458+ instance
459+ ] ,
460+ previousScrollTop : 0
461+ } )
462+ }
463+
464+ console . log ( scrollContainers )
465+
445466 // Calculate data for the first time
446467 instance . calculate ( )
447468
@@ -455,16 +476,21 @@ if (isBrowser === true) {
455476 // Start to loop
456477 loop ( )
457478
479+ console . log ( 'okay' )
480+
458481 // Recalculate and update instances when the window size changes
459482 window . addEventListener ( 'resize' , debounce ( ( ) => {
460483
461- // Get all tracked instances
462- const trackedInstances = getTrackedInstances ( instances )
484+ scrollContainers . forEach ( container => {
485+
486+ // Get all tracked instances
487+ const trackedInstances = getTrackedInstances ( container )
463488
464- trackedInstances . forEach ( ( instance ) => {
465- instance . calculate ( )
466- instance . update ( )
467- } )
489+ trackedInstances . forEach ( ( instance ) => {
490+ instance . calculate ( )
491+ instance . update ( )
492+ } )
493+ } )
468494
469495 } , 50 ) )
470496
0 commit comments