Published
Edited
Aug 5, 2021
Fork of Slides
1 fork
Importers
16 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
slide.md("callout")`
# Draw attention to this point
`
Insert cell
slide.html('small')`
<div style="height:40vw">Code is a code example -- edit the code below to change the display
</div>
`
Insert cell
Insert cell
Insert cell
Insert cell
slide = ({
md: wrap(md, 'slide'),
html: wrap(html, 'slide')
})
Insert cell
notes = ({
md: wrap(md, 'notes'),
html: wrap(html, 'notes')
})
Insert cell
wrap = (fn, className) => (...args) => {
if (args[0].raw) return html`<div class="${className}">${fn(...args)}</div>`;
else
return (...rest) => html`
<div class="${className} ${args
.map(s => `${className}--${s}`)
.join(' ')}">${fn(...rest)}</div>
`;
}
Insert cell
// hide li elements (so they can be shown on key events)
hide_li_elements = function(slide) {
const lis = slide.querySelectorAll('.observablehq .slide li');
lis.forEach(li => li.classList.add("hidden"));
}
Insert cell
keyBindings = {
let currentSlide = 0;
let showNotes = () => {};

function keyUp(event) {
const slides = document.querySelectorAll('.observablehq .slide');
switch (event.key) {
case 'ArrowUp':
case 'ArrowLeft':
// Check if there are any more bullets to *hide*
// If there are displayed LI elements, hide them (instead of advancing slides)
let cell = slides[currentSlide].parentNode;
let hidden_lis = cell.querySelectorAll("li:not(.hidden)");
console.log(hidden_lis);
if (hidden_lis.length !== 0) {
hidden_lis[hidden_lis.length - 1].classList.add("hidden");
} else {
currentSlide = Math.max(currentSlide - 1, 0);
slides[currentSlide].scrollIntoView();
showNotes(slides[currentSlide]);
}

break;
case 'ArrowDown':
case 'ArrowRight':
// Check if there are any more bullets to move through
// If there are hidden LI elements, show them (instead of advancing slides)
currentSlide = Math.min(currentSlide, slides.length - 1);
console.log(currentSlide, slides[currentSlide]);
let current_cell = slides[currentSlide].parentNode;
const lis = current_cell.querySelectorAll("li.hidden");
if (lis.length !== 0) {
lis[0].classList.remove("hidden");
}

// Otherwise, advance
else {
currentSlide = Math.min(currentSlide + 1, slides.length - 1);
const slide = slides[currentSlide];
hide_li_elements(slide);
slide.scrollIntoView();
showNotes(slide);
}

break;
}
}

document.removeEventListener('keyup', keyUp);
document.addEventListener('keyup', keyUp);

const button = html`<button>Notes</button>`;
button.onclick = () => {
const notes = open("about:blank", "notes", "width=300,height=200").document
.body;
showNotes = slide => {
notes.innerHTML = "";
let cell = slide.parentNode;
const siblings = Array.from(document.querySelectorAll('.observablehq'));
for (const sibling of siblings.slice(siblings.indexOf(cell))) {
if (sibling.querySelector('.notes')) {
notes.innerHTML = sibling.innerHTML;
break;
}
}
};
};

return button;
}
Insert cell
divider_color = "rgb(128, 207, 156)"
Insert cell
style = html`
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300&display=swap" rel="stylesheet">
<style>
.slide,
.notes {
padding: 1% 10%;
width: calc(100% + 28px);
box-sizing: border-box;
margin: 0 -14px;
}

.slide {
min-height: 64vw;
display: flex;
align-items: center;
}
.slide{
font-size: 3vw;
}

.slide.slide--small {
padding-bottom: 1%;
min-height: auto;
}

.slide.slide--bleed {
padding: 0;
min-height: 0;
}

.slide h1,
.slide h2,
.slide p,
.slide pre,
.slide img {
max-width: 100%;
}



.slide small {
color: gray;
}

.slide blockquote,
.slide ol,
.slide ul {
max-width: none;
}

.slide > * {
width: 100%;
}
.slide > iframe {
height: 56vw;
}

.slide ul,
.slide ol {
padding-left: 3vw;
margin-bottom: 0;
}
.slide ul li::before,
.slide ol li::before {
margin-left: -2vw;
}


.slide--intro {
background-color:black;
color:white;
font-family:"Lato", sans-serif;
}
.slide--intro h1 {
border-bottom: 1px solid ${divider_color};
width: 100%;
color:white;
margin-bottom:3px;
}

.slide--intro p {
margin-top:0px;
}

.slide--feature p {
border-top: 1px solid ${divider_color};
font-size:.8em;
position: absolute;
bottom: 0px;
width: 83%;
}
.slide--feature p code {
font-size:.8em;
}

p code, li code {color: #c30771;}

li.hidden {
opacity:0;
}

.slide--bullets {
align-items:flex-start;
}
.slide--bullets h1 {
font-family:"Lato", sans-serif;
font-size:1.75em;
border-bottom: 1px solid ${divider_color};
}

.slide--bullets ul {
list-style-position: outside;
list-style-type: none;
padding:0px;
}

.slide--callout {
background-color:${divider_color};
}

.slide--feature > span {
position:relative;
height:100%;
}
.slide--feature > span > img {
max-height:calc(100% - 210px);
border: 1px solid black;
position: absolute;
top: 43%;
transform: translate(-50%, -50%);
left:50%;
}
.slide--feature > span > p {
bottom:30px;
width:100%;
}
.slide {
height: 64vw;
}
</style>`
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more