mirror of
https://github.com/john-okeefe/foliate-js.git
synced 2026-09-09 11:29:14 -04:00
Reader: add footnote popovers
Lacks a "go to" button, but at least shows something instead of nothing
This commit is contained in:
+14
@@ -237,6 +237,20 @@ body {
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223%22%2F%3E%3C%2Fsvg%3E');
|
||||
}
|
||||
.popover {
|
||||
background: Canvas;
|
||||
color: CanvasText;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, .2), 0 0 16px rgba(0, 0, 0, .1), 0 0 32px rgba(0, 0, 0, .1);
|
||||
}
|
||||
.popover-arrow-down {
|
||||
fill: Canvas;
|
||||
filter: drop-shadow(0 -1px 0 rgba(0, 0, 0, .2));
|
||||
}
|
||||
.popover-arrow-up {
|
||||
fill: Canvas;
|
||||
filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .2));
|
||||
}
|
||||
</style>
|
||||
<input type="file" id="file-input" hidden>
|
||||
<div id="drop-target" class="filter">
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { View } from './view.js'
|
||||
import { createTOCView } from './ui/tree.js'
|
||||
import { createMenu } from './ui/menu.js'
|
||||
import { createPopover } from './ui/popover.js'
|
||||
|
||||
const { ZipReader, BlobReader, TextWriter, BlobWriter } = zip
|
||||
zip.configure({ useWebWorkers: false })
|
||||
@@ -119,6 +120,30 @@ const emit = obj => {
|
||||
if (tocItem?.href) setCurrentHref?.(tocItem.href)
|
||||
break
|
||||
}
|
||||
case 'reference': {
|
||||
const { content, pos: { point, dir } } = obj
|
||||
const iframe = document.createElement('iframe')
|
||||
iframe.sandbox = 'allow-same-origin'
|
||||
iframe.srcdoc = content
|
||||
iframe.onload = () => {
|
||||
const doc = iframe.contentDocument
|
||||
doc.documentElement.style.colorScheme = 'light dark'
|
||||
doc.body.style.margin = '18px'
|
||||
}
|
||||
Object.assign(iframe.style, {
|
||||
border: '0',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
})
|
||||
const { popover, arrow, overlay } = createPopover(300, 250, point, dir)
|
||||
overlay.style.zIndex = 3
|
||||
popover.style.zIndex = 3
|
||||
arrow.style.zIndex = 3
|
||||
popover.append(iframe)
|
||||
document.body.append(overlay)
|
||||
document.body.append(popover)
|
||||
document.body.append(arrow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
const clamp = (min, max, x) => Math.min(max, Math.max(min, x))
|
||||
|
||||
const arrowHeight = 10
|
||||
const arrowWidth = 20
|
||||
const radius = 6
|
||||
|
||||
const createSVGElement = tag =>
|
||||
document.createElementNS('http://www.w3.org/2000/svg', tag)
|
||||
|
||||
const createArrow = down => {
|
||||
const h = arrowHeight + 1
|
||||
const svg = createSVGElement('svg')
|
||||
svg.setAttribute('width', arrowWidth)
|
||||
svg.setAttribute('height', arrowHeight)
|
||||
const polygon = createSVGElement('polygon')
|
||||
polygon.setAttribute('points', down
|
||||
? `0 ${h}, ${arrowWidth / 2} 0, ${arrowWidth} ${h}`
|
||||
: `0 0, ${arrowWidth / 2} ${h}, ${arrowWidth} 0`)
|
||||
svg.classList.add(down ? 'popover-arrow-down' : 'popover-arrow-up')
|
||||
svg.append(polygon)
|
||||
return svg
|
||||
}
|
||||
|
||||
export const createPopover = (width, height, { x, y }, dir) => {
|
||||
const down = dir === 'down'
|
||||
const fullHeight = height + arrowHeight
|
||||
const overlay = document.createElement('div')
|
||||
Object.assign(overlay.style, {
|
||||
position: 'absolute',
|
||||
left: '0',
|
||||
top: '0',
|
||||
width: '100vw',
|
||||
height: '100vh',
|
||||
})
|
||||
const arrow = createArrow(down)
|
||||
Object.assign(arrow.style, {
|
||||
position: 'absolute',
|
||||
left: `${clamp(radius, window.innerWidth - arrowWidth - radius,
|
||||
x - arrowWidth / 2)}px`,
|
||||
top: `${clamp(0, window.innerHeight - arrowHeight,
|
||||
down ? y : y - arrowHeight)}px`,
|
||||
})
|
||||
const popover = document.createElement('div')
|
||||
popover.classList.add('popover')
|
||||
Object.assign(popover.style, {
|
||||
position: 'absolute',
|
||||
boxSizing: 'border-box',
|
||||
overflow: 'hidden',
|
||||
left: `${clamp(0, window.innerWidth - width, x - width / 2)}px`,
|
||||
top: `${clamp(0, window.innerHeight - fullHeight,
|
||||
down ? y + arrowHeight : y - fullHeight)}px`,
|
||||
width: `${width}px`,
|
||||
height: `${height}px`,
|
||||
})
|
||||
overlay.addEventListener('click', () => {
|
||||
overlay.parentNode.removeChild(overlay)
|
||||
arrow.parentNode.removeChild(arrow)
|
||||
popover.parentNode.removeChild(popover)
|
||||
})
|
||||
return { popover, arrow, overlay }
|
||||
}
|
||||
Reference in New Issue
Block a user