git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Tree: a0d45464afed54dcb36fdf48278c914c2204a62e

Files: a0d45464afed54dcb36fdf48278c914c2204a62e / lib / pull-scroll.js

3022 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 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 obs.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
82 }, function (err) {
83 if(err) console.error(err)
84 cb ? cb(err) : console.error(err)
85 })
86 )
87
88 stream.visible = add
89 stream.queue = obs
90 return stream
91}
92
93
94function append(scroller, list, el, isPrepend, isSticky) {
95 if(!el) return
96 var s = scroller.scrollHeight
97 var st = scroller.scrollTop
98 if(isPrepend && list.firstChild)
99 list.insertBefore(el, list.firstChild)
100 else
101 list.appendChild(el)
102
103 //scroll down by the height of the thing added.
104 //if it added to the top (in non-sticky mode)
105 //or added it to the bottom (in sticky mode)
106 if(isPrepend !== isSticky) {
107 var d = (scroller.scrollHeight - s)
108 var before = scroller.scrollTop
109 //check whether the browser has moved the scrollTop for us.
110 //if you add an element that is not scrolled into view
111 //it no longer bumps the view down! but this check is still needed
112 //for firefox.
113 //this seems to be the behavior in recent chrome (also electron)
114 if(st === scroller.scrollTop) {
115 scroller.scrollTop = scroller.scrollTop + d
116 }
117 }
118}
119

Built with git-ssb-web