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-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');
|
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>
|
</style>
|
||||||
<input type="file" id="file-input" hidden>
|
<input type="file" id="file-input" hidden>
|
||||||
<div id="drop-target" class="filter">
|
<div id="drop-target" class="filter">
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { View } from './view.js'
|
import { View } from './view.js'
|
||||||
import { createTOCView } from './ui/tree.js'
|
import { createTOCView } from './ui/tree.js'
|
||||||
import { createMenu } from './ui/menu.js'
|
import { createMenu } from './ui/menu.js'
|
||||||
|
import { createPopover } from './ui/popover.js'
|
||||||
|
|
||||||
const { ZipReader, BlobReader, TextWriter, BlobWriter } = zip
|
const { ZipReader, BlobReader, TextWriter, BlobWriter } = zip
|
||||||
zip.configure({ useWebWorkers: false })
|
zip.configure({ useWebWorkers: false })
|
||||||
@@ -119,6 +120,30 @@ const emit = obj => {
|
|||||||
if (tocItem?.href) setCurrentHref?.(tocItem.href)
|
if (tocItem?.href) setCurrentHref?.(tocItem.href)
|
||||||
break
|
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