git ssb

10+

Matt McKegg / patchwork



Tree: 7495ba504a750013427db3c17cf79911bdbe5106

Files: 7495ba504a750013427db3c17cf79911bdbe5106 / lib / pull-scroll.js

3035 bytesRaw
1// forked because of weird non-filling and over-resuming problems
2// should really PR this, but Dominic might not accept it :D
3
4var pull = require('pull-stream')
5var Pause = require('pull-pause')
6var Value = require('mutant/value')
7
8var next = 'undefined' === typeof setImmediate ? setTimeout : setImmediate
9var buffer = Math.max(window.innerHeight * 2, 1000)
10
11var u = require('pull-scroll/utils'),
12 assertScrollable = u.assertScrollable,
13 isEnd = u.isEnd,
14 isVisible = u.isVisible
15
16module.exports = Scroller
17
18
19function Scroller(scroller, content, render, isPrepend, isSticky, cb) {
20 assertScrollable(scroller)
21 var obs = Value(0)
22
23 //if second argument is a function,
24 //it means the scroller and content elements are the same.
25 if('function' === typeof content) {
26 cb = isSticky
27 isPrepend = render
28 render = content
29 content = scroller
30 }
31
32 if(!cb) cb = function (err) { if(err) throw err }
33
34 scroller.addEventListener('scroll', scroll)
35 var pause = Pause(function () {})
36 var queue = []
37
38 //apply some changes to the dom, but ensure that
39 //`element` is at the same place on screen afterwards.
40
41 function add () {
42 if(queue.length) {
43 var m = queue.shift()
44 var r = render(m)
45 append(scroller, content, r, isPrepend, isSticky)
46 obs.set(queue.length)
47 }
48 }
49
50 function scroll (ev) {
51 if (isEnd(scroller, buffer, isPrepend)) {
52 add()
53 pause.resume()
54 }
55 }
56
57 pause.pause()
58
59 //wait until the scroller has been added to the document
60 next(function next () {
61 if(scroller.parentElement) pause.resume()
62 else setTimeout(next, 100)
63 })
64
65 var stream = pull(
66 pause,
67 pull.drain(function (e) {
68 queue.push(e)
69 obs.set(queue.length)
70
71 if(content.clientHeight < window.innerHeight)
72 add()
73
74 if (isVisible(content)) {
75 if (isEnd(scroller, buffer, isPrepend))
76 add()
77 }
78
79 if(queue.length > 5) {
80 pause.pause()
81 }
82
83 }, function (err) {
84 if(err) console.error(err)
85 cb ? cb(err) : console.error(err)
86 })
87 )
88
89 stream.visible = add
90 stream.queue = obs
91 return stream
92}
93
94
95function append(scroller, list, el, isPrepend, isSticky) {
96 if(!el) return
97 var s = scroller.scrollHeight
98 var st = scroller.scrollTop
99 if(isPrepend && list.firstChild)
100 list.insertBefore(el, list.firstChild)
101 else
102 list.appendChild(el)
103
104 //scroll down by the height of the thing added.
105 //if it added to the top (in non-sticky mode)
106 //or added it to the bottom (in sticky mode)
107 if(isPrepend !== isSticky) {
108 var d = (scroller.scrollHeight - s)
109 var before = scroller.scrollTop
110 //check whether the browser has moved the scrollTop for us.
111 //if you add an element that is not scrolled into view
112 //it no longer bumps the view down! but this check is still needed
113 //for firefox.
114 //this seems to be the behavior in recent chrome (also electron)
115 if(st === scroller.scrollTop) {
116 scroller.scrollTop = scroller.scrollTop + d
117 }
118 }
119}
120

Built with git-ssb-web