mirror of
https://github.com/osmarks/website
synced 2025-04-29 14:13:21 +00:00
inline footnotes prototype
This commit is contained in:
parent
a9c4072283
commit
ebcee20c5b
88
src/page.js
88
src/page.js
@ -413,6 +413,37 @@ const inCollapsedDetails = el => {
|
|||||||
|
|
||||||
const footnotes = document.querySelector(".footnotes")
|
const footnotes = document.querySelector(".footnotes")
|
||||||
const sidenotes = document.querySelector(".sidenotes")
|
const sidenotes = document.querySelector(".sidenotes")
|
||||||
|
var sidenotesAtSide = () => false
|
||||||
|
|
||||||
|
let previousHighlight
|
||||||
|
const fixDetailsSummary = elt => {
|
||||||
|
if (!(elt instanceof HTMLElement) && !window.location.hash.slice(1)) return
|
||||||
|
const el = elt instanceof HTMLElement ? elt : document.getElementById(window.location.hash.slice(1))
|
||||||
|
var parent = el
|
||||||
|
if (!el) return
|
||||||
|
if (el.classList.contains("footnote-item")) {
|
||||||
|
if (previousHighlight) {
|
||||||
|
previousHighlight.classList.remove("hl1")
|
||||||
|
}
|
||||||
|
el.classList.add("hl1")
|
||||||
|
previousHighlight = el
|
||||||
|
}
|
||||||
|
if (el.classList.contains("footnote-backref")) {
|
||||||
|
// close footnote
|
||||||
|
if (previousHighlight) {
|
||||||
|
previousHighlight.classList.remove("hl1")
|
||||||
|
previousHighlight.classList.remove("hl3")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (parent.parentElement) {
|
||||||
|
if (parent.nodeName === "DETAILS") {
|
||||||
|
parent.setAttribute("open", true)
|
||||||
|
}
|
||||||
|
parent = parent.parentElement
|
||||||
|
}
|
||||||
|
if (sidenotesAtSide()) el.scrollIntoView()
|
||||||
|
}
|
||||||
|
|
||||||
if (sidenotes && footnotes) {
|
if (sidenotes && footnotes) {
|
||||||
const codeblocks = Array.from(document.querySelectorAll(".wider")).concat(Array.from(document.querySelectorAll(".content pre")))
|
const codeblocks = Array.from(document.querySelectorAll(".wider")).concat(Array.from(document.querySelectorAll(".content pre")))
|
||||||
const article = document.querySelector(".content")
|
const article = document.querySelector(".content")
|
||||||
@ -424,7 +455,7 @@ if (sidenotes && footnotes) {
|
|||||||
const sum = xs => xs.reduce((a, b) => a + b, 0)
|
const sum = xs => xs.reduce((a, b) => a + b, 0)
|
||||||
const arrayOf = (n, x) => new Array(n).fill(x)
|
const arrayOf = (n, x) => new Array(n).fill(x)
|
||||||
const BORDER = 16
|
const BORDER = 16
|
||||||
const sidenotesAtSide = () => getComputedStyle(sidenotes).paddingLeft !== "0px"
|
sidenotesAtSide = () => getComputedStyle(sidenotes).paddingLeft !== "0px"
|
||||||
let rendered = false
|
let rendered = false
|
||||||
const relayout = forceRedraw => {
|
const relayout = forceRedraw => {
|
||||||
// sidenote column width is static: no need to redo positioning on resize unless no positions applied
|
// sidenote column width is static: no need to redo positioning on resize unless no positions applied
|
||||||
@ -447,13 +478,14 @@ if (sidenotes && footnotes) {
|
|||||||
inclusions.push({ start: end - snRect.top, contents: [] })
|
inclusions.push({ start: end - snRect.top, contents: [] })
|
||||||
}
|
}
|
||||||
inclusions[inclusions.length - 1].end = Infinity
|
inclusions[inclusions.length - 1].end = Infinity
|
||||||
console.log(inclusions, exclusions)
|
|
||||||
const notes = []
|
const notes = []
|
||||||
// read off sidenotes to place
|
// read off sidenotes to place
|
||||||
for (const item of footnoteItems) {
|
for (const item of footnoteItems) {
|
||||||
const link = article.querySelector(`#${item.id.replace(/^fn/, "fnref")}`)
|
const link = article.querySelector(`#${item.id.replace(/^fn/, "fnref")}`)
|
||||||
const linkRect = link.getBoundingClientRect()
|
const linkRect = link.getBoundingClientRect()
|
||||||
item.style.position = "absolute"
|
item.style.position = "absolute"
|
||||||
|
item.style.display = "list-item"
|
||||||
|
item.style.width = null
|
||||||
item.style.left = getComputedStyle(sidenotes).paddingLeft
|
item.style.left = getComputedStyle(sidenotes).paddingLeft
|
||||||
item.style.paddingBottom = item.style.paddingTop = item.style.paddingRight = `${BORDER / 2}px`
|
item.style.paddingBottom = item.style.paddingTop = item.style.paddingRight = `${BORDER / 2}px`
|
||||||
const itemRect = item.getBoundingClientRect()
|
const itemRect = item.getBoundingClientRect()
|
||||||
@ -470,7 +502,6 @@ if (sidenotes && footnotes) {
|
|||||||
.findIndex(inc => (sum(inc.contents.map(x => x.height)) + note.height) < (inc.end - inc.start))
|
.findIndex(inc => (sum(inc.contents.map(x => x.height)) + note.height) < (inc.end - inc.start))
|
||||||
inclusions[index + next].contents.push(note)
|
inclusions[index + next].contents.push(note)
|
||||||
}
|
}
|
||||||
console.log(inclusions)
|
|
||||||
// TODO: try simple moves between regions? might be useful sometimes
|
// TODO: try simple moves between regions? might be useful sometimes
|
||||||
// place within region and apply styles
|
// place within region and apply styles
|
||||||
for (const inc of inclusions) {
|
for (const inc of inclusions) {
|
||||||
@ -525,7 +556,7 @@ if (sidenotes && footnotes) {
|
|||||||
}
|
}
|
||||||
const solutionVars = new Map(solution.variables)
|
const solutionVars = new Map(solution.variables)
|
||||||
let position = 0
|
let position = 0
|
||||||
console.log(solutionVars, model)
|
console.log("Layout solution found")
|
||||||
regionNotes.forEach((note, i) => {
|
regionNotes.forEach((note, i) => {
|
||||||
position += solutionVars.get(`gap_${i}`) || 0
|
position += solutionVars.get(`gap_${i}`) || 0
|
||||||
note.item.style.top = position + "px"
|
note.item.style.top = position + "px"
|
||||||
@ -535,8 +566,17 @@ if (sidenotes && footnotes) {
|
|||||||
}
|
}
|
||||||
rendered = true
|
rendered = true
|
||||||
} else {
|
} else {
|
||||||
|
const articleRect = article.getBoundingClientRect()
|
||||||
|
const pad = parseFloat(getComputedStyle(sidenotes).paddingLeft)
|
||||||
for (const item of sidenotes.querySelectorAll(".footnote-item")) {
|
for (const item of sidenotes.querySelectorAll(".footnote-item")) {
|
||||||
item.style.position = "static"
|
//item.style.position = "static"
|
||||||
|
const link = article.querySelector(`#${item.id.replace(/^fn/, "fnref")}`)
|
||||||
|
const linkRect = link.getBoundingClientRect()
|
||||||
|
item.style.position = "absolute"
|
||||||
|
item.style.left = (articleRect.left + pad) + "px"
|
||||||
|
item.style.width = (articleRect.right - articleRect.left - pad * 2) + "px"
|
||||||
|
item.style.top = linkRect.bottom + "px"
|
||||||
|
item.style.display = "none"
|
||||||
}
|
}
|
||||||
rendered = false
|
rendered = false
|
||||||
}
|
}
|
||||||
@ -549,6 +589,12 @@ if (sidenotes && footnotes) {
|
|||||||
link.addEventListener("mouseleave", () => {
|
link.addEventListener("mouseleave", () => {
|
||||||
item.classList.remove("hl2")
|
item.classList.remove("hl2")
|
||||||
})
|
})
|
||||||
|
item.addEventListener("mouseover", () => {
|
||||||
|
if (!sidenotesAtSide()) item.classList.add("hl3")
|
||||||
|
})
|
||||||
|
item.addEventListener("mouseleave", () => {
|
||||||
|
item.classList.remove("hl3")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,28 +611,18 @@ if (sidenotes && footnotes) {
|
|||||||
setTimeout(() => relayout(true), 0)
|
setTimeout(() => relayout(true), 0)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
document.querySelectorAll("a").forEach(x => {
|
||||||
|
const isBackref = x.classList.contains("footnote-backref")
|
||||||
let previousHighlight
|
const isRef = x.parentElement.classList.contains("footnote-ref")
|
||||||
const fixDetailsSummary = () => {
|
if (!isBackref && !isRef) return
|
||||||
if (!window.location.hash.slice(1)) return
|
x.addEventListener("click", ev => {
|
||||||
const el = document.getElementById(window.location.hash.slice(1))
|
if (!sidenotesAtSide()) {
|
||||||
var parent = el
|
ev.preventDefault()
|
||||||
if (!el) return
|
if (isRef) fixDetailsSummary(document.getElementById(x.getAttribute("href").slice(1)))
|
||||||
if (el.classList.contains("footnote-item")) {
|
else fixDetailsSummary(x)
|
||||||
if (previousHighlight) {
|
|
||||||
previousHighlight.classList.remove("hl1")
|
|
||||||
}
|
}
|
||||||
el.classList.add("hl1")
|
})
|
||||||
previousHighlight = el
|
})
|
||||||
}
|
|
||||||
while (parent.parentElement) {
|
|
||||||
if (parent.nodeName === "DETAILS") {
|
|
||||||
parent.setAttribute("open", true)
|
|
||||||
}
|
|
||||||
parent = parent.parentElement
|
|
||||||
}
|
|
||||||
el.scrollIntoView()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("hashchange", fixDetailsSummary)
|
window.addEventListener("hashchange", fixDetailsSummary)
|
||||||
|
@ -102,7 +102,7 @@ h1, h2, h3, h4, h5, h6
|
|||||||
font-family: $headers
|
font-family: $headers
|
||||||
text-align: left
|
text-align: left
|
||||||
a
|
a
|
||||||
color: inherit
|
color: inherit !important
|
||||||
text-decoration: none !important
|
text-decoration: none !important
|
||||||
|
|
||||||
summary h1, summary h2
|
summary h1, summary h2
|
||||||
@ -222,9 +222,12 @@ blockquote
|
|||||||
min-width: $sidenotes-width
|
min-width: $sidenotes-width
|
||||||
padding-left: 1.5rem
|
padding-left: 1.5rem
|
||||||
position: relative
|
position: relative
|
||||||
|
box-sizing: border-box
|
||||||
p
|
p
|
||||||
margin: 0
|
margin: 0
|
||||||
|
|
||||||
|
.footnotes-list
|
||||||
|
margin: 0
|
||||||
.footnotes-sep
|
.footnotes-sep
|
||||||
display: none
|
display: none
|
||||||
.footnotes-list
|
.footnotes-list
|
||||||
@ -236,16 +239,22 @@ blockquote
|
|||||||
width: auto
|
width: auto
|
||||||
max-width: $content-width
|
max-width: $content-width
|
||||||
padding: 0
|
padding: 0
|
||||||
|
position: static
|
||||||
margin-left: $content-margin
|
margin-left: $content-margin
|
||||||
margin-right: $content-margin
|
margin-right: $content-margin
|
||||||
.footnotes-sep
|
|
||||||
display: block
|
|
||||||
.sidenotes-container
|
.sidenotes-container
|
||||||
display: block
|
display: block
|
||||||
table
|
table
|
||||||
display: block
|
display: block
|
||||||
overflow-x: scroll
|
overflow-x: scroll
|
||||||
|
|
||||||
|
.footnote-item.hl1, .footnote-item.hl2, .footnote-item.hl3
|
||||||
|
background: hsl(0, 0%, var(--autocol-lightness))
|
||||||
|
padding: 0.5em
|
||||||
|
box-sizing: border-box
|
||||||
|
list-style-type: none
|
||||||
|
display: block !important
|
||||||
|
|
||||||
@media (min-width: calc(4 * $content-margin + $content-width + $sidenotes-width + $navbar-width))
|
@media (min-width: calc(4 * $content-margin + $content-width + $sidenotes-width + $navbar-width))
|
||||||
// fullwidth 3-pane layout
|
// fullwidth 3-pane layout
|
||||||
body
|
body
|
||||||
@ -278,7 +287,7 @@ blockquote
|
|||||||
min-width: calc(40rem - 2 * $content-margin - $navbar-width)
|
min-width: calc(40rem - 2 * $content-margin - $navbar-width)
|
||||||
|
|
||||||
$hl-border: 3px
|
$hl-border: 3px
|
||||||
.footnote-item.hl1, .footnote-item.hl2
|
.footnote-item.hl1, .footnote-item.hl2, .footnote-item.hl3
|
||||||
border-top: solid $hl-border orange
|
border-top: solid $hl-border orange
|
||||||
border-bottom: solid $hl-border orange
|
border-bottom: solid $hl-border orange
|
||||||
margin-top: -$hl-border
|
margin-top: -$hl-border
|
||||||
|
Loading…
x
Reference in New Issue
Block a user