Files: 2bb5c91108d1ef5bc4ec2b74e6556e058b2198c2 / app / html / scroller.js
2304 bytesRaw
1 | const nest = require('depnest') |
2 | const { h } = require('mutant') |
3 | |
4 | exports.gives = nest('app.html.scroller') |
5 | |
6 | exports.create = function (api) { |
7 | return nest('app.html.scroller', Scroller) |
8 | |
9 | function Scroller (opts = {}) { |
10 | const { prepend, content = null, append, classList = [], className = '', title = '', scrollIntoView } = opts |
11 | |
12 | const contentSection = h('section.content', { title: '' }, content) |
13 | |
14 | const container = h('Scroller', |
15 | { |
16 | classList, |
17 | className, |
18 | title, |
19 | style: { 'overflow-y': 'scroll', 'overflow-x': 'auto' }, |
20 | intersectionBindingViewport: { rootMargin: '1000px' } // mutant magic |
21 | // TODO (watch for breaks e.g. stuff stops updating after scrolling) |
22 | }, |
23 | [ |
24 | prepend ? h('section.top', prepend) : null, |
25 | contentSection, |
26 | append ? h('section.bottom', append) : null |
27 | ] |
28 | ) |
29 | |
30 | container.keyboardScroll = KeyboardScroll(contentSection, scrollIntoView) |
31 | |
32 | return { |
33 | content: contentSection, |
34 | container |
35 | } |
36 | } |
37 | } |
38 | |
39 | function KeyboardScroll (content, scrollIntoView = false) { |
40 | var curMsgEl |
41 | |
42 | if (!content) return () => {} |
43 | |
44 | content.addEventListener('click', onActivateChild, false) |
45 | content.addEventListener('focus', onActivateChild, true) |
46 | |
47 | function onActivateChild (ev) { |
48 | for (var el = ev.target; el; el = el.parentNode) { |
49 | if (el.parentNode === content) { |
50 | curMsgEl = el |
51 | return |
52 | } |
53 | } |
54 | } |
55 | |
56 | return function scroll (d) { |
57 | const child = (!curMsgEl || d === 'first') ? content.firstChild |
58 | : (!curMsgEl || d === 'last') ? content.lastChild |
59 | : d < 0 ? curMsgEl.previousElementSibling || content.firstChild |
60 | : d > 0 ? curMsgEl.nextElementSibling || content.lastChild |
61 | : curMsgEl |
62 | |
63 | selectChild(child) |
64 | curMsgEl = child |
65 | |
66 | return curMsgEl |
67 | } |
68 | |
69 | function selectChild (el) { |
70 | if (!el) { return } |
71 | |
72 | if (scrollIntoView) { |
73 | if (!el.scrollIntoViewIfNeeded && !el.scrollIntoView) return |
74 | ;(el.scrollIntoViewIfNeeded || el.scrollIntoView).call(el) |
75 | } else { |
76 | const height = el.offsetTop - content.parentElement.offsetTop - 10 |
77 | // content.parentElement.scroll({ top: height, behavior: 'smooth' }) |
78 | content.parentElement.scrollTop = height |
79 | } |
80 | |
81 | if (el.focus) el.focus() |
82 | } |
83 | } |
84 |
Built with git-ssb-web