mirror of
https://github.com/john-okeefe/foliate-js.git
synced 2026-09-09 11:29:14 -04:00
Add header and footer
Also allow getting next location, which is useful for the footer
This commit is contained in:
+66
-3
@@ -128,6 +128,24 @@ const getBackground = doc => {
|
||||
: bodyStyle.background
|
||||
}
|
||||
|
||||
const makeMarginals = length => Array.from({ length }, () => {
|
||||
const div = document.createElement('div')
|
||||
const child = document.createElement('div')
|
||||
div.append(child)
|
||||
Object.assign(div.style, {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
minWidth: '0',
|
||||
})
|
||||
Object.assign(child.style, {
|
||||
overflow: 'hidden',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
})
|
||||
return div
|
||||
})
|
||||
|
||||
class View {
|
||||
#element = document.createElement('div')
|
||||
#iframe = document.createElement('iframe')
|
||||
@@ -320,6 +338,8 @@ class View {
|
||||
export class Paginator {
|
||||
#element = document.createElement('div')
|
||||
#container = document.createElement('div')
|
||||
#header = document.createElement('div')
|
||||
#footer = document.createElement('div')
|
||||
#view
|
||||
#vertical = false
|
||||
#rtl = false
|
||||
@@ -348,6 +368,18 @@ export class Paginator {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
})
|
||||
|
||||
const marginalStyle = {
|
||||
position: 'absolute', left: '0', right: '0',
|
||||
display: 'grid',
|
||||
fontFamily: 'system-ui',
|
||||
opacity: '.5',
|
||||
}
|
||||
Object.assign(this.#header.style, marginalStyle, { top: '0' })
|
||||
Object.assign(this.#footer.style, marginalStyle, { bottom: '0' })
|
||||
this.#element.append(this.#header)
|
||||
this.#element.append(this.#footer)
|
||||
|
||||
new ResizeObserver(() => this.render()).observe(this.#element)
|
||||
this.#container.addEventListener('scroll', debounce(() => {
|
||||
if (this.scrolled) this.#afterScroll('scroll')
|
||||
@@ -371,14 +403,22 @@ export class Paginator {
|
||||
this.#element.style.background = background
|
||||
|
||||
const { flow, margin, gap, maxColumnWidth } = this.layout
|
||||
|
||||
if (flow === 'scrolled') {
|
||||
// FIXME: vertical-rl only, not -lr
|
||||
this.#element.setAttribute('dir', vertical ? 'rtl' : 'ltr')
|
||||
this.#element.style.padding = '0'
|
||||
this.#container.style.overflow ='scroll'
|
||||
const columnWidth = this.layout.maxColumnWidth
|
||||
|
||||
this.heads = null
|
||||
this.feet = null
|
||||
this.#header.replaceChildren()
|
||||
this.#footer.replaceChildren()
|
||||
|
||||
return { flow, margin, gap, columnWidth }
|
||||
}
|
||||
|
||||
const { width, height } = this.#container.getBoundingClientRect()
|
||||
const size = vertical ? height : width
|
||||
const divisor = Math.ceil(size / maxColumnWidth)
|
||||
@@ -388,6 +428,25 @@ export class Paginator {
|
||||
const paddingV = `${vertical ? margin - gap / 2 : margin}px`
|
||||
this.#element.style.padding = `${paddingV} ${paddingH}`
|
||||
this.#container.style.overflow ='hidden'
|
||||
|
||||
const marginalHeight = `${margin * .85}px`
|
||||
const marginalStyle = {
|
||||
height: marginalHeight,
|
||||
gridTemplateColumns: `repeat(${divisor}, 1fr)`,
|
||||
gap: `${gap}px`,
|
||||
padding: `0 ${gap}px`,
|
||||
fontSize: `min(.75em, ${marginalHeight})`,
|
||||
lineHeight: marginalHeight,
|
||||
}
|
||||
Object.assign(this.#header.style, marginalStyle)
|
||||
Object.assign(this.#footer.style, marginalStyle)
|
||||
const heads = makeMarginals(divisor)
|
||||
const feet = makeMarginals(divisor)
|
||||
this.heads = heads.map(el => el.children[0])
|
||||
this.feet = feet.map(el => el.children[0])
|
||||
this.#header.replaceChildren(...heads)
|
||||
this.#footer.replaceChildren(...feet)
|
||||
|
||||
return { height, width, margin, gap, columnWidth }
|
||||
}
|
||||
render() {
|
||||
@@ -524,11 +583,15 @@ export class Paginator {
|
||||
const range = this.#getVisibleRange()
|
||||
// don't set new anchor if relocation was to scroll to anchor
|
||||
if (reason !== 'anchor') this.#anchor = range
|
||||
|
||||
const index = this.#index
|
||||
if (this.scrolled)
|
||||
this.onRelocated?.(range, index, this.end / this.viewSize)
|
||||
else if (this.pages > 0)
|
||||
this.onRelocated?.(range, index, (this.page + 1) / this.pages)
|
||||
this.onRelocated?.(range, index, this.start / this.viewSize)
|
||||
else if (this.pages > 0) {
|
||||
const { page, pages } = this
|
||||
this.#header.style.visibility = page > 0 ? 'visible' : 'hidden'
|
||||
this.onRelocated?.(range, index, page / pages, 1 / pages)
|
||||
}
|
||||
}
|
||||
async #display(promise) {
|
||||
const { index, src, anchor, onLoad, select } = await promise
|
||||
|
||||
Reference in New Issue
Block a user