git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Tree: c50f73d28c82ec782f6fca2e0a41d3b4d138becb

Files: c50f73d28c82ec782f6fca2e0a41d3b4d138becb / lib / pull-scroll.js

2999 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 Obv = require('obv')
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 obv = Obv()
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 obv.set(queue.length)
47 }
48 }
49
50 function scroll (ev) {
51 if(isEnd(scroller, buffer, isPrepend)) {
52 pause.resume()
53 }
54 }
55
56 pause.pause()
57
58 //wait until the scroller has been added to the document
59 next(function next () {
60 if(scroller.parentElement) pause.resume()
61 else setTimeout(next, 100)
62 })
63
64 var stream = pull(
65 pause,
66 pull.drain(function (e) {
67 queue.push(e)
68 obv.set(queue.length)
69
70 if(content.clientHeight < window.innerHeight)
71 add()
72
73 if (isVisible(content)) {
74 if (isEnd(scroller, buffer, isPrepend))
75 add()
76 }
77
78 if(queue.length > 5)
79 pause.pause()
80
81 }, function (err) {
82 if(err) console.error(err)
83 cb ? cb(err) : console.error(err)
84 })
85 )
86
87 stream.visible = add
88 stream.observ = obv
89 return stream
90}
91
92
93function append(scroller, list, el, isPrepend, isSticky) {
94 if(!el) return
95 var s = scroller.scrollHeight
96 var st = scroller.scrollTop
97 if(isPrepend && list.firstChild)
98 list.insertBefore(el, list.firstChild)
99 else
100 list.appendChild(el)
101
102 //scroll down by the height of the thing added.
103 //if it added to the top (in non-sticky mode)
104 //or added it to the bottom (in sticky mode)
105 if(isPrepend !== isSticky) {
106 var d = (scroller.scrollHeight - s)
107 var before = scroller.scrollTop
108 //check whether the browser has moved the scrollTop for us.
109 //if you add an element that is not scrolled into view
110 //it no longer bumps the view down! but this check is still needed
111 //for firefox.
112 //this seems to be the behavior in recent chrome (also electron)
113 if(st === scroller.scrollTop) {
114 scroller.scrollTop = scroller.scrollTop + d
115 }
116 }
117}
118

Built with git-ssb-web