Merge branch 'upstream-sync'

This commit is contained in:
Kathleen Fitzpatrick
2023-10-30 16:25:56 -04:00
64 changed files with 6168 additions and 10812 deletions
+31
View File
@@ -0,0 +1,31 @@
name: tests
on:
- push
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- 18
- 20
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm run build --if-present
- run: npm test
env:
CI: true
-2
View File
@@ -1,7 +1,5 @@
/test /test
/examples /examples
.github .github
.gulpfile
.sass-cache .sass-cache
gulpfile.js gulpfile.js
CONTRIBUTING.md
+6 -1
View File
@@ -5,7 +5,7 @@
* https://revealjs.com/pdf-export/ * https://revealjs.com/pdf-export/
*/ */
html.print-pdf { html.reveal-print {
* { * {
-webkit-print-color-adjust: exact; -webkit-print-color-adjust: exact;
} }
@@ -70,6 +70,10 @@ html.print-pdf {
page-break-after: always; page-break-after: always;
} }
.reveal .slides .pdf-page:last-of-type {
page-break-after: avoid;
}
.reveal .slides section { .reveal .slides section {
visibility: visible !important; visibility: visible !important;
display: block !important; display: block !important;
@@ -145,6 +149,7 @@ html.print-pdf {
display: block; display: block;
position: absolute; position: absolute;
font-size: 14px; font-size: 14px;
visibility: visible;
} }
/* This accessibility tool is not useful in PDF and breaks it visually */ /* This accessibility tool is not useful in PDF and breaks it visually */
+244 -9
View File
@@ -19,6 +19,7 @@ html.reveal-full-page {
height: 100%; height: 100%;
height: 100vh; height: 100vh;
height: calc( var(--vh, 1vh) * 100 ); height: calc( var(--vh, 1vh) * 100 );
height: 100svh;
overflow: hidden; overflow: hidden;
} }
@@ -31,6 +32,8 @@ html.reveal-full-page {
background-color: #fff; background-color: #fff;
color: #000; color: #000;
--r-controls-spacing: 12px;
} }
// Force the presentation to cover the full viewport when we // Force the presentation to cover the full viewport when we
@@ -271,13 +274,11 @@ $controlsArrowAngleActive: 36deg;
} }
.reveal .controls { .reveal .controls {
$spacing: 12px;
display: none; display: none;
position: absolute; position: absolute;
top: auto; top: auto;
bottom: $spacing; bottom: var(--r-controls-spacing);
right: $spacing; right: var(--r-controls-spacing);
left: auto; left: auto;
z-index: 11; z-index: 11;
color: #000; color: #000;
@@ -509,7 +510,9 @@ $controlsArrowAngleActive: 36deg;
// Edge aligned controls layout // Edge aligned controls layout
@media screen and (min-width: 500px) { @media screen and (min-width: 500px) {
$spacing: 0.8em; .reveal-viewport {
--r-controls-spacing: 0.8em;
}
.reveal .controls[data-controls-layout="edges"] { .reveal .controls[data-controls-layout="edges"] {
& { & {
@@ -529,24 +532,24 @@ $controlsArrowAngleActive: 36deg;
.navigate-left { .navigate-left {
top: 50%; top: 50%;
left: $spacing; left: var(--r-controls-spacing);
margin-top: -$controlArrowSize*0.5; margin-top: -$controlArrowSize*0.5;
} }
.navigate-right { .navigate-right {
top: 50%; top: 50%;
right: $spacing; right: var(--r-controls-spacing);
margin-top: -$controlArrowSize*0.5; margin-top: -$controlArrowSize*0.5;
} }
.navigate-up { .navigate-up {
top: $spacing; top: var(--r-controls-spacing);
left: 50%; left: 50%;
margin-left: -$controlArrowSize*0.5; margin-left: -$controlArrowSize*0.5;
} }
.navigate-down { .navigate-down {
bottom: $spacing - $controlArrowSpacing + 0.3em; bottom: calc(var(--r-controls-spacing) - #{$controlArrowSpacing} + 0.3em);
left: 50%; left: 50%;
margin-left: -$controlArrowSize*0.5; margin-left: -$controlArrowSize*0.5;
} }
@@ -1636,6 +1639,10 @@ $overlayHeaderPadding: 5px;
opacity: 0.4; opacity: 0.4;
} }
.reveal .hljs.has-highlights.fragment {
transition: all .2s ease;
}
.reveal .hljs:not(:first-child).fragment { .reveal .hljs:not(:first-child).fragment {
position: absolute; position: absolute;
top: 0; top: 0;
@@ -1860,6 +1867,234 @@ $notesWidthPercent: 25%;
} }
/*********************************************
* SCROLL VIEW
*********************************************/
.reveal-viewport.loading-scroll-mode {
visibility: hidden;
}
.reveal-viewport.reveal-scroll {
& {
margin: 0 auto;
overflow: auto;
overflow-x: hidden;
overflow-y: auto;
z-index: 1;
--r-scrollbar-width: 7px;
--r-scrollbar-trigger-size: 5px;
--r-controls-spacing: 8px;
}
@media screen and (max-width: 500px) {
--r-scrollbar-width: 3px;
--r-scrollbar-trigger-size: 3px;
}
.controls,
.progress,
.playback,
.backgrounds,
.slide-number,
.speaker-notes {
display: none !important;
}
.reveal {
overflow: visible;
touch-action: manipulation;
}
.slides {
position: static;
pointer-events: initial;
left: auto;
top: auto;
width: 100% !important;
margin: 0;
padding: 0;
overflow: visible;
display: block;
perspective: none;
perspective-origin: 50% 50%;
}
.scroll-page {
position: relative;
width: 100%;
height: calc(var(--page-height) + var(--page-scroll-padding));
z-index: 1;
overflow: visible;
}
.scroll-page-sticky {
position: sticky;
height: var(--page-height);
top: 0px;
}
.scroll-page-content {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.scroll-page section {
visibility: visible !important;
display: block !important;
position: absolute !important;
width: var(--slide-width) !important;
height: var(--slide-height) !important;
top: 50% !important;
left: 50% !important;
opacity: 1 !important;
transform: scale(var(--slide-scale)) translate(-50%, -50%) !important;
transform-style: flat !important;
transform-origin: 0 0 !important;
}
.slide-background {
display: block !important;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: auto !important;
visibility: visible;
opacity: 1;
touch-action: manipulation;
}
}
// Chromium
.reveal-viewport.reveal-scroll[data-scrollbar="true"]::-webkit-scrollbar,
.reveal-viewport.reveal-scroll[data-scrollbar="auto"]::-webkit-scrollbar {
display: none;
}
// Firefox
.reveal-viewport.reveal-scroll[data-scrollbar="true"],
.reveal-viewport.reveal-scroll[data-scrollbar="auto"] {
scrollbar-width: none;
}
.reveal.has-dark-background,
.reveal-viewport.has-dark-background {
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal.has-light-background,
.reveal-viewport.has-light-background {
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport.reveal-scroll .scrollbar {
position: sticky;
top: 50%;
z-index: 20;
opacity: 0;
transition: all 0.3s ease;
&.visible,
&:hover {
opacity: 1;
}
.scrollbar-inner {
position: absolute;
width: var(--r-scrollbar-width);
height: calc(var(--viewport-height) - var(--r-controls-spacing) * 2);
right: var(--r-controls-spacing);
top: 0;
transform: translateY(-50%);
border-radius: var(--r-scrollbar-width);
z-index: 10;
}
.scrollbar-playhead {
position: absolute;
width: var(--r-scrollbar-width);
height: var(--r-scrollbar-width);
top: 0;
left: 0;
border-radius: var(--r-scrollbar-width);
background-color: rgba(var(--r-overlay-element-bg-color), 1);
z-index: 11;
transition: background-color 0.2s ease;
}
.scrollbar-slide {
position: absolute;
width: 100%;
background-color: rgba(var(--r-overlay-element-bg-color), 0.2);
box-shadow: 0 0 0px 1px rgba(var(--r-overlay-element-fg-color), 0.1);
border-radius: var(--r-scrollbar-width);
transition: background-color 0.2s ease;
}
// Hit area
.scrollbar-slide:after {
content: '';
position: absolute;
width: 200%;
height: 100%;
top: 0;
left: -50%;
background: rgba( 0, 0, 0, 0 );
z-index: -1;
}
.scrollbar-slide:hover,
.scrollbar-slide.active {
background-color: rgba(var(--r-overlay-element-bg-color), 0.4);
}
.scrollbar-trigger {
position: absolute;
width: 100%;
transition: background-color 0.2s ease;
}
.scrollbar-slide.active.has-triggers {
background-color: rgba(var(--r-overlay-element-bg-color), 0.4);
z-index: 10;
}
.scrollbar-slide.active .scrollbar-trigger:after {
content: '';
position: absolute;
width: var(--r-scrollbar-trigger-size);
height: var(--r-scrollbar-trigger-size);
border-radius: 20px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(var(--r-overlay-element-bg-color), 1);
transition: transform 0.2s ease, opacity 0.2s ease;
opacity: 0.4;
}
.scrollbar-slide.active .scrollbar-trigger.active:after,
.scrollbar-slide.active .scrollbar-trigger.active ~ .scrollbar-trigger:after {
opacity: 1;
}
.scrollbar-slide.active .scrollbar-trigger ~ .scrollbar-trigger.active:after {
transform: translate(calc( var(--r-scrollbar-width) * -2), 0);
background-color: rgba(var(--r-overlay-element-bg-color), 1);
}
}
/********************************************* /*********************************************
* PRINT STYLES * PRINT STYLES
*********************************************/ *********************************************/
+3
View File
@@ -27,6 +27,9 @@ $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: rgba(79, 64, 28, 0.99); $selectionBackgroundColor: rgba(79, 64, 28, 0.99);
$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); $heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15);
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Background generator // Background generator
@mixin bodyBackground() { @mixin bodyBackground() {
@include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) ); @include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) );
-4
View File
@@ -18,10 +18,6 @@
/** /**
* Solarized colors by Ethan Schoonover * Solarized colors by Ethan Schoonover
*/ */
html * {
color-profile: sRGB;
rendering-intent: auto;
}
// Solarized colors // Solarized colors
$base03: #002b36; $base03: #002b36;
+3
View File
@@ -25,6 +25,9 @@ $linkColor: #51483D;
$linkColorHover: lighten( $linkColor, 20% ); $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: #26351C; $selectionBackgroundColor: #26351C;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
.reveal a { .reveal a {
line-height: 1.3em; line-height: 1.3em;
} }
+3
View File
@@ -31,6 +31,9 @@ $linkColor: #00008B;
$linkColorHover: lighten( $linkColor, 20% ); $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: rgba(0, 0, 0, 0.99); $selectionBackgroundColor: rgba(0, 0, 0, 0.99);
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds // Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff); @include dark-bg-text-color(#fff);
+3
View File
@@ -29,6 +29,9 @@ $linkColor: #3b759e;
$linkColorHover: lighten( $linkColor, 20% ); $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: #134674; $selectionBackgroundColor: #134674;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Fix links so they are not cut off // Fix links so they are not cut off
.reveal a { .reveal a {
line-height: 1.3em; line-height: 1.3em;
+3
View File
@@ -51,6 +51,9 @@ $linkColor: $blue;
$linkColorHover: lighten( $linkColor, 20% ); $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: $magenta; $selectionBackgroundColor: $magenta;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Background generator // Background generator
// @mixin bodyBackground() { // @mixin bodyBackground() {
// @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) ); // @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) );
+3
View File
@@ -40,6 +40,9 @@ $heading2Size: 1.6em;
$heading3Size: 1.3em; $heading3Size: 1.3em;
$heading4Size: 1.0em; $heading4Size: 1.0em;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds // Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff); @include dark-bg-text-color(#fff);
+3
View File
@@ -37,6 +37,9 @@ $heading2Size: 1.6em;
$heading3Size: 1.3em; $heading3Size: 1.3em;
$heading4Size: 1.0em; $heading4Size: 1.0em;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds // Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff); @include dark-bg-text-color(#fff);
+2
View File
@@ -25,4 +25,6 @@
--r-link-color-hover: #{$linkColorHover}; --r-link-color-hover: #{$linkColorHover};
--r-selection-background-color: #{$selectionBackgroundColor}; --r-selection-background-color: #{$selectionBackgroundColor};
--r-selection-color: #{$selectionColor}; --r-selection-color: #{$selectionColor};
--r-overlay-element-bg-color: #{$overlayElementBgColor};
--r-overlay-element-fg-color: #{$overlayElementFgColor};
} }
+5
View File
@@ -38,6 +38,11 @@ $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: #FF5E99; $selectionBackgroundColor: #FF5E99;
$selectionColor: #fff; $selectionColor: #fff;
// Colors used for UI elements that are overlaid on top of
// the presentation
$overlayElementBgColor: 240, 240, 240;
$overlayElementFgColor: 0, 0, 0;
// Generates the presentation background, can be overridden // Generates the presentation background, can be overridden
// to return a background image or gradient // to return a background image or gradient
@mixin bodyBackground() { @mixin bodyBackground() {
+2 -2
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+9 -7
View File
@@ -37,16 +37,18 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #c0a86e; --r-link-color-hover: #c0a86e;
--r-selection-background-color: rgba(79, 64, 28, 0.99); --r-selection-background-color: rgba(79, 64, 28, 0.99);
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {
background: #f7f2d3; background: rgb(247, 242, 211);
background: -moz-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); background: -moz-radial-gradient(center, circle cover, rgb(255, 255, 255) 0%, rgb(247, 242, 211) 100%);
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, white), color-stop(100%, #f7f2d3)); background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, rgb(255, 255, 255)), color-stop(100%, rgb(247, 242, 211)));
background: -webkit-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); background: -webkit-radial-gradient(center, circle cover, rgb(255, 255, 255) 0%, rgb(247, 242, 211) 100%);
background: -o-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); background: -o-radial-gradient(center, circle cover, rgb(255, 255, 255) 0%, rgb(247, 242, 211) 100%);
background: -ms-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); background: -ms-radial-gradient(center, circle cover, rgb(255, 255, 255) 0%, rgb(247, 242, 211) 100%);
background: radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); background: radial-gradient(center, circle cover, rgb(255, 255, 255) 0%, rgb(247, 242, 211) 100%);
background-color: var(--r-background-color); background-color: var(--r-background-color);
} }
+2
View File
@@ -39,6 +39,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #8dcffc; --r-link-color-hover: #8dcffc;
--r-selection-background-color: #bee4fd; --r-selection-background-color: #bee4fd;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -36,6 +36,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #8dcffc; --r-link-color-hover: #8dcffc;
--r-selection-background-color: rgba(66, 175, 250, 0.75); --r-selection-background-color: rgba(66, 175, 250, 0.75);
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -42,6 +42,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #dd5566; --r-link-color-hover: #dd5566;
--r-selection-background-color: #a23; --r-selection-background-color: #a23;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -43,6 +43,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #8BE9FD; --r-link-color-hover: #8BE9FD;
--r-selection-background-color: #44475A; --r-selection-background-color: #44475A;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {
+9 -7
View File
@@ -39,16 +39,18 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #71e9f4; --r-link-color-hover: #71e9f4;
--r-selection-background-color: #FF5E99; --r-selection-background-color: #FF5E99;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {
background: #1c1e20; background: rgb(28, 30, 32);
background: -moz-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); background: -moz-radial-gradient(center, circle cover, rgb(85, 90, 95) 0%, rgb(28, 30, 32) 100%);
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #555a5f), color-stop(100%, #1c1e20)); background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, rgb(85, 90, 95)), color-stop(100%, rgb(28, 30, 32)));
background: -webkit-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); background: -webkit-radial-gradient(center, circle cover, rgb(85, 90, 95) 0%, rgb(28, 30, 32) 100%);
background: -o-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); background: -o-radial-gradient(center, circle cover, rgb(85, 90, 95) 0%, rgb(28, 30, 32) 100%);
background: -ms-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); background: -ms-radial-gradient(center, circle cover, rgb(85, 90, 95) 0%, rgb(28, 30, 32) 100%);
background: radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); background: radial-gradient(center, circle cover, rgb(85, 90, 95) 0%, rgb(28, 30, 32) 100%);
background-color: var(--r-background-color); background-color: var(--r-background-color);
} }
+2 -5
View File
@@ -7,11 +7,6 @@
/** /**
* Solarized colors by Ethan Schoonover * Solarized colors by Ethan Schoonover
*/ */
html * {
color-profile: sRGB;
rendering-intent: auto;
}
section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 {
color: #222; color: #222;
} }
@@ -44,6 +39,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #78b9e6; --r-link-color-hover: #78b9e6;
--r-selection-background-color: #d33682; --r-selection-background-color: #d33682;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -37,6 +37,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #f3d7ac; --r-link-color-hover: #f3d7ac;
--r-selection-background-color: #e7ad52; --r-selection-background-color: #e7ad52;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -40,6 +40,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #8b7c69; --r-link-color-hover: #8b7c69;
--r-selection-background-color: #26351C; --r-selection-background-color: #26351C;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -39,6 +39,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #0000f1; --r-link-color-hover: #0000f1;
--r-selection-background-color: rgba(0, 0, 0, 0.99); --r-selection-background-color: rgba(0, 0, 0, 0.99);
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -41,6 +41,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #74a7cb; --r-link-color-hover: #74a7cb;
--r-selection-background-color: #134674; --r-selection-background-color: #134674;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -40,6 +40,8 @@ html * {
--r-link-color-hover: #78b9e6; --r-link-color-hover: #78b9e6;
--r-selection-background-color: #d33682; --r-selection-background-color: #d33682;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -39,6 +39,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #6ca0e8; --r-link-color-hover: #6ca0e8;
--r-selection-background-color: #98bdef; --r-selection-background-color: #98bdef;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {
+2
View File
@@ -36,6 +36,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #6ca0e8; --r-link-color-hover: #6ca0e8;
--r-selection-background-color: #98bdef; --r-selection-background-color: #98bdef;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {
+526
View File
@@ -0,0 +1,526 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js - 500 slides</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="../dist/reveal.css">
<link rel="stylesheet" href="../dist/theme/black.css">
</head>
<body>
<div class="reveal">
<div class="slides">
<section><h1>1</h1></section>
<section><h1>2</h1></section>
<section><h1>3</h1></section>
<section><h1>4</h1></section>
<section><h1>5</h1></section>
<section><h1>6</h1></section>
<section><h1>7</h1></section>
<section><h1>8</h1></section>
<section><h1>9</h1></section>
<section><h1>10</h1></section>
<section><h1>11</h1></section>
<section><h1>12</h1></section>
<section><h1>13</h1></section>
<section><h1>14</h1></section>
<section><h1>15</h1></section>
<section><h1>16</h1></section>
<section><h1>17</h1></section>
<section><h1>18</h1></section>
<section><h1>19</h1></section>
<section><h1>20</h1></section>
<section><h1>21</h1></section>
<section><h1>22</h1></section>
<section><h1>23</h1></section>
<section><h1>24</h1></section>
<section><h1>25</h1></section>
<section><h1>26</h1></section>
<section><h1>27</h1></section>
<section><h1>28</h1></section>
<section><h1>29</h1></section>
<section><h1>30</h1></section>
<section><h1>31</h1></section>
<section><h1>32</h1></section>
<section><h1>33</h1></section>
<section><h1>34</h1></section>
<section><h1>35</h1></section>
<section><h1>36</h1></section>
<section><h1>37</h1></section>
<section><h1>38</h1></section>
<section><h1>39</h1></section>
<section><h1>40</h1></section>
<section><h1>41</h1></section>
<section><h1>42</h1></section>
<section><h1>43</h1></section>
<section><h1>44</h1></section>
<section><h1>45</h1></section>
<section><h1>46</h1></section>
<section><h1>47</h1></section>
<section><h1>48</h1></section>
<section><h1>49</h1></section>
<section><h1>50</h1></section>
<section><h1>51</h1></section>
<section><h1>52</h1></section>
<section><h1>53</h1></section>
<section><h1>54</h1></section>
<section><h1>55</h1></section>
<section><h1>56</h1></section>
<section><h1>57</h1></section>
<section><h1>58</h1></section>
<section><h1>59</h1></section>
<section><h1>60</h1></section>
<section><h1>61</h1></section>
<section><h1>62</h1></section>
<section><h1>63</h1></section>
<section><h1>64</h1></section>
<section><h1>65</h1></section>
<section><h1>66</h1></section>
<section><h1>67</h1></section>
<section><h1>68</h1></section>
<section><h1>69</h1></section>
<section><h1>70</h1></section>
<section><h1>71</h1></section>
<section><h1>72</h1></section>
<section><h1>73</h1></section>
<section><h1>74</h1></section>
<section><h1>75</h1></section>
<section><h1>76</h1></section>
<section><h1>77</h1></section>
<section><h1>78</h1></section>
<section><h1>79</h1></section>
<section><h1>80</h1></section>
<section><h1>81</h1></section>
<section><h1>82</h1></section>
<section><h1>83</h1></section>
<section><h1>84</h1></section>
<section><h1>85</h1></section>
<section><h1>86</h1></section>
<section><h1>87</h1></section>
<section><h1>88</h1></section>
<section><h1>89</h1></section>
<section><h1>90</h1></section>
<section><h1>91</h1></section>
<section><h1>92</h1></section>
<section><h1>93</h1></section>
<section><h1>94</h1></section>
<section><h1>95</h1></section>
<section><h1>96</h1></section>
<section><h1>97</h1></section>
<section><h1>98</h1></section>
<section><h1>99</h1></section>
<section><h1>100</h1></section>
<section><h1>101</h1></section>
<section><h1>102</h1></section>
<section><h1>103</h1></section>
<section><h1>104</h1></section>
<section><h1>105</h1></section>
<section><h1>106</h1></section>
<section><h1>107</h1></section>
<section><h1>108</h1></section>
<section><h1>109</h1></section>
<section><h1>110</h1></section>
<section><h1>111</h1></section>
<section><h1>112</h1></section>
<section><h1>113</h1></section>
<section><h1>114</h1></section>
<section><h1>115</h1></section>
<section><h1>116</h1></section>
<section><h1>117</h1></section>
<section><h1>118</h1></section>
<section><h1>119</h1></section>
<section><h1>120</h1></section>
<section><h1>121</h1></section>
<section><h1>122</h1></section>
<section><h1>123</h1></section>
<section><h1>124</h1></section>
<section><h1>125</h1></section>
<section><h1>126</h1></section>
<section><h1>127</h1></section>
<section><h1>128</h1></section>
<section><h1>129</h1></section>
<section><h1>130</h1></section>
<section><h1>131</h1></section>
<section><h1>132</h1></section>
<section><h1>133</h1></section>
<section><h1>134</h1></section>
<section><h1>135</h1></section>
<section><h1>136</h1></section>
<section><h1>137</h1></section>
<section><h1>138</h1></section>
<section><h1>139</h1></section>
<section><h1>140</h1></section>
<section><h1>141</h1></section>
<section><h1>142</h1></section>
<section><h1>143</h1></section>
<section><h1>144</h1></section>
<section><h1>145</h1></section>
<section><h1>146</h1></section>
<section><h1>147</h1></section>
<section><h1>148</h1></section>
<section><h1>149</h1></section>
<section><h1>150</h1></section>
<section><h1>151</h1></section>
<section><h1>152</h1></section>
<section><h1>153</h1></section>
<section><h1>154</h1></section>
<section><h1>155</h1></section>
<section><h1>156</h1></section>
<section><h1>157</h1></section>
<section><h1>158</h1></section>
<section><h1>159</h1></section>
<section><h1>160</h1></section>
<section><h1>161</h1></section>
<section><h1>162</h1></section>
<section><h1>163</h1></section>
<section><h1>164</h1></section>
<section><h1>165</h1></section>
<section><h1>166</h1></section>
<section><h1>167</h1></section>
<section><h1>168</h1></section>
<section><h1>169</h1></section>
<section><h1>170</h1></section>
<section><h1>171</h1></section>
<section><h1>172</h1></section>
<section><h1>173</h1></section>
<section><h1>174</h1></section>
<section><h1>175</h1></section>
<section><h1>176</h1></section>
<section><h1>177</h1></section>
<section><h1>178</h1></section>
<section><h1>179</h1></section>
<section><h1>180</h1></section>
<section><h1>181</h1></section>
<section><h1>182</h1></section>
<section><h1>183</h1></section>
<section><h1>184</h1></section>
<section><h1>185</h1></section>
<section><h1>186</h1></section>
<section><h1>187</h1></section>
<section><h1>188</h1></section>
<section><h1>189</h1></section>
<section><h1>190</h1></section>
<section><h1>191</h1></section>
<section><h1>192</h1></section>
<section><h1>193</h1></section>
<section><h1>194</h1></section>
<section><h1>195</h1></section>
<section><h1>196</h1></section>
<section><h1>197</h1></section>
<section><h1>198</h1></section>
<section><h1>199</h1></section>
<section><h1>200</h1></section>
<section><h1>201</h1></section>
<section><h1>202</h1></section>
<section><h1>203</h1></section>
<section><h1>204</h1></section>
<section><h1>205</h1></section>
<section><h1>206</h1></section>
<section><h1>207</h1></section>
<section><h1>208</h1></section>
<section><h1>209</h1></section>
<section><h1>210</h1></section>
<section><h1>211</h1></section>
<section><h1>212</h1></section>
<section><h1>213</h1></section>
<section><h1>214</h1></section>
<section><h1>215</h1></section>
<section><h1>216</h1></section>
<section><h1>217</h1></section>
<section><h1>218</h1></section>
<section><h1>219</h1></section>
<section><h1>220</h1></section>
<section><h1>221</h1></section>
<section><h1>222</h1></section>
<section><h1>223</h1></section>
<section><h1>224</h1></section>
<section><h1>225</h1></section>
<section><h1>226</h1></section>
<section><h1>227</h1></section>
<section><h1>228</h1></section>
<section><h1>229</h1></section>
<section><h1>230</h1></section>
<section><h1>231</h1></section>
<section><h1>232</h1></section>
<section><h1>233</h1></section>
<section><h1>234</h1></section>
<section><h1>235</h1></section>
<section><h1>236</h1></section>
<section><h1>237</h1></section>
<section><h1>238</h1></section>
<section><h1>239</h1></section>
<section><h1>240</h1></section>
<section><h1>241</h1></section>
<section><h1>242</h1></section>
<section><h1>243</h1></section>
<section><h1>244</h1></section>
<section><h1>245</h1></section>
<section><h1>246</h1></section>
<section><h1>247</h1></section>
<section><h1>248</h1></section>
<section><h1>249</h1></section>
<section><h1>250</h1></section>
<section><h1>251</h1></section>
<section><h1>252</h1></section>
<section><h1>253</h1></section>
<section><h1>254</h1></section>
<section><h1>255</h1></section>
<section><h1>256</h1></section>
<section><h1>257</h1></section>
<section><h1>258</h1></section>
<section><h1>259</h1></section>
<section><h1>260</h1></section>
<section><h1>261</h1></section>
<section><h1>262</h1></section>
<section><h1>263</h1></section>
<section><h1>264</h1></section>
<section><h1>265</h1></section>
<section><h1>266</h1></section>
<section><h1>267</h1></section>
<section><h1>268</h1></section>
<section><h1>269</h1></section>
<section><h1>270</h1></section>
<section><h1>271</h1></section>
<section><h1>272</h1></section>
<section><h1>273</h1></section>
<section><h1>274</h1></section>
<section><h1>275</h1></section>
<section><h1>276</h1></section>
<section><h1>277</h1></section>
<section><h1>278</h1></section>
<section><h1>279</h1></section>
<section><h1>280</h1></section>
<section><h1>281</h1></section>
<section><h1>282</h1></section>
<section><h1>283</h1></section>
<section><h1>284</h1></section>
<section><h1>285</h1></section>
<section><h1>286</h1></section>
<section><h1>287</h1></section>
<section><h1>288</h1></section>
<section><h1>289</h1></section>
<section><h1>290</h1></section>
<section><h1>291</h1></section>
<section><h1>292</h1></section>
<section><h1>293</h1></section>
<section><h1>294</h1></section>
<section><h1>295</h1></section>
<section><h1>296</h1></section>
<section><h1>297</h1></section>
<section><h1>298</h1></section>
<section><h1>299</h1></section>
<section><h1>300</h1></section>
<section><h1>301</h1></section>
<section><h1>302</h1></section>
<section><h1>303</h1></section>
<section><h1>304</h1></section>
<section><h1>305</h1></section>
<section><h1>306</h1></section>
<section><h1>307</h1></section>
<section><h1>308</h1></section>
<section><h1>309</h1></section>
<section><h1>310</h1></section>
<section><h1>311</h1></section>
<section><h1>312</h1></section>
<section><h1>313</h1></section>
<section><h1>314</h1></section>
<section><h1>315</h1></section>
<section><h1>316</h1></section>
<section><h1>317</h1></section>
<section><h1>318</h1></section>
<section><h1>319</h1></section>
<section><h1>320</h1></section>
<section><h1>321</h1></section>
<section><h1>322</h1></section>
<section><h1>323</h1></section>
<section><h1>324</h1></section>
<section><h1>325</h1></section>
<section><h1>326</h1></section>
<section><h1>327</h1></section>
<section><h1>328</h1></section>
<section><h1>329</h1></section>
<section><h1>330</h1></section>
<section><h1>331</h1></section>
<section><h1>332</h1></section>
<section><h1>333</h1></section>
<section><h1>334</h1></section>
<section><h1>335</h1></section>
<section><h1>336</h1></section>
<section><h1>337</h1></section>
<section><h1>338</h1></section>
<section><h1>339</h1></section>
<section><h1>340</h1></section>
<section><h1>341</h1></section>
<section><h1>342</h1></section>
<section><h1>343</h1></section>
<section><h1>344</h1></section>
<section><h1>345</h1></section>
<section><h1>346</h1></section>
<section><h1>347</h1></section>
<section><h1>348</h1></section>
<section><h1>349</h1></section>
<section><h1>350</h1></section>
<section><h1>351</h1></section>
<section><h1>352</h1></section>
<section><h1>353</h1></section>
<section><h1>354</h1></section>
<section><h1>355</h1></section>
<section><h1>356</h1></section>
<section><h1>357</h1></section>
<section><h1>358</h1></section>
<section><h1>359</h1></section>
<section><h1>360</h1></section>
<section><h1>361</h1></section>
<section><h1>362</h1></section>
<section><h1>363</h1></section>
<section><h1>364</h1></section>
<section><h1>365</h1></section>
<section><h1>366</h1></section>
<section><h1>367</h1></section>
<section><h1>368</h1></section>
<section><h1>369</h1></section>
<section><h1>370</h1></section>
<section><h1>371</h1></section>
<section><h1>372</h1></section>
<section><h1>373</h1></section>
<section><h1>374</h1></section>
<section><h1>375</h1></section>
<section><h1>376</h1></section>
<section><h1>377</h1></section>
<section><h1>378</h1></section>
<section><h1>379</h1></section>
<section><h1>380</h1></section>
<section><h1>381</h1></section>
<section><h1>382</h1></section>
<section><h1>383</h1></section>
<section><h1>384</h1></section>
<section><h1>385</h1></section>
<section><h1>386</h1></section>
<section><h1>387</h1></section>
<section><h1>388</h1></section>
<section><h1>389</h1></section>
<section><h1>390</h1></section>
<section><h1>391</h1></section>
<section><h1>392</h1></section>
<section><h1>393</h1></section>
<section><h1>394</h1></section>
<section><h1>395</h1></section>
<section><h1>396</h1></section>
<section><h1>397</h1></section>
<section><h1>398</h1></section>
<section><h1>399</h1></section>
<section><h1>400</h1></section>
<section><h1>401</h1></section>
<section><h1>402</h1></section>
<section><h1>403</h1></section>
<section><h1>404</h1></section>
<section><h1>405</h1></section>
<section><h1>406</h1></section>
<section><h1>407</h1></section>
<section><h1>408</h1></section>
<section><h1>409</h1></section>
<section><h1>410</h1></section>
<section><h1>411</h1></section>
<section><h1>412</h1></section>
<section><h1>413</h1></section>
<section><h1>414</h1></section>
<section><h1>415</h1></section>
<section><h1>416</h1></section>
<section><h1>417</h1></section>
<section><h1>418</h1></section>
<section><h1>419</h1></section>
<section><h1>420</h1></section>
<section><h1>421</h1></section>
<section><h1>422</h1></section>
<section><h1>423</h1></section>
<section><h1>424</h1></section>
<section><h1>425</h1></section>
<section><h1>426</h1></section>
<section><h1>427</h1></section>
<section><h1>428</h1></section>
<section><h1>429</h1></section>
<section><h1>430</h1></section>
<section><h1>431</h1></section>
<section><h1>432</h1></section>
<section><h1>433</h1></section>
<section><h1>434</h1></section>
<section><h1>435</h1></section>
<section><h1>436</h1></section>
<section><h1>437</h1></section>
<section><h1>438</h1></section>
<section><h1>439</h1></section>
<section><h1>440</h1></section>
<section><h1>441</h1></section>
<section><h1>442</h1></section>
<section><h1>443</h1></section>
<section><h1>444</h1></section>
<section><h1>445</h1></section>
<section><h1>446</h1></section>
<section><h1>447</h1></section>
<section><h1>448</h1></section>
<section><h1>449</h1></section>
<section><h1>450</h1></section>
<section><h1>451</h1></section>
<section><h1>452</h1></section>
<section><h1>453</h1></section>
<section><h1>454</h1></section>
<section><h1>455</h1></section>
<section><h1>456</h1></section>
<section><h1>457</h1></section>
<section><h1>458</h1></section>
<section><h1>459</h1></section>
<section><h1>460</h1></section>
<section><h1>461</h1></section>
<section><h1>462</h1></section>
<section><h1>463</h1></section>
<section><h1>464</h1></section>
<section><h1>465</h1></section>
<section><h1>466</h1></section>
<section><h1>467</h1></section>
<section><h1>468</h1></section>
<section><h1>469</h1></section>
<section><h1>470</h1></section>
<section><h1>471</h1></section>
<section><h1>472</h1></section>
<section><h1>473</h1></section>
<section><h1>474</h1></section>
<section><h1>475</h1></section>
<section><h1>476</h1></section>
<section><h1>477</h1></section>
<section><h1>478</h1></section>
<section><h1>479</h1></section>
<section><h1>480</h1></section>
<section><h1>481</h1></section>
<section><h1>482</h1></section>
<section><h1>483</h1></section>
<section><h1>484</h1></section>
<section><h1>485</h1></section>
<section><h1>486</h1></section>
<section><h1>487</h1></section>
<section><h1>488</h1></section>
<section><h1>489</h1></section>
<section><h1>490</h1></section>
<section><h1>491</h1></section>
<section><h1>492</h1></section>
<section><h1>493</h1></section>
<section><h1>494</h1></section>
<section><h1>495</h1></section>
<section><h1>496</h1></section>
<section><h1>497</h1></section>
<section><h1>498</h1></section>
<section><h1>499</h1></section>
</div>
</div>
<script src="../dist/reveal.js"></script>
<script>
Reveal.initialize({
transition: 'linear'
});
</script>
</body>
</html>
+118
View File
@@ -0,0 +1,118 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js - Scroll View</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="../dist/reset.css">
<link rel="stylesheet" href="../dist/reveal.css">
<link rel="stylesheet" href="../dist/theme/black.css" id="theme">
<link rel="stylesheet" href="../plugin/highlight/monokai.css">
</head>
<body>
<div class="reveal">
<div class="slides">
<section><h1>Scroll View</h1></section>
<section data-background="indigo">
<h2>Scroll triggered fragments</h2>
<ul>
<li class="fragment fade-left">Step one</li>
<li class="fragment fade-left">Step two</li>
<li class="fragment fade-left">Step three</li>
</ul>
</section>
<section data-background-color="#fff"><h2>Scrollbar inverts<br>based on slide bg</h2></section>
<section data-auto-animate data-auto-animate-easing="cubic-bezier(0.770, 0.000, 0.175, 1.000)">
<h2>Auto-Animate</h2>
<p>Scroll triggered auto-animations 😍</p>
<div class="r-hstack justify-center">
<div data-id="box1" style="background: #999; width: 50px; height: 50px; margin: 10px; border-radius: 5px;"></div>
<div data-id="box2" style="background: #999; width: 50px; height: 50px; margin: 10px; border-radius: 5px;"></div>
<div data-id="box3" style="background: #999; width: 50px; height: 50px; margin: 10px; border-radius: 5px;"></div>
</div>
</section>
<section data-auto-animate data-auto-animate-easing="cubic-bezier(0.770, 0.000, 0.175, 1.000)">
<div class="r-hstack justify-center">
<div data-id="box1" data-auto-animate-delay="0" style="background: cyan; width: 150px; height: 100px; margin: 10px;"></div>
<div data-id="box2" data-auto-animate-delay="0.1" style="background: magenta; width: 150px; height: 100px; margin: 10px;"></div>
<div data-id="box3" data-auto-animate-delay="0.2" style="background: yellow; width: 150px; height: 100px; margin: 10px;"></div>
</div>
<h2 style="margin-top: 20px;">Auto-Animate</h2>
</section>
<section data-auto-animate data-auto-animate-easing="cubic-bezier(0.770, 0.000, 0.175, 1.000)">
<div class="r-stack">
<div data-id="box1" style="background: cyan; width: 300px; height: 300px; border-radius: 200px;"></div>
<div data-id="box2" style="background: magenta; width: 200px; height: 200px; border-radius: 200px;"></div>
<div data-id="box3" style="background: yellow; width: 100px; height: 100px; border-radius: 200px;"></div>
</div>
<h2 style="margin-top: 20px;">Auto-Animate</h2>
</section>
<section data-background-gradient="linear-gradient(to bottom, #283b95, #17b2c3)" id="gradient-bg">
<h2 data-id="code-title">Code highlights,<br />meet scroll triggers</h2>
<pre data-id="code-animation"><code class="hljs javascript" data-trim data-line-numbers="|4,8-11|17|22-24"><script type="text/template">
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
function SecondExample() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
</script></code></pre>
</section>
<section class="stack">
<section data-background="https://static.slid.es/reveal/image-placeholder.png" id="image-bg">
<h2>Image Backgrounds</h2>
</section>
<section data-background-video-muted data-background-video="https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.mp4,https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.webm">
<h2>Video background</h2>
</section>
</section>
<section><h2>The end</h2></section>
</div>
</div>
<script src="../dist/reveal.js"></script>
<script src="../plugin/notes/notes.js"></script>
<script src="../plugin/markdown/markdown.js"></script>
<script src="../plugin/highlight/highlight.js"></script>
<script>
Reveal.initialize({
view: 'scroll',
hash: true,
plugins: [ RevealMarkdown, RevealHighlight, RevealNotes ]
});
</script>
</body>
</html>
+1 -3
View File
@@ -1,13 +1,11 @@
const pkg = require('./package.json') const pkg = require('./package.json')
const path = require('path')
const glob = require('glob') const glob = require('glob')
const yargs = require('yargs') const yargs = require('yargs')
const colors = require('colors')
const through = require('through2'); const through = require('through2');
const qunit = require('node-qunit-puppeteer') const qunit = require('node-qunit-puppeteer')
const {rollup} = require('rollup') const {rollup} = require('rollup')
const {terser} = require('rollup-plugin-terser') const terser = require('@rollup/plugin-terser')
const babel = require('@rollup/plugin-babel').default const babel = require('@rollup/plugin-babel').default
const commonjs = require('@rollup/plugin-commonjs') const commonjs = require('@rollup/plugin-commonjs')
const resolve = require('@rollup/plugin-node-resolve').default const resolve = require('@rollup/plugin-node-resolve').default
+31 -1
View File
@@ -256,6 +256,36 @@ export default {
parallaxBackgroundHorizontal: null, parallaxBackgroundHorizontal: null,
parallaxBackgroundVertical: null, parallaxBackgroundVertical: null,
// Can be used to initialize reveal.js in one of the following views:
// - print: Render the presentation so that it can be printed to PDF
// - scroll: Show the presentation as a tall scrollable page with scroll
// triggered animations
view: null,
// Adjusts the height of each slide in the scroll view.
// - full: Each slide is as tall as the viewport
// - compact: Slides are as small as possible, allowing multiple slides
// to be visible in parallel on tall devices
scrollLayout: 'full',
// Control how scroll snapping works in the scroll view.
// - false: No snapping, scrolling is continuous
// - proximity: Snap when close to a slide
// - mandatory: Always snap to the closest slide
//
// Only applies to presentations in scroll view.
scrollSnap: 'mandatory',
// Enables and configure the scroll view progress bar.
// - 'auto': Show the scrollbar while scrolling, hide while idle
// - true: Always show the scrollbar
// - false: Never show the scrollbar
scrollProgress: 'auto',
// Automatically activate the scroll view when we the viewport falls
// below the given width.
scrollActivationWidth: 435,
// The maximum number of pages a single slide can expand onto when printing // The maximum number of pages a single slide can expand onto when printing
// to PDF, unlimited by default // to PDF, unlimited by default
pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY, pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY,
@@ -287,7 +317,7 @@ export default {
// Time before the cursor is hidden (in ms) // Time before the cursor is hidden (in ms)
hideCursorTime: 5000, hideCursorTime: 5000,
// Should we automatmically sort and set indices for fragments // Should we automatically sort and set indices for fragments
// at each sync? (See Reveal.sync) // at each sync? (See Reveal.sync)
sortFragmentsOnSync: true, sortFragmentsOnSync: true,
+42 -11
View File
@@ -190,10 +190,30 @@ export default class Backgrounds {
if( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition; if( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition;
if( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity; if( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity;
const contrastClass = this.getContrastClass( slide );
if( typeof contrastClass === 'string' ) {
slide.classList.add( contrastClass );
}
}
/**
* Returns a class name that can be applied to a slide to indicate
* if it has a light or dark background.
*
* @param {*} slide
*
* @returns {string|null}
*/
getContrastClass( slide ) {
const element = slide.slideBackgroundElement;
// If this slide has a background color, we add a class that // If this slide has a background color, we add a class that
// signals if it is light or dark. If the slide has no background // signals if it is light or dark. If the slide has no background
// color, no class will be added // color, no class will be added
let contrastColor = data.backgroundColor; let contrastColor = slide.getAttribute( 'data-background-color' );
// If no bg color was found, or it cannot be converted by colorToRgb, check the computed background // If no bg color was found, or it cannot be converted by colorToRgb, check the computed background
if( !contrastColor || !colorToRgb( contrastColor ) ) { if( !contrastColor || !colorToRgb( contrastColor ) ) {
@@ -211,14 +231,32 @@ export default class Backgrounds {
// an element with no background // an element with no background
if( rgb && rgb.a !== 0 ) { if( rgb && rgb.a !== 0 ) {
if( colorBrightness( contrastColor ) < 128 ) { if( colorBrightness( contrastColor ) < 128 ) {
slide.classList.add( 'has-dark-background' ); return 'has-dark-background';
} }
else { else {
slide.classList.add( 'has-light-background' ); return 'has-light-background';
} }
} }
} }
return null;
}
/**
* Bubble the 'has-light-background'/'has-dark-background' classes.
*/
bubbleSlideContrastClassToElement( slide, target ) {
[ 'has-light-background', 'has-dark-background' ].forEach( classToBubble => {
if( slide.classList.contains( classToBubble ) ) {
target.classList.add( classToBubble );
}
else {
target.classList.remove( classToBubble );
}
}, this );
} }
/** /**
@@ -322,14 +360,7 @@ export default class Backgrounds {
// If there's a background brightness flag for this slide, // If there's a background brightness flag for this slide,
// bubble it to the .reveal container // bubble it to the .reveal container
if( currentSlide ) { if( currentSlide ) {
[ 'has-light-background', 'has-dark-background' ].forEach( classToBubble => { this.bubbleSlideContrastClassToElement( currentSlide, this.Reveal.getRevealElement() );
if( currentSlide.classList.contains( classToBubble ) ) {
this.Reveal.getRevealElement().classList.add( classToBubble );
}
else {
this.Reveal.getRevealElement().classList.remove( classToBubble );
}
}, this );
} }
// Allow the first background to apply without transition // Allow the first background to apply without transition
+5 -6
View File
@@ -174,24 +174,23 @@ export default class Fragments {
* *
* @return {{shown: array, hidden: array}} * @return {{shown: array, hidden: array}}
*/ */
update( index, fragments ) { update( index, fragments, slide = this.Reveal.getCurrentSlide() ) {
let changedFragments = { let changedFragments = {
shown: [], shown: [],
hidden: [] hidden: []
}; };
let currentSlide = this.Reveal.getCurrentSlide(); if( slide && this.Reveal.getConfig().fragments ) {
if( currentSlide && this.Reveal.getConfig().fragments ) {
fragments = fragments || this.sort( currentSlide.querySelectorAll( '.fragment' ) ); fragments = fragments || this.sort( slide.querySelectorAll( '.fragment' ) );
if( fragments.length ) { if( fragments.length ) {
let maxIndex = 0; let maxIndex = 0;
if( typeof index !== 'number' ) { if( typeof index !== 'number' ) {
let currentFragment = this.sort( currentSlide.querySelectorAll( '.fragment.visible' ) ).pop(); let currentFragment = this.sort( slide.querySelectorAll( '.fragment.visible' ) ).pop();
if( currentFragment ) { if( currentFragment ) {
index = parseInt( currentFragment.getAttribute( 'data-fragment-index' ) || 0, 10 ); index = parseInt( currentFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );
} }
@@ -252,7 +251,7 @@ export default class Fragments {
// the current fragment index. // the current fragment index.
index = typeof index === 'number' ? index : -1; index = typeof index === 'number' ? index : -1;
index = Math.max( Math.min( index, maxIndex ), -1 ); index = Math.max( Math.min( index, maxIndex ), -1 );
currentSlide.setAttribute( 'data-fragment', index ); slide.setAttribute( 'data-fragment', index );
} }
+9 -22
View File
@@ -17,7 +17,6 @@ export default class Keyboard {
this.bindings = {}; this.bindings = {};
this.onDocumentKeyDown = this.onDocumentKeyDown.bind( this ); this.onDocumentKeyDown = this.onDocumentKeyDown.bind( this );
this.onDocumentKeyPress = this.onDocumentKeyPress.bind( this );
} }
@@ -54,7 +53,6 @@ export default class Keyboard {
bind() { bind() {
document.addEventListener( 'keydown', this.onDocumentKeyDown, false ); document.addEventListener( 'keydown', this.onDocumentKeyDown, false );
document.addEventListener( 'keypress', this.onDocumentKeyPress, false );
} }
@@ -64,7 +62,6 @@ export default class Keyboard {
unbind() { unbind() {
document.removeEventListener( 'keydown', this.onDocumentKeyDown, false ); document.removeEventListener( 'keydown', this.onDocumentKeyDown, false );
document.removeEventListener( 'keypress', this.onDocumentKeyPress, false );
} }
@@ -135,20 +132,6 @@ export default class Keyboard {
} }
/**
* Handler for the document level 'keypress' event.
*
* @param {object} event
*/
onDocumentKeyPress( event ) {
// Check if the pressed key is question mark
if( event.shiftKey && event.charCode === 63 ) {
this.Reveal.toggleHelp();
}
}
/** /**
* Handler for the document level 'keydown' event. * Handler for the document level 'keydown' event.
* *
@@ -184,10 +167,10 @@ export default class Keyboard {
let activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className); let activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className);
// Whitelist certain modifiers for slide navigation shortcuts // Whitelist certain modifiers for slide navigation shortcuts
let isNavigationKey = [32, 37, 38, 39, 40, 78, 80].indexOf( event.keyCode ) !== -1; let keyCodeUsesModifier = [32, 37, 38, 39, 40, 78, 80, 191].indexOf( event.keyCode ) !== -1;
// Prevent all other events when a modifier is pressed // Prevent all other events when a modifier is pressed
let unusedModifier = !( isNavigationKey && event.shiftKey || event.altKey ) && let unusedModifier = !( keyCodeUsesModifier && event.shiftKey || event.altKey ) &&
( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ); ( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey );
// Disregard the event if there's a focused element or a // Disregard the event if there's a focused element or a
@@ -351,7 +334,7 @@ export default class Keyboard {
} }
} }
// TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS "BLACK SCREEN" BUTTON // TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS "BLACK SCREEN" BUTTON
else if( keyCode === 58 || keyCode === 59 || keyCode === 66 || keyCode === 86 || keyCode === 190 || keyCode === 191 ) { else if( [58, 59, 66, 86, 190].includes( keyCode ) || ( keyCode === 191 && !event.shiftKey ) ) {
this.Reveal.togglePause(); this.Reveal.togglePause();
} }
// F // F
@@ -360,16 +343,20 @@ export default class Keyboard {
} }
// A // A
else if( keyCode === 65 ) { else if( keyCode === 65 ) {
if ( config.autoSlideStoppable ) { if( config.autoSlideStoppable ) {
this.Reveal.toggleAutoSlide( autoSlideWasPaused ); this.Reveal.toggleAutoSlide( autoSlideWasPaused );
} }
} }
// G // G
else if( keyCode === 71 ) { else if( keyCode === 71 ) {
if ( config.jumpToSlide ) { if( config.jumpToSlide ) {
this.Reveal.toggleJumpToSlide(); this.Reveal.toggleJumpToSlide();
} }
} }
// ?
else if( keyCode === 191 && event.shiftKey ) {
this.Reveal.toggleHelp();
}
else { else {
triggered = false; triggered = false;
} }
+1 -1
View File
@@ -64,7 +64,7 @@ export default class Location {
try { try {
slide = document slide = document
.getElementById( decodeURIComponent( name ) ) .getElementById( decodeURIComponent( name ) )
.closest('.slides>section, .slides>section>section'); .closest('.slides section');
} }
catch ( error ) { } catch ( error ) { }
+10 -4
View File
@@ -38,10 +38,12 @@ export default class Notes {
*/ */
update() { update() {
if( this.Reveal.getConfig().showNotes && this.element && this.Reveal.getCurrentSlide() && !this.Reveal.print.isPrintingPDF() ) { if( this.Reveal.getConfig().showNotes &&
this.element && this.Reveal.getCurrentSlide() &&
!this.Reveal.isScrollView() &&
!this.Reveal.isPrintView()
) {
this.element.innerHTML = this.getSlideNotes() || '<span class="notes-placeholder">No notes on this slide.</span>'; this.element.innerHTML = this.getSlideNotes() || '<span class="notes-placeholder">No notes on this slide.</span>';
} }
} }
@@ -54,7 +56,11 @@ export default class Notes {
*/ */
updateVisibility() { updateVisibility() {
if( this.Reveal.getConfig().showNotes && this.hasNotes() && !this.Reveal.print.isPrintingPDF() ) { if( this.Reveal.getConfig().showNotes &&
this.hasNotes() &&
!this.Reveal.isScrollView() &&
!this.Reveal.isPrintView()
) {
this.Reveal.getRevealElement().classList.add( 'show-notes' ); this.Reveal.getRevealElement().classList.add( 'show-notes' );
} }
else { else {
+1 -1
View File
@@ -24,7 +24,7 @@ export default class Overview {
activate() { activate() {
// Only proceed if enabled in config // Only proceed if enabled in config
if( this.Reveal.getConfig().overview && !this.isActive() ) { if( this.Reveal.getConfig().overview && !this.Reveal.isScrollView() && !this.isActive() ) {
this.active = true; this.active = true;
+4 -7
View File
@@ -27,12 +27,10 @@ export default class Pointer {
configure( config, oldConfig ) { configure( config, oldConfig ) {
if( config.mouseWheel ) { if( config.mouseWheel ) {
document.addEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false ); // FF document.addEventListener( 'wheel', this.onDocumentMouseScroll, false );
document.addEventListener( 'mousewheel', this.onDocumentMouseScroll, false );
} }
else { else {
document.removeEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false ); // FF document.removeEventListener( 'wheel', this.onDocumentMouseScroll, false );
document.removeEventListener( 'mousewheel', this.onDocumentMouseScroll, false );
} }
// Auto-hide the mouse pointer when its inactive // Auto-hide the mouse pointer when its inactive
@@ -79,8 +77,7 @@ export default class Pointer {
this.showCursor(); this.showCursor();
document.removeEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false ); document.removeEventListener( 'wheel', this.onDocumentMouseScroll, false );
document.removeEventListener( 'mousewheel', this.onDocumentMouseScroll, false );
document.removeEventListener( 'mousemove', this.onDocumentCursorActive, false ); document.removeEventListener( 'mousemove', this.onDocumentCursorActive, false );
document.removeEventListener( 'mousedown', this.onDocumentCursorActive, false ); document.removeEventListener( 'mousedown', this.onDocumentCursorActive, false );
@@ -126,4 +123,4 @@ export default class Pointer {
} }
} }
@@ -4,7 +4,7 @@ import { queryAll, createStyleSheet } from '../utils/util.js'
/** /**
* Setups up our presentation for printing/exporting to PDF. * Setups up our presentation for printing/exporting to PDF.
*/ */
export default class Print { export default class PrintView {
constructor( Reveal ) { constructor( Reveal ) {
@@ -16,7 +16,7 @@ export default class Print {
* Configures the presentation for printing to a static * Configures the presentation for printing to a static
* PDF. * PDF.
*/ */
async setupPDF() { async activate() {
const config = this.Reveal.getConfig(); const config = this.Reveal.getConfig();
const slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ) const slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR )
@@ -42,11 +42,11 @@ export default class Print {
// Limit the size of certain elements to the dimensions of the slide // Limit the size of certain elements to the dimensions of the slide
createStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' ); createStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' );
document.documentElement.classList.add( 'print-pdf' ); document.documentElement.classList.add( 'reveal-print', 'print-pdf' );
document.body.style.width = pageWidth + 'px'; document.body.style.width = pageWidth + 'px';
document.body.style.height = pageHeight + 'px'; document.body.style.height = pageHeight + 'px';
const viewportElement = document.querySelector( '.reveal-viewport' ); const viewportElement = this.Reveal.getViewportElement();
let presentationBackground; let presentationBackground;
if( viewportElement ) { if( viewportElement ) {
const viewportStyles = window.getComputedStyle( viewportElement ); const viewportStyles = window.getComputedStyle( viewportElement );
@@ -226,12 +226,12 @@ export default class Print {
} }
/** /**
* Checks if this instance is being used to print a PDF. * Checks if the print mode is/should be activated.
*/ */
isPrintingPDF() { isActive() {
return ( /print-pdf/gi ).test( window.location.search ); return this.Reveal.getConfig().view === 'print';
} }
} }
+888
View File
@@ -0,0 +1,888 @@
import { HORIZONTAL_SLIDES_SELECTOR } from '../utils/constants.js'
import { queryAll } from '../utils/util.js'
const HIDE_SCROLLBAR_TIMEOUT = 500;
const MAX_PROGRESS_SPACING = 4;
const MIN_PROGRESS_SEGMENT_HEIGHT = 6;
const MIN_PLAYHEAD_HEIGHT = 8;
/**
* The scroll view lets you read a reveal.js presentation
* as a linear scrollable page.
*/
export default class ScrollView {
constructor( Reveal ) {
this.Reveal = Reveal;
this.active = false;
this.activatedCallbacks = [];
this.onScroll = this.onScroll.bind( this );
}
/**
* Activates the scroll view. This rearranges the presentation DOM
* byamong other thingswrapping each slide in a page element.
*/
activate() {
if( this.active ) return;
const stateBeforeActivation = this.Reveal.getState();
this.active = true;
// Store the full presentation HTML so that we can restore it
// when/if the scroll view is deactivated
this.slideHTMLBeforeActivation = this.Reveal.getSlidesElement().innerHTML;
const horizontalSlides = queryAll( this.Reveal.getRevealElement(), HORIZONTAL_SLIDES_SELECTOR );
this.viewportElement.classList.add( 'loading-scroll-mode', 'reveal-scroll' );
let presentationBackground;
const viewportStyles = window.getComputedStyle( this.viewportElement );
if( viewportStyles && viewportStyles.background ) {
presentationBackground = viewportStyles.background;
}
const pageElements = [];
const pageContainer = horizontalSlides[0].parentNode;
let previousSlide;
// Creates a new page element and appends the given slide/bg
// to it.
const createPageElement = ( slide, h, v ) => {
let contentContainer;
// If this slide is part of an auto-animation sequence, we
// group it under the same page element as the previous slide
if( previousSlide && this.Reveal.shouldAutoAnimateBetween( previousSlide, slide ) ) {
contentContainer = document.createElement( 'div' );
contentContainer.className = 'scroll-page-content scroll-auto-animate-page';
contentContainer.style.display = 'none';
previousSlide.closest( '.scroll-page-content' ).parentNode.appendChild( contentContainer );
}
else {
// Wrap the slide in a page element and hide its overflow
// so that no page ever flows onto another
const page = document.createElement( 'div' );
page.className = 'scroll-page';
pageElements.push( page );
// Copy the presentation-wide background to each page
if( presentationBackground ) {
page.style.background = presentationBackground;
}
const stickyContainer = document.createElement( 'div' );
stickyContainer.className = 'scroll-page-sticky';
page.appendChild( stickyContainer );
contentContainer = document.createElement( 'div' );
contentContainer.className = 'scroll-page-content';
stickyContainer.appendChild( contentContainer );
}
contentContainer.appendChild( slide );
slide.classList.remove( 'past', 'future' );
slide.setAttribute( 'data-index-h', h );
slide.setAttribute( 'data-index-v', v );
if( slide.slideBackgroundElement ) {
slide.slideBackgroundElement.remove( 'past', 'future' );
contentContainer.insertBefore( slide.slideBackgroundElement, slide );
}
previousSlide = slide;
}
// Slide and slide background layout
horizontalSlides.forEach( ( horizontalSlide, h ) => {
if( this.Reveal.isVerticalStack( horizontalSlide ) ) {
horizontalSlide.querySelectorAll( 'section' ).forEach( ( verticalSlide, v ) => {
createPageElement( verticalSlide, h, v );
});
}
else {
createPageElement( horizontalSlide, h, 0 );
}
}, this );
this.createProgressBar();
// Remove leftover stacks
queryAll( this.Reveal.getRevealElement(), '.stack' ).forEach( stack => stack.remove() );
// Add our newly created pages to the DOM
pageElements.forEach( page => pageContainer.appendChild( page ) );
// Re-run JS-based content layout after the slide is added to page DOM
this.Reveal.slideContent.layout( this.Reveal.getSlidesElement() );
this.Reveal.layout();
this.Reveal.setState( stateBeforeActivation );
this.activatedCallbacks.forEach( callback => callback() );
this.activatedCallbacks = [];
this.restoreScrollPosition();
this.viewportElement.classList.remove( 'loading-scroll-mode' );
this.viewportElement.addEventListener( 'scroll', this.onScroll, { passive: true } );
}
/**
* Deactivates the scroll view and restores the standard slide-based
* presentation.
*/
deactivate() {
if( !this.active ) return;
const stateBeforeDeactivation = this.Reveal.getState();
this.active = false;
this.viewportElement.removeEventListener( 'scroll', this.onScroll );
this.viewportElement.classList.remove( 'reveal-scroll' );
this.removeProgressBar();
this.Reveal.getSlidesElement().innerHTML = this.slideHTMLBeforeActivation;
this.Reveal.sync();
this.Reveal.setState( stateBeforeDeactivation );
this.slideHTMLBeforeActivation = null;
}
toggle( override ) {
if( typeof override === 'boolean' ) {
override ? this.activate() : this.deactivate();
}
else {
this.isActive() ? this.deactivate() : this.activate();
}
}
/**
* Checks if the scroll view is currently active.
*/
isActive() {
return this.active;
}
/**
* Renders the progress bar component.
*/
createProgressBar() {
this.progressBar = document.createElement( 'div' );
this.progressBar.className = 'scrollbar';
this.progressBarInner = document.createElement( 'div' );
this.progressBarInner.className = 'scrollbar-inner';
this.progressBar.appendChild( this.progressBarInner );
this.progressBarPlayhead = document.createElement( 'div' );
this.progressBarPlayhead.className = 'scrollbar-playhead';
this.progressBarInner.appendChild( this.progressBarPlayhead );
this.viewportElement.insertBefore( this.progressBar, this.viewportElement.firstChild );
const handleDocumentMouseMove = ( event ) => {
let progress = ( event.clientY - this.progressBarInner.getBoundingClientRect().top ) / this.progressBarHeight;
progress = Math.max( Math.min( progress, 1 ), 0 );
this.viewportElement.scrollTop = progress * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );
};
const handleDocumentMouseUp = ( event ) => {
this.draggingProgressBar = false;
this.showProgressBar();
document.removeEventListener( 'mousemove', handleDocumentMouseMove );
document.removeEventListener( 'mouseup', handleDocumentMouseUp );
};
const handleMouseDown = ( event ) => {
event.preventDefault();
this.draggingProgressBar = true;
document.addEventListener( 'mousemove', handleDocumentMouseMove );
document.addEventListener( 'mouseup', handleDocumentMouseUp );
handleDocumentMouseMove( event );
};
this.progressBarInner.addEventListener( 'mousedown', handleMouseDown );
}
removeProgressBar() {
if( this.progressBar ) {
this.progressBar.remove();
this.progressBar = null;
}
}
layout() {
if( this.isActive() ) {
this.syncPages();
this.syncScrollPosition();
}
}
/**
* Updates our pages to match the latest configuration and
* presentation size.
*/
syncPages() {
const config = this.Reveal.getConfig();
const slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight );
const scale = this.Reveal.getScale();
const useCompactLayout = config.scrollLayout === 'compact';
const viewportHeight = this.viewportElement.offsetHeight;
const compactHeight = slideSize.height * scale;
const pageHeight = useCompactLayout ? compactHeight : viewportHeight;
// The height that needs to be scrolled between scroll triggers
const scrollTriggerHeight = useCompactLayout ? compactHeight : viewportHeight;
this.viewportElement.style.setProperty( '--page-height', pageHeight + 'px' );
this.viewportElement.style.scrollSnapType = typeof config.scrollSnap === 'string' ? `y ${config.scrollSnap}` : '';
// This will hold all scroll triggers used to show/hide slides
this.slideTriggers = [];
const pageElements = Array.from( this.Reveal.getRevealElement().querySelectorAll( '.scroll-page' ) );
this.pages = pageElements.map( pageElement => {
const page = this.createPage({
pageElement,
slideElement: pageElement.querySelector( 'section' ),
stickyElement: pageElement.querySelector( '.scroll-page-sticky' ),
contentElement: pageElement.querySelector( '.scroll-page-content' ),
backgroundElement: pageElement.querySelector( '.slide-background' ),
autoAnimateElements: pageElement.querySelectorAll( '.scroll-auto-animate-page' ),
autoAnimatePages: []
});
page.pageElement.style.setProperty( '--slide-height', config.center === true ? 'auto' : slideSize.height + 'px' );
this.slideTriggers.push({
page: page,
activate: () => this.activatePage( page ),
deactivate: () => this.deactivatePage( page )
});
// Create scroll triggers that show/hide fragments
this.createFragmentTriggersForPage( page );
// Create scroll triggers for triggering auto-animate steps
if( page.autoAnimateElements.length > 0 ) {
this.createAutoAnimateTriggersForPage( page );
}
let totalScrollTriggerCount = Math.max( page.scrollTriggers.length - 1, 0 );
// Each auto-animate step may include its own scroll triggers
// for fragments, ensure we count those as well
totalScrollTriggerCount += page.autoAnimatePages.reduce( ( total, page ) => {
return total + Math.max( page.scrollTriggers.length - 1, 0 );
}, page.autoAnimatePages.length );
// Clean up from previous renders
page.pageElement.querySelectorAll( '.scroll-snap-point' ).forEach( el => el.remove() );
// Create snap points for all scroll triggers
// - Can't be absolute in FF
// - Can't be 0-height in Safari
// - Can't use snap-align on parent in Safari because then
// inner triggers won't work
for( let i = 0; i < totalScrollTriggerCount + 1; i++ ) {
const triggerStick = document.createElement( 'div' );
triggerStick.className = 'scroll-snap-point';
triggerStick.style.height = scrollTriggerHeight + 'px';
triggerStick.style.scrollSnapAlign = useCompactLayout ? 'center' : 'start';
page.pageElement.appendChild( triggerStick );
if( i === 0 ) {
triggerStick.style.marginTop = -scrollTriggerHeight + 'px';
}
}
// In the compact layout, only slides with scroll triggers cover the
// full viewport height. This helps avoid empty gaps before or after
// a sticky slide.
if( useCompactLayout && page.scrollTriggers.length > 0 ) {
page.pageHeight = viewportHeight;
page.pageElement.style.setProperty( '--page-height', viewportHeight + 'px' );
}
else {
page.pageHeight = pageHeight;
page.pageElement.style.removeProperty( '--page-height' );
}
// Add scroll padding based on how many scroll triggers we have
page.scrollPadding = scrollTriggerHeight * totalScrollTriggerCount;
// The total height including scrollable space
page.totalHeight = page.pageHeight + page.scrollPadding;
// This is used to pad the height of our page in CSS
page.pageElement.style.setProperty( '--page-scroll-padding', page.scrollPadding + 'px' );
// If this is a sticky page, stick it to the vertical center
if( totalScrollTriggerCount > 0 ) {
page.stickyElement.style.position = 'sticky';
page.stickyElement.style.top = Math.max( ( viewportHeight - page.pageHeight ) / 2, 0 ) + 'px';
}
else {
page.stickyElement.style.position = 'relative';
page.pageElement.style.scrollSnapAlign = page.pageHeight < viewportHeight ? 'center' : 'start';
}
return page;
} );
this.setTriggerRanges();
/*
console.log(this.slideTriggers.map( t => {
return {
range: `${t.range[0].toFixed(2)}-${t.range[1].toFixed(2)}`,
triggers: t.page.scrollTriggers.map( t => {
return `${t.range[0].toFixed(2)}-${t.range[1].toFixed(2)}`
}).join( ', ' ),
}
}))
*/
this.viewportElement.setAttribute( 'data-scrollbar', config.scrollProgress );
if( config.scrollProgress && this.totalScrollTriggerCount > 1 ) {
// Create the progress bar if it doesn't already exist
if( !this.progressBar ) this.createProgressBar();
this.syncProgressBar();
}
else {
this.removeProgressBar();
}
}
/**
* Calculates and sets the scroll range for all of our scroll
* triggers.
*/
setTriggerRanges() {
// Calculate the total number of scroll triggers
this.totalScrollTriggerCount = this.slideTriggers.reduce( ( total, trigger ) => {
return total + Math.max( trigger.page.scrollTriggers.length, 1 );
}, 0 );
let rangeStart = 0;
// Calculate the scroll range of each scroll trigger on a scale
// of 0-1
this.slideTriggers.forEach( ( trigger, i ) => {
trigger.range = [
rangeStart,
rangeStart + Math.max( trigger.page.scrollTriggers.length, 1 ) / this.totalScrollTriggerCount
];
const scrollTriggerSegmentSize = ( trigger.range[1] - trigger.range[0] ) / trigger.page.scrollTriggers.length;
// Set the range for each inner scroll trigger
trigger.page.scrollTriggers.forEach( ( scrollTrigger, i ) => {
scrollTrigger.range = [
rangeStart + i * scrollTriggerSegmentSize,
rangeStart + ( i + 1 ) * scrollTriggerSegmentSize
];
} );
rangeStart = trigger.range[1];
} );
}
/**
* Creates one scroll trigger for each fragments in the given page.
*
* @param {*} page
*/
createFragmentTriggersForPage( page, slideElement ) {
slideElement = slideElement || page.slideElement;
// Each fragment 'group' is an array containing one or more
// fragments. Multiple fragments that appear at the same time
// are part of the same group.
const fragmentGroups = this.Reveal.fragments.sort( slideElement.querySelectorAll( '.fragment' ), true );
// Create scroll triggers that show/hide fragments
if( fragmentGroups.length ) {
page.fragments = this.Reveal.fragments.sort( slideElement.querySelectorAll( '.fragment:not(.disabled)' ) );
page.scrollTriggers.push(
// Trigger for the initial state with no fragments visible
{
activate: () => {
this.Reveal.fragments.update( -1, page.fragments, slideElement );
}
},
// Triggers for each fragment group
...fragmentGroups.map( ( fragments, i ) => ({
activate: () => {
this.Reveal.fragments.update( i, page.fragments, slideElement );
}
})
)
);
}
return page.scrollTriggers.length;
}
/**
* Creates scroll triggers for the auto-animate steps in the
* given page.
*
* @param {*} page
*/
createAutoAnimateTriggersForPage( page ) {
if( page.autoAnimateElements.length > 0 ) {
// Triggers for each subsequent auto-animate slide
this.slideTriggers.push( ...Array.from( page.autoAnimateElements ).map( ( autoAnimateElement, i ) => {
let autoAnimatePage = this.createPage({
slideElement: autoAnimateElement.querySelector( 'section' ),
contentElement: autoAnimateElement,
backgroundElement: autoAnimateElement.querySelector( '.slide-background' )
});
// Create fragment scroll triggers for the auto-animate slide
this.createFragmentTriggersForPage( autoAnimatePage, autoAnimatePage.slideElement );
page.autoAnimatePages.push( autoAnimatePage );
// Return our slide trigger
return {
page: autoAnimatePage,
activate: () => this.activatePage( autoAnimatePage ),
deactivate: () => this.deactivatePage( autoAnimatePage )
};
}));
}
}
/**
* Helper method for creating a page definition and adding
* required fields. A "page" is a slide or auto-animate step.
*/
createPage( page ) {
page.scrollTriggers = [];
page.indexh = parseInt( page.slideElement.getAttribute( 'data-index-h' ), 10 );
page.indexv = parseInt( page.slideElement.getAttribute( 'data-index-v' ), 10 );
return page;
}
/**
* Rerenders progress bar segments so that they match the current
* reveal.js config and size.
*/
syncProgressBar() {
this.progressBarInner.querySelectorAll( '.scrollbar-slide' ).forEach( slide => slide.remove() );
const scrollHeight = this.viewportElement.scrollHeight;
const viewportHeight = this.viewportElement.offsetHeight;
const viewportHeightFactor = viewportHeight / scrollHeight;
this.progressBarHeight = this.progressBarInner.offsetHeight;
this.playheadHeight = Math.max( viewportHeightFactor * this.progressBarHeight, MIN_PLAYHEAD_HEIGHT );
this.progressBarScrollableHeight = this.progressBarHeight - this.playheadHeight;
const progressSegmentHeight = viewportHeight / scrollHeight * this.progressBarHeight;
const spacing = Math.min( progressSegmentHeight / 8, MAX_PROGRESS_SPACING );
this.progressBarPlayhead.style.height = this.playheadHeight - spacing + 'px';
// Don't show individual segments if they're too small
if( progressSegmentHeight > MIN_PROGRESS_SEGMENT_HEIGHT ) {
this.slideTriggers.forEach( slideTrigger => {
const { page } = slideTrigger;
// Visual representation of a slide
page.progressBarSlide = document.createElement( 'div' );
page.progressBarSlide.className = 'scrollbar-slide';
page.progressBarSlide.style.top = slideTrigger.range[0] * this.progressBarHeight + 'px';
page.progressBarSlide.style.height = ( slideTrigger.range[1] - slideTrigger.range[0] ) * this.progressBarHeight - spacing + 'px';
page.progressBarSlide.classList.toggle( 'has-triggers', page.scrollTriggers.length > 0 );
this.progressBarInner.appendChild( page.progressBarSlide );
// Visual representations of each scroll trigger
page.scrollTriggerElements = page.scrollTriggers.map( ( trigger, i ) => {
const triggerElement = document.createElement( 'div' );
triggerElement.className = 'scrollbar-trigger';
triggerElement.style.top = ( trigger.range[0] - slideTrigger.range[0] ) * this.progressBarHeight + 'px';
triggerElement.style.height = ( trigger.range[1] - trigger.range[0] ) * this.progressBarHeight - spacing + 'px';
page.progressBarSlide.appendChild( triggerElement );
if( i === 0 ) triggerElement.style.display = 'none';
return triggerElement;
} );
} );
}
else {
this.pages.forEach( page => page.progressBarSlide = null );
}
}
/**
* Reads the current scroll position and updates our active
* trigger states accordingly.
*/
syncScrollPosition() {
const viewportHeight = this.viewportElement.offsetHeight;
const viewportHeightFactor = viewportHeight / this.viewportElement.scrollHeight;
const scrollTop = this.viewportElement.scrollTop;
const scrollHeight = this.viewportElement.scrollHeight - viewportHeight
const scrollProgress = Math.max( Math.min( scrollTop / scrollHeight, 1 ), 0 );
const scrollProgressMid = Math.max( Math.min( ( scrollTop + viewportHeight / 2 ) / this.viewportElement.scrollHeight, 1 ), 0 );
let activePage;
this.slideTriggers.forEach( ( trigger ) => {
const { page } = trigger;
const shouldPreload = scrollProgress >= trigger.range[0] - viewportHeightFactor*2 &&
scrollProgress <= trigger.range[1] + viewportHeightFactor*2;
// Load slides that are within the preload range
if( shouldPreload && !page.loaded ) {
page.loaded = true;
this.Reveal.slideContent.load( page.slideElement );
}
else if( page.loaded ) {
page.loaded = false;
this.Reveal.slideContent.unload( page.slideElement );
}
// If we're within this trigger range, activate it
if( scrollProgress >= trigger.range[0] && scrollProgress <= trigger.range[1] ) {
this.activateTrigger( trigger );
activePage = trigger.page;
}
// .. otherwise deactivate
else if( trigger.active ) {
this.deactivateTrigger( trigger );
}
} );
// Each page can have its own scroll triggers, check if any of those
// need to be activated/deactivated
if( activePage ) {
activePage.scrollTriggers.forEach( ( trigger ) => {
if( scrollProgressMid >= trigger.range[0] && scrollProgressMid <= trigger.range[1] ) {
this.activateTrigger( trigger );
}
else if( trigger.active ) {
this.deactivateTrigger( trigger );
}
} );
}
// Update our visual progress indication
this.setProgressBarValue( scrollTop / ( this.viewportElement.scrollHeight - viewportHeight ) );
}
/**
* Moves the progress bar playhead to the specified position.
*
* @param {number} progress 0-1
*/
setProgressBarValue( progress ) {
if( this.progressBar ) {
this.progressBarPlayhead.style.transform = `translateY(${progress * this.progressBarScrollableHeight}px)`;
this.getAllPages()
.filter( page => page.progressBarSlide )
.forEach( ( page ) => {
page.progressBarSlide.classList.toggle( 'active', page.active === true );
page.scrollTriggers.forEach( ( trigger, i ) => {
page.scrollTriggerElements[i].classList.toggle( 'active', page.active === true && trigger.active === true );
} );
} );
this.showProgressBar();
}
}
/**
* Show the progress bar and, if configured, automatically hide
* it after a delay.
*/
showProgressBar() {
this.progressBar.classList.add( 'visible' );
clearTimeout( this.hideProgressBarTimeout );
if( this.Reveal.getConfig().scrollProgress === 'auto' && !this.draggingProgressBar ) {
this.hideProgressBarTimeout = setTimeout( () => {
if( this.progressBar ) {
this.progressBar.classList.remove( 'visible' );
}
}, HIDE_SCROLLBAR_TIMEOUT );
}
}
/**
* Scrolls the given slide element into view.
*
* @param {HTMLElement} slideElement
*/
scrollToSlide( slideElement ) {
// If the scroll view isn't active yet, queue this action
if( !this.active ) {
this.activatedCallbacks.push( () => this.scrollToSlide( slideElement ) );
}
else {
// Find the trigger for this slide
const trigger = this.getScrollTriggerBySlide( slideElement );
if( trigger ) {
// Use the trigger's range to calculate the scroll position
this.viewportElement.scrollTop = trigger.range[0] * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );
}
}
}
/**
* Persists the current scroll position to session storage
* so that it can be restored.
*/
storeScrollPosition() {
clearTimeout( this.storeScrollPositionTimeout );
this.storeScrollPositionTimeout = setTimeout( () => {
sessionStorage.setItem( 'reveal-scroll-top', this.viewportElement.scrollTop );
sessionStorage.setItem( 'reveal-scroll-origin', location.origin + location.pathname );
this.storeScrollPositionTimeout = null;
}, 50 );
}
/**
* Restores the scroll position when a deck is reloader.
*/
restoreScrollPosition() {
const scrollPosition = sessionStorage.getItem( 'reveal-scroll-top' );
const scrollOrigin = sessionStorage.getItem( 'reveal-scroll-origin' );
if( scrollPosition && scrollOrigin === location.origin + location.pathname ) {
this.viewportElement.scrollTop = parseInt( scrollPosition, 10 );
}
}
/**
* Activates the given page and starts its embedded content
* if there is any.
*
* @param {object} page
*/
activatePage( page ) {
if( !page.active ) {
page.active = true;
const { slideElement, backgroundElement, contentElement, indexh, indexv } = page;
contentElement.style.display = 'block';
slideElement.classList.add( 'present' );
if( backgroundElement ) {
backgroundElement.classList.add( 'present' );
}
this.Reveal.setCurrentScrollPage( slideElement, indexh, indexv );
this.Reveal.backgrounds.bubbleSlideContrastClassToElement( slideElement, this.viewportElement );
// If this page is part of an auto-animation there will be one
// content element per auto-animated page. We need to show the
// current page and hide all others.
Array.from( contentElement.parentNode.querySelectorAll( '.scroll-page-content' ) ).forEach( sibling => {
if( sibling !== contentElement ) {
sibling.style.display = 'none';
}
});
}
}
/**
* Deactivates the page after it has been visible.
*
* @param {object} page
*/
deactivatePage( page ) {
if( page.active ) {
page.active = false;
page.slideElement.classList.remove( 'present' );
page.backgroundElement.classList.remove( 'present' );
}
}
activateTrigger( trigger ) {
if( !trigger.active ) {
trigger.active = true;
trigger.activate();
}
}
deactivateTrigger( trigger ) {
if( trigger.active ) {
trigger.active = false;
if( trigger.deactivate ) {
trigger.deactivate();
}
}
}
/**
* Retrieve a slide by its original h/v index (i.e. the indices the
* slide had before being linearized).
*
* @param {number} h
* @param {number} v
* @returns {HTMLElement}
*/
getSlideByIndices( h, v ) {
const page = this.getAllPages().find( page => {
return page.indexh === h && page.indexv === v;
} );
return page ? page.slideElement : null;
}
/**
* Retrieve a list of all scroll triggers for the given slide
* DOM element.
*
* @param {HTMLElement} slide
* @returns {Array}
*/
getScrollTriggerBySlide( slide ) {
return this.slideTriggers.find( trigger => trigger.page.slideElement === slide );
}
/**
* Get a list of all pages in the scroll view. This includes
* both top-level slides and auto-animate steps.
*
* @returns {Array}
*/
getAllPages() {
return this.pages.flatMap( page => [page, ...(page.autoAnimatePages || [])] );
}
onScroll() {
this.syncScrollPosition();
this.storeScrollPosition();
}
get viewportElement() {
return this.Reveal.getViewportElement();
}
}
+4
View File
@@ -25,6 +25,10 @@ export default class SlideContent {
*/ */
shouldPreload( element ) { shouldPreload( element ) {
if( this.Reveal.isScrollView() ) {
return true;
}
// Prefer an explicit global preload setting // Prefer an explicit global preload setting
let preload = this.Reveal.getConfig().preloadIframes; let preload = this.Reveal.getConfig().preloadIframes;
+1 -1
View File
@@ -23,7 +23,7 @@ export default class SlideNumber {
configure( config, oldConfig ) { configure( config, oldConfig ) {
let slideNumberDisplay = 'none'; let slideNumberDisplay = 'none';
if( config.slideNumber && !this.Reveal.isPrintingPDF() ) { if( config.slideNumber && !this.Reveal.isPrintView() ) {
if( config.showSlideNumber === 'all' ) { if( config.showSlideNumber === 'all' ) {
slideNumberDisplay = 'block'; slideNumberDisplay = 'block';
} }
+240 -62
View File
@@ -3,6 +3,8 @@ import SlideNumber from './controllers/slidenumber.js'
import JumpToSlide from './controllers/jumptoslide.js' import JumpToSlide from './controllers/jumptoslide.js'
import Backgrounds from './controllers/backgrounds.js' import Backgrounds from './controllers/backgrounds.js'
import AutoAnimate from './controllers/autoanimate.js' import AutoAnimate from './controllers/autoanimate.js'
import ScrollView from './controllers/scrollview.js'
import PrintView from './controllers/printview.js'
import Fragments from './controllers/fragments.js' import Fragments from './controllers/fragments.js'
import Overview from './controllers/overview.js' import Overview from './controllers/overview.js'
import Keyboard from './controllers/keyboard.js' import Keyboard from './controllers/keyboard.js'
@@ -11,7 +13,6 @@ import Controls from './controllers/controls.js'
import Progress from './controllers/progress.js' import Progress from './controllers/progress.js'
import Pointer from './controllers/pointer.js' import Pointer from './controllers/pointer.js'
import Plugins from './controllers/plugins.js' import Plugins from './controllers/plugins.js'
import Print from './controllers/print.js'
import Touch from './controllers/touch.js' import Touch from './controllers/touch.js'
import Focus from './controllers/focus.js' import Focus from './controllers/focus.js'
import Notes from './controllers/notes.js' import Notes from './controllers/notes.js'
@@ -27,7 +28,7 @@ import {
} from './utils/constants.js' } from './utils/constants.js'
// The reveal.js version // The reveal.js version
export const VERSION = '4.5.0'; export const VERSION = '5.0.1';
/** /**
* reveal.js * reveal.js
@@ -105,6 +106,8 @@ export default function( revealElement, options ) {
jumpToSlide = new JumpToSlide( Reveal ), jumpToSlide = new JumpToSlide( Reveal ),
autoAnimate = new AutoAnimate( Reveal ), autoAnimate = new AutoAnimate( Reveal ),
backgrounds = new Backgrounds( Reveal ), backgrounds = new Backgrounds( Reveal ),
scrollView = new ScrollView( Reveal ),
printView = new PrintView( Reveal ),
fragments = new Fragments( Reveal ), fragments = new Fragments( Reveal ),
overview = new Overview( Reveal ), overview = new Overview( Reveal ),
keyboard = new Keyboard( Reveal ), keyboard = new Keyboard( Reveal ),
@@ -113,7 +116,6 @@ export default function( revealElement, options ) {
progress = new Progress( Reveal ), progress = new Progress( Reveal ),
pointer = new Pointer( Reveal ), pointer = new Pointer( Reveal ),
plugins = new Plugins( Reveal ), plugins = new Plugins( Reveal ),
print = new Print( Reveal ),
focus = new Focus( Reveal ), focus = new Focus( Reveal ),
touch = new Touch( Reveal ), touch = new Touch( Reveal ),
notes = new Notes( Reveal ); notes = new Notes( Reveal );
@@ -140,6 +142,11 @@ export default function( revealElement, options ) {
// 5. Query params // 5. Query params
config = { ...defaultConfig, ...config, ...options, ...initOptions, ...Util.getQueryHash() }; config = { ...defaultConfig, ...config, ...options, ...initOptions, ...Util.getQueryHash() };
// Legacy support for the ?print-pdf query
if( /print-pdf/gi.test( window.location.search ) ) {
config.view = 'print';
}
setViewport(); setViewport();
// Force a layout when the whole page, incl fonts, has loaded // Force a layout when the whole page, incl fonts, has loaded
@@ -201,12 +208,15 @@ export default function( revealElement, options ) {
// Updates the presentation to match the current configuration values // Updates the presentation to match the current configuration values
configure(); configure();
// Read the initial hash
location.readURL();
// Create slide backgrounds // Create slide backgrounds
backgrounds.update( true ); backgrounds.update( true );
// Activate the print/scroll view if configured
activateInitialView();
// Read the initial hash
location.readURL();
// Notify listeners that the presentation is ready but use a 1ms // Notify listeners that the presentation is ready but use a 1ms
// timeout to ensure it's not fired synchronously after #initialize() // timeout to ensure it's not fired synchronously after #initialize()
setTimeout( () => { setTimeout( () => {
@@ -225,19 +235,41 @@ export default function( revealElement, options ) {
}); });
}, 1 ); }, 1 );
// Special setup and config is required when printing to PDF }
if( print.isPrintingPDF() ) {
removeEventListeners();
// The document needs to have loaded for the PDF layout /**
// measurements to be accurate * Activates the correct reveal.js view based on our config.
if( document.readyState === 'complete' ) { * This is only invoked once during initialization.
print.setupPDF(); */
function activateInitialView() {
const activatePrintView = config.view === 'print';
const activateScrollView = config.view === 'scroll' || config.view === 'reader';
if( activatePrintView || activateScrollView ) {
if( activatePrintView ) {
removeEventListeners();
} }
else { else {
window.addEventListener( 'load', () => { touch.unbind();
print.setupPDF(); }
} );
// Avoid content flickering during layout
dom.viewport.classList.add( 'loading-scroll-mode' );
if( activatePrintView ) {
// The document needs to have loaded for the PDF layout
// measurements to be accurate
if( document.readyState === 'complete' ) {
printView.activate();
}
else {
window.addEventListener( 'load', () => printView.activate() );
}
}
else {
scrollView.activate();
} }
} }
@@ -255,7 +287,18 @@ export default function( revealElement, options ) {
if( !config.showHiddenSlides ) { if( !config.showHiddenSlides ) {
Util.queryAll( dom.wrapper, 'section[data-visibility="hidden"]' ).forEach( slide => { Util.queryAll( dom.wrapper, 'section[data-visibility="hidden"]' ).forEach( slide => {
slide.parentNode.removeChild( slide ); const parent = slide.parentNode;
// If this slide is part of a stack and that stack will be
// empty after removing the hidden slide, remove the entire
// stack
if( parent.childElementCount === 1 && /section/i.test( parent.nodeName ) ) {
parent.remove();
}
else {
slide.remove();
}
} ); } );
} }
@@ -374,7 +417,7 @@ export default function( revealElement, options ) {
function setupScrollPrevention() { function setupScrollPrevention() {
setInterval( () => { setInterval( () => {
if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) { if( !scrollView.isActive() && dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {
dom.wrapper.scrollTop = 0; dom.wrapper.scrollTop = 0;
dom.wrapper.scrollLeft = 0; dom.wrapper.scrollLeft = 0;
} }
@@ -441,8 +484,8 @@ export default function( revealElement, options ) {
dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition ); dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );
// Expose our configured slide dimensions as custom props // Expose our configured slide dimensions as custom props
dom.viewport.style.setProperty( '--slide-width', config.width + 'px' ); dom.viewport.style.setProperty( '--slide-width', typeof config.width === 'string' ? config.width : config.width + 'px' );
dom.viewport.style.setProperty( '--slide-height', config.height + 'px' ); dom.viewport.style.setProperty( '--slide-height', typeof config.height === 'string' ? config.height : config.height + 'px' );
if( config.shuffle ) { if( config.shuffle ) {
shuffle(); shuffle();
@@ -678,6 +721,26 @@ export default function( revealElement, options ) {
} }
/**
* Dispatches a slidechanged event.
*
* @param {string} origin Used to identify multiplex clients
*/
function dispatchSlideChanged( origin ) {
dispatchEvent({
type: 'slidechanged',
data: {
indexh,
indexv,
previousSlide,
currentSlide,
origin
}
});
}
/** /**
* Dispatched a postMessage of the given type from our window. * Dispatched a postMessage of the given type from our window.
*/ */
@@ -861,7 +924,10 @@ export default function( revealElement, options ) {
*/ */
function layout() { function layout() {
if( dom.wrapper && !print.isPrintingPDF() ) { if( dom.wrapper && !printView.isActive() ) {
const viewportWidth = dom.viewport.offsetWidth;
const viewportHeight = dom.viewport.offsetHeight;
if( !config.disableLayout ) { if( !config.disableLayout ) {
@@ -875,7 +941,9 @@ export default function( revealElement, options ) {
document.documentElement.style.setProperty( '--vh', ( window.innerHeight * 0.01 ) + 'px' ); document.documentElement.style.setProperty( '--vh', ( window.innerHeight * 0.01 ) + 'px' );
} }
const size = getComputedSlideSize(); const size = scrollView.isActive() ?
getComputedSlideSize( viewportWidth, viewportHeight ) :
getComputedSlideSize();
const oldScale = scale; const oldScale = scale;
@@ -892,8 +960,9 @@ export default function( revealElement, options ) {
scale = Math.max( scale, config.minScale ); scale = Math.max( scale, config.minScale );
scale = Math.min( scale, config.maxScale ); scale = Math.min( scale, config.maxScale );
// Don't apply any scaling styles if scale is 1 // Don't apply any scaling styles if scale is 1 or we're
if( scale === 1 ) { // in the scroll view
if( scale === 1 || scrollView.isActive() ) {
dom.slides.style.zoom = ''; dom.slides.style.zoom = '';
dom.slides.style.left = ''; dom.slides.style.left = '';
dom.slides.style.top = ''; dom.slides.style.top = '';
@@ -921,7 +990,7 @@ export default function( revealElement, options ) {
continue; continue;
} }
if( config.center || slide.classList.contains( 'center' ) ) { if( ( config.center || slide.classList.contains( 'center' ) ) ) {
// Vertical stacks are not centred since their section // Vertical stacks are not centred since their section
// children will be // children will be
if( slide.classList.contains( 'stack' ) ) { if( slide.classList.contains( 'stack' ) ) {
@@ -947,9 +1016,25 @@ export default function( revealElement, options ) {
} }
}); });
} }
// Responsively turn on the scroll mode if there is an activation
// width configured. Ignore if we're configured to always be in
// scroll mode.
if( typeof config.scrollActivationWidth === 'number' && config.view !== 'scroll' ) {
if( size.presentationWidth > 0 && size.presentationWidth <= config.scrollActivationWidth ) {
if( !scrollView.isActive() ) scrollView.activate();
}
else {
if( scrollView.isActive() ) scrollView.deactivate();
}
}
} }
dom.viewport.style.setProperty( '--slide-scale', scale ); dom.viewport.style.setProperty( '--slide-scale', scale );
dom.viewport.style.setProperty( '--viewport-width', viewportWidth + 'px' );
dom.viewport.style.setProperty( '--viewport-height', viewportHeight + 'px' );
scrollView.layout();
progress.update(); progress.update();
backgrounds.updateParallax(); backgrounds.updateParallax();
@@ -970,7 +1055,6 @@ export default function( revealElement, options ) {
* @param {string|number} height * @param {string|number} height
*/ */
function layoutSlideContents( width, height ) { function layoutSlideContents( width, height ) {
// Handle sizing of elements with the 'r-stretch' class // Handle sizing of elements with the 'r-stretch' class
Util.queryAll( dom.slides, 'section > .stretch, section > .r-stretch' ).forEach( element => { Util.queryAll( dom.slides, 'section > .stretch, section > .r-stretch' ).forEach( element => {
@@ -1006,6 +1090,7 @@ export default function( revealElement, options ) {
* @param {number} [presentationHeight=dom.wrapper.offsetHeight] * @param {number} [presentationHeight=dom.wrapper.offsetHeight]
*/ */
function getComputedSlideSize( presentationWidth, presentationHeight ) { function getComputedSlideSize( presentationWidth, presentationHeight ) {
let width = config.width; let width = config.width;
let height = config.height; let height = config.height;
@@ -1092,6 +1177,19 @@ export default function( revealElement, options ) {
} }
/**
* Checks if the current or specified slide is a stack containing
* vertical slides.
*
* @param {HTMLElement} [slide=currentSlide]
* @return {Boolean}
*/
function isVerticalStack( slide = currentSlide ) {
return slide.classList.contains( '.stack' ) || slide.querySelector( 'section' ) !== null;
}
/** /**
* Returns true if we're on the last slide in the current * Returns true if we're on the last slide in the current
* vertical stack. * vertical stack.
@@ -1277,6 +1375,14 @@ export default function( revealElement, options ) {
// Query all horizontal slides in the deck // Query all horizontal slides in the deck
const horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ); const horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR );
// If we're in scroll mode, we scroll the target slide into view
// instead of running our standard slide transition
if( scrollView.isActive() ) {
const scrollToSlide = scrollView.getSlideByIndices( h, v );
if( scrollToSlide ) scrollView.scrollToSlide( scrollToSlide );
return;
}
// Abort if there are no slides // Abort if there are no slides
if( horizontalSlides.length === 0 ) return; if( horizontalSlides.length === 0 ) return;
@@ -1323,6 +1429,9 @@ export default function( revealElement, options ) {
// Detect if we're moving between two auto-animated slides // Detect if we're moving between two auto-animated slides
if( slideChanged && previousSlide && currentSlide && !overview.isActive() ) { if( slideChanged && previousSlide && currentSlide && !overview.isActive() ) {
transition = 'running';
autoAnimateTransition = shouldAutoAnimateBetween( previousSlide, currentSlide, indexhBefore, indexvBefore );
// If this is an auto-animated transition, we disable the // If this is an auto-animated transition, we disable the
// regular slide transition // regular slide transition
@@ -1330,16 +1439,9 @@ export default function( revealElement, options ) {
// Note 20-03-2020: // Note 20-03-2020:
// This needs to happen before we update slide visibility, // This needs to happen before we update slide visibility,
// otherwise transitions will still run in Safari. // otherwise transitions will still run in Safari.
if( previousSlide.hasAttribute( 'data-auto-animate' ) && currentSlide.hasAttribute( 'data-auto-animate' ) if( autoAnimateTransition ) {
&& previousSlide.getAttribute( 'data-auto-animate-id' ) === currentSlide.getAttribute( 'data-auto-animate-id' ) dom.slides.classList.add( 'disable-slide-transitions' )
&& !( ( indexh > indexhBefore || indexv > indexvBefore ) ? currentSlide : previousSlide ).hasAttribute( 'data-auto-animate-restart' ) ) {
autoAnimateTransition = true;
dom.slides.classList.add( 'disable-slide-transitions' );
} }
transition = 'running';
} }
// Update the visibility of slides now that the indices have changed // Update the visibility of slides now that the indices have changed
@@ -1398,16 +1500,7 @@ export default function( revealElement, options ) {
} }
if( slideChanged ) { if( slideChanged ) {
dispatchEvent({ dispatchSlideChanged( origin );
type: 'slidechanged',
data: {
indexh,
indexv,
previousSlide,
currentSlide,
origin
}
});
} }
// Handle embedded content // Handle embedded content
@@ -1452,6 +1545,71 @@ export default function( revealElement, options ) {
} }
/**
* Checks whether or not an auto-animation should take place between
* the two given slides.
*
* @param {HTMLElement} fromSlide
* @param {HTMLElement} toSlide
* @param {number} indexhBefore
* @param {number} indexvBefore
*
* @returns {boolean}
*/
function shouldAutoAnimateBetween( fromSlide, toSlide, indexhBefore, indexvBefore ) {
return fromSlide.hasAttribute( 'data-auto-animate' ) && toSlide.hasAttribute( 'data-auto-animate' ) &&
fromSlide.getAttribute( 'data-auto-animate-id' ) === toSlide.getAttribute( 'data-auto-animate-id' ) &&
!( ( indexh > indexhBefore || indexv > indexvBefore ) ? toSlide : fromSlide ).hasAttribute( 'data-auto-animate-restart' );
}
/**
* Called anytime a new slide should be activated while in the scroll
* view. The active slide is the page that occupies the most space in
* the scrollable viewport.
*
* @param {number} pageIndex
* @param {HTMLElement} slideElement
*/
function setCurrentScrollPage( slideElement, h, v ) {
let indexhBefore = indexh || 0;
indexh = h;
indexv = v;
const slideChanged = currentSlide !== slideElement;
previousSlide = currentSlide;
currentSlide = slideElement;
if( currentSlide && previousSlide ) {
if( config.autoAnimate && shouldAutoAnimateBetween( previousSlide, currentSlide, indexhBefore, indexv ) ) {
// Run the auto-animation between our slides
autoAnimate.run( previousSlide, currentSlide );
}
}
// Start or stop embedded content like videos and iframes
if( slideChanged ) {
if( previousSlide ) {
slideContent.stopEmbeddedContent( previousSlide );
slideContent.stopEmbeddedContent( previousSlide.slideBackgroundElement );
}
slideContent.startEmbeddedContent( currentSlide );
slideContent.startEmbeddedContent( currentSlide.slideBackgroundElement );
}
requestAnimationFrame( () => {
announceStatus( getStatusText( currentSlide ) );
});
dispatchSlideChanged();
}
/** /**
* Syncs the presentation with the current DOM. Useful * Syncs the presentation with the current DOM. Useful
* when new slides or control elements are added or when * when new slides or control elements are added or when
@@ -1597,7 +1755,7 @@ export default function( revealElement, options ) {
let slides = Util.queryAll( dom.wrapper, selector ), let slides = Util.queryAll( dom.wrapper, selector ),
slidesLength = slides.length; slidesLength = slides.length;
let printMode = print.isPrintingPDF(); let printMode = scrollView.isActive() || printView.isActive();
let loopedForwards = false; let loopedForwards = false;
let loopedBackwards = false; let loopedBackwards = false;
@@ -1709,7 +1867,7 @@ export default function( revealElement, options ) {
} }
/** /**
* Shows all fragment elements within the given contaienr. * Shows all fragment elements within the given container.
*/ */
function showFragmentsIn( container ) { function showFragmentsIn( container ) {
@@ -1721,7 +1879,7 @@ export default function( revealElement, options ) {
} }
/** /**
* Hides all fragment elements within the given contaienr. * Hides all fragment elements within the given container.
*/ */
function hideFragmentsIn( container ) { function hideFragmentsIn( container ) {
@@ -1757,7 +1915,7 @@ export default function( revealElement, options ) {
} }
// All slides need to be visible when exporting to PDF // All slides need to be visible when exporting to PDF
if( print.isPrintingPDF() ) { if( printView.isActive() ) {
viewDistance = Number.MAX_VALUE; viewDistance = Number.MAX_VALUE;
} }
@@ -1988,21 +2146,31 @@ export default function( revealElement, options ) {
// If a slide is specified, return the indices of that slide // If a slide is specified, return the indices of that slide
if( slide ) { if( slide ) {
let isVertical = isVerticalSlide( slide ); // In scroll mode the original h/x index is stored on the slide
let slideh = isVertical ? slide.parentNode : slide; if( scrollView.isActive() ) {
h = parseInt( slide.getAttribute( 'data-index-h' ), 10 );
// Select all horizontal slides if( slide.getAttribute( 'data-index-v' ) ) {
let horizontalSlides = getHorizontalSlides(); v = parseInt( slide.getAttribute( 'data-index-v' ), 10 );
}
}
else {
let isVertical = isVerticalSlide( slide );
let slideh = isVertical ? slide.parentNode : slide;
// Now that we know which the horizontal slide is, get its index // Select all horizontal slides
h = Math.max( horizontalSlides.indexOf( slideh ), 0 ); let horizontalSlides = getHorizontalSlides();
// Assume we're not vertical // Now that we know which the horizontal slide is, get its index
v = undefined; h = Math.max( horizontalSlides.indexOf( slideh ), 0 );
// If this is a vertical slide, grab the vertical index // Assume we're not vertical
if( isVertical ) { v = undefined;
v = Math.max( Util.queryAll( slide.parentNode, 'section' ).indexOf( slide ), 0 );
// If this is a vertical slide, grab the vertical index
if( isVertical ) {
v = Math.max( Util.queryAll( slide.parentNode, 'section' ).indexOf( slide ), 0 );
}
} }
} }
@@ -2675,6 +2843,9 @@ export default function( revealElement, options ) {
// Toggles the overview mode on/off // Toggles the overview mode on/off
toggleOverview: overview.toggle.bind( overview ), toggleOverview: overview.toggle.bind( overview ),
// Toggles the scroll view on/off
toggleScrollView: scrollView.toggle.bind( scrollView ),
// Toggles the "black screen" mode on/off // Toggles the "black screen" mode on/off
togglePause, togglePause,
@@ -2689,6 +2860,7 @@ export default function( revealElement, options ) {
isLastSlide, isLastSlide,
isLastVerticalSlide, isLastVerticalSlide,
isVerticalSlide, isVerticalSlide,
isVerticalStack,
// State checks // State checks
isPaused, isPaused,
@@ -2696,7 +2868,9 @@ export default function( revealElement, options ) {
isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ), isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),
isOverview: overview.isActive.bind( overview ), isOverview: overview.isActive.bind( overview ),
isFocused: focus.isFocused.bind( focus ), isFocused: focus.isFocused.bind( focus ),
isPrintingPDF: print.isPrintingPDF.bind( print ),
isScrollView: scrollView.isActive.bind( scrollView ),
isPrintView: printView.isActive.bind( printView ),
// Checks if reveal.js has been loaded and is ready for use // Checks if reveal.js has been loaded and is ready for use
isReady: () => ready, isReady: () => ready,
@@ -2769,6 +2943,8 @@ export default function( revealElement, options ) {
hasNavigatedHorizontally: () => navigationHistory.hasNavigatedHorizontally, hasNavigatedHorizontally: () => navigationHistory.hasNavigatedHorizontally,
hasNavigatedVertically: () => navigationHistory.hasNavigatedVertically, hasNavigatedVertically: () => navigationHistory.hasNavigatedVertically,
shouldAutoAnimateBetween,
// Adds/removes a custom key binding // Adds/removes a custom key binding
addKeyBinding: keyboard.addKeyBinding.bind( keyboard ), addKeyBinding: keyboard.addKeyBinding.bind( keyboard ),
removeKeyBinding: keyboard.removeKeyBinding.bind( keyboard ), removeKeyBinding: keyboard.removeKeyBinding.bind( keyboard ),
@@ -2780,6 +2956,7 @@ export default function( revealElement, options ) {
registerKeyboardShortcut: keyboard.registerKeyboardShortcut.bind( keyboard ), registerKeyboardShortcut: keyboard.registerKeyboardShortcut.bind( keyboard ),
getComputedSlideSize, getComputedSlideSize,
setCurrentScrollPage,
// Returns the current scale of the presentation content // Returns the current scale of the presentation content
getScale: () => scale, getScale: () => scale,
@@ -2816,13 +2993,14 @@ export default function( revealElement, options ) {
getStatusText, getStatusText,
// Controllers // Controllers
print,
focus, focus,
scroll: scrollView,
progress, progress,
controls, controls,
location, location,
overview, overview,
fragments, fragments,
backgrounds,
slideContent, slideContent,
slideNumber, slideNumber,
+4 -4
View File
@@ -65,7 +65,7 @@ Note: corporate control, one that presumes that you should pay even if in *your
# Alternatives # Alternatives
Note: So what are our alternatives? We've heard about several of them today and over the past few days: projects and platforms and publishing workflows that are not corporate-owned, but that rely on public and institutional investment in order to make both publishing and reading freely available to all, and that are accountable to the publics that they serve. And this is the point at which I want to turn from pontificating to instead talk about my own project... Note: So what are our alternatives? We've heard about several of them over the course of the week so far, and especially today: projects and platforms and publishing workflows that are not corporate-owned, but that rely on public and institutional investment in order to make both publishing and reading freely available to all, and that are accountable to the publics that they serve. And this is the point at which I want to turn from general pontificating to instead talk about my own project...
![Humanities Commons logo](images/hclogo-new.png) ![Humanities Commons logo](images/hclogo-new.png)
@@ -75,7 +75,7 @@ Note: Humanities Commons originated from a desire to build new avenues for more
# The Goal # The Goal
Note: Our goal is to provide a non-extractive, scholar-led, and academy-owned and transparently governed alternative to commercial platforms. Beyond that, however, we also want to encourage our users to rethink the dynamics of publishing altogether, in ways that might allow for the development of new, open, collective, equitable processes of creating and sharing knowledge that give all scholars agency over the ways their work develops and circulates. Note: Our goal is to provide a non-extractive, scholar-led, academy-owned, transparently governed alternative to commercial platforms. Beyond that, however, we want to encourage our users to rethink the purposes and the dynamics of publishing altogether, in ways that might allow for the development of new, open, collective, equitable processes of creating and sharing knowledge that recenter agency over the ways that scholarly work develops and circulates with the scholars themselves.
![Screenshot of Humanities Commons front page](images/humcomm091822.png) ![Screenshot of Humanities Commons front page](images/humcomm091822.png)
@@ -110,7 +110,7 @@ However, becoming sustainable -- rather than remaining dependent on the endless
Note: But bringing the Commons to institutions requires us to serve the entirety of the campus, not just the humanities. And this is not the usual narrative about innovation in scholarly communication, in which new ideas begin in the sciences and only gradually makes their way into the stodgy print-oriented humanities, where our elbow-patched blazers and dusty archives encourage us to resist everything technical. But last year we were approached by a group of STEM folks on campus who recognized that we've figured out something that they can learn from -- that the values-based approach to building participatory communities we've taken with the Commons is what they need to make their work successful. Note: But bringing the Commons to institutions requires us to serve the entirety of the campus, not just the humanities. And this is not the usual narrative about innovation in scholarly communication, in which new ideas begin in the sciences and only gradually makes their way into the stodgy print-oriented humanities, where our elbow-patched blazers and dusty archives encourage us to resist everything technical. But last year we were approached by a group of STEM folks on campus who recognized that we've figured out something that they can learn from -- that the values-based approach to building participatory communities we've taken with the Commons is what they need to make their work successful.
<span class="fragment highlight-red">FAIR</span><span class="fragment highlight-red">OS</span> <span class="fragment highlight-red">RCN</span> # NSF <span class="fragment highlight-red">FAIR</span><span class="fragment highlight-red">OS</span> <span class="fragment highlight-red">RCN</span>
Note: So in 2023, the Commons team was awarded a significant grant from the National Science Foundation in order to extend our model in collaboration with a group of STEM education researchers. We're part of the inaugural cohort of the NSF's FAIROS RCN grantees -- which is how I discovered the NSF's deep love for acronyms. This one is composed of three key parts: Note: So in 2023, the Commons team was awarded a significant grant from the National Science Foundation in order to extend our model in collaboration with a group of STEM education researchers. We're part of the inaugural cohort of the NSF's FAIROS RCN grantees -- which is how I discovered the NSF's deep love for acronyms. This one is composed of three key parts:
- **(CLICK)** first, FAIR, which stands for "findable, accessible, interoperable, and reusable," a set of principles guiding data sharing - **(CLICK)** first, FAIR, which stands for "findable, accessible, interoperable, and reusable," a set of principles guiding data sharing
@@ -135,7 +135,7 @@ Note: So we're working with our colleagues to develop STEMEd+ Commons, a researc
Note: But the key is that the Commons is designed to facilitate **community-building**. Its emphasis on member-to-member connections and communication is a significant component of why our STEM education colleagues came to us, rather than selecting another platform on which they could build their research coordination network -- because while there are a ton of well-funded platforms that can host and preserve the data and publications that scientists produce, many of them are operated without academic values in mind, and none of them focus on the *people* doing the work, or on the ways that discussion and collaboration amongst those people might lead to transformative change. Note: But the key is that the Commons is designed to facilitate **community-building**. Its emphasis on member-to-member connections and communication is a significant component of why our STEM education colleagues came to us, rather than selecting another platform on which they could build their research coordination network -- because while there are a ton of well-funded platforms that can host and preserve the data and publications that scientists produce, many of them are operated without academic values in mind, and none of them focus on the *people* doing the work, or on the ways that discussion and collaboration amongst those people might lead to transformative change.
# change # change
Note: And this is how we change a culture. Not by starting with the technologies, or the business model, but by starting with the people, and with the culture that connects them. If we are going to develop true open access -- publishing systems that are open both to authors and to readers, not just to contribute and consume products but to genuinely shape the future of the systems themselves -- that's where we need to begin. And that's how we get to OA without tears. Note: And this is how we change a culture. Not by starting with the technologies, or the business model, but by starting with the people, and with the culture that connects them. If we are going to develop true open access -- publishing systems that are open both to authors and to readers, not just to contribute and consume products but to genuinely shape the future of the systems themselves -- that's where we need to begin. And that's how we get to OA without tears.
+3756 -10597
View File
File diff suppressed because it is too large Load Diff
+21 -21
View File
@@ -1,6 +1,6 @@
{ {
"name": "reveal.js", "name": "reveal.js",
"version": "4.5.0", "version": "5.0.1",
"description": "The HTML Presentation Framework", "description": "The HTML Presentation Framework",
"homepage": "https://revealjs.com", "homepage": "https://revealjs.com",
"subdomain": "revealjs", "subdomain": "revealjs",
@@ -22,7 +22,7 @@
"url": "git://github.com/hakimel/reveal.js.git" "url": "git://github.com/hakimel/reveal.js.git"
}, },
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=18.0.0"
}, },
"keywords": [ "keywords": [
"reveal", "reveal",
@@ -30,33 +30,33 @@
"presentation" "presentation"
], ],
"devDependencies": { "devDependencies": {
"@babel/core": "^7.14.3", "@babel/core": "^7.23.2",
"@babel/eslint-parser": "^7.14.3", "@babel/eslint-parser": "^7.22.15",
"@babel/preset-env": "^7.14.2", "@babel/preset-env": "^7.23.2",
"@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^19.0.0", "@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^13.0.0", "@rollup/plugin-node-resolve": "^15.2.3",
"babel-plugin-transform-html-import-to-string": "0.0.1", "@rollup/plugin-terser": "^0.4.4",
"babel-plugin-transform-html-import-to-string": "2.0.0",
"colors": "^1.4.0", "colors": "^1.4.0",
"core-js": "^3.12.1", "core-js": "^3.33.1",
"fitty": "^2.3.0", "fitty": "^2.3.7",
"glob": "^7.1.7", "glob": "^10.3.10",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-autoprefixer": "^8.0.0", "gulp-autoprefixer": "^8.0.0",
"gulp-clean-css": "^4.2.0", "gulp-clean-css": "^4.3.0",
"gulp-connect": "^5.7.0", "gulp-connect": "^5.7.0",
"gulp-eslint": "^6.0.0", "gulp-eslint": "^6.0.0",
"gulp-header": "^2.0.9", "gulp-header": "^2.0.9",
"gulp-tap": "^2.0.0", "gulp-tap": "^2.0.0",
"gulp-zip": "^4.2.0", "gulp-zip": "^5.1.0",
"highlight.js": "^11.7.0", "highlight.js": "^11.9.0",
"marked": "^4.0.12", "marked": "^4.3.0",
"node-qunit-puppeteer": "^2.1.2", "node-qunit-puppeteer": "^2.1.2",
"qunit": "^2.19.3", "qunit": "^2.20.0",
"rollup": "^2.48.0", "rollup": "^4.1.5",
"rollup-plugin-terser": "^7.0.2", "sass": "^1.69.5",
"sass": "^1.39.2", "yargs": "^17.7.2"
"yargs": "^15.1.0"
}, },
"overrides": { "overrides": {
"chokidar": "3.5.3", "chokidar": "3.5.3",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -3,4 +3,4 @@ const t=()=>{let t,e={messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(",
* This plugin is a wrapper for the MathJax2, * This plugin is a wrapper for the MathJax2,
* MathJax3 and KaTeX typesetter plugins. * MathJax3 and KaTeX typesetter plugins.
*/ */
var a=Plugin=Object.assign(e(),{KaTeX:()=>{let t,e={version:"latest",delimiters:[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],ignoredTags:["script","noscript","style","textarea","pre"]};const a=t=>new Promise(((e,a)=>{const n=document.createElement("script");n.type="text/javascript",n.onload=e,n.onerror=a,n.src=t,document.head.append(n)}));return{id:"katex",init:function(n){t=n;let i=t.getConfig().katex||{},s={...e,...i};const{local:l,version:o,extensions:r,...c}=s;let d=s.local||"https://cdn.jsdelivr.net/npm/katex",p=s.local?"":"@"+s.version,u=d+p+"/dist/katex.min.css",h=d+p+"/dist/contrib/mhchem.min.js",x=d+p+"/dist/contrib/auto-render.min.js",m=[d+p+"/dist/katex.min.js"];s.extensions&&s.extensions.includes("mhchem")&&m.push(h),m.push(x);const f=()=>{renderMathInElement(n.getSlidesElement(),c),t.layout()};(t=>{let e=document.createElement("link");e.rel="stylesheet",e.href=t,document.head.appendChild(e)})(u),async function(t){for(const e of t)await a(e)}(m).then((()=>{t.isReady()?f():t.on("ready",f.bind(this))}))}}},MathJax2:t,MathJax3:()=>{let t,e={tex:{inlineMath:[["$","$"],["\\(","\\)"]]},options:{skipHtmlTags:["script","noscript","style","textarea","pre"]},startup:{ready:()=>{MathJax.startup.defaultReady(),MathJax.startup.promise.then((()=>{Reveal.layout()}))}}};return{id:"mathjax3",init:function(a){t=a;let n=t.getConfig().mathjax3||{},i={...e,...n};i.tex={...e.tex,...n.tex},i.options={...e.options,...n.options},i.startup={...e.startup,...n.startup};let s=i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js";i.mathjax=null,window.MathJax=i,function(t,e){let a=document.createElement("script");a.type="text/javascript",a.id="MathJax-script",a.src=t,a.async=!0,a.onload=()=>{"function"==typeof e&&(e.call(),e=null)},document.head.appendChild(a)}(s,(function(){Reveal.addEventListener("slidechanged",(function(t){MathJax.typeset()}))}))}}}});export default a; var a=Plugin=Object.assign(e(),{KaTeX:()=>{let t,e={version:"latest",delimiters:[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],ignoredTags:["script","noscript","style","textarea","pre"]};const a=t=>new Promise(((e,a)=>{const n=document.createElement("script");n.type="text/javascript",n.onload=e,n.onerror=a,n.src=t,document.head.append(n)}));return{id:"katex",init:function(n){t=n;let i=t.getConfig().katex||{},s={...e,...i};const{local:l,version:o,extensions:r,...c}=s;let d=s.local||"https://cdn.jsdelivr.net/npm/katex",p=s.local?"":"@"+s.version,u=d+p+"/dist/katex.min.css",h=d+p+"/dist/contrib/mhchem.min.js",x=d+p+"/dist/contrib/auto-render.min.js",m=[d+p+"/dist/katex.min.js"];s.extensions&&s.extensions.includes("mhchem")&&m.push(h),m.push(x);const f=()=>{renderMathInElement(n.getSlidesElement(),c),t.layout()};(t=>{let e=document.createElement("link");e.rel="stylesheet",e.href=t,document.head.appendChild(e)})(u),async function(t){for(const e of t)await a(e)}(m).then((()=>{t.isReady()?f():t.on("ready",f.bind(this))}))}}},MathJax2:t,MathJax3:()=>{let t,e={tex:{inlineMath:[["$","$"],["\\(","\\)"]]},options:{skipHtmlTags:["script","noscript","style","textarea","pre"]},startup:{ready:()=>{MathJax.startup.defaultReady(),MathJax.startup.promise.then((()=>{Reveal.layout()}))}}};return{id:"mathjax3",init:function(a){t=a;let n=t.getConfig().mathjax3||{},i={...e,...n};i.tex={...e.tex,...n.tex},i.options={...e.options,...n.options},i.startup={...e.startup,...n.startup};let s=i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js";i.mathjax=null,window.MathJax=i,function(t,e){let a=document.createElement("script");a.type="text/javascript",a.id="MathJax-script",a.src=t,a.async=!0,a.onload=()=>{"function"==typeof e&&(e.call(),e=null)},document.head.appendChild(a)}(s,(function(){Reveal.addEventListener("slidechanged",(function(t){MathJax.typeset()}))}))}}}});export{a as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6 -2
View File
@@ -146,8 +146,12 @@ const Plugin = () => {
} }
// Look for notes defined in an aside element // Look for notes defined in an aside element
if( notesElements ) { if( notesElements && notesElements.length ) {
messageData.notes = Array.from(notesElements).map( notesElement => notesElement.innerHTML ).join( '\n' ); // Ignore notes inside of fragments since those are shown
// individually when stepping through fragments
notesElements = Array.from( notesElements ).filter( notesElement => notesElement.closest( '.fragment' ) === null );
messageData.notes = notesElements.map( notesElement => notesElement.innerHTML ).join( '\n' );
messageData.markdown = notesElements[0] && typeof notesElements[0].getAttribute( 'data-markdown' ) === 'string'; messageData.markdown = notesElements[0] && typeof notesElements[0].getAttribute( 'data-markdown' ) === 'string';
} }
+2 -2
View File
@@ -533,8 +533,8 @@
var urlSeparator = /\?/.test(data.url) ? '&' : '?'; var urlSeparator = /\?/.test(data.url) ? '&' : '?';
var hash = '#/' + data.state.indexh + '/' + data.state.indexv; var hash = '#/' + data.state.indexh + '/' + data.state.indexv;
var currentURL = data.url + urlSeparator + params + '&postMessageEvents=true' + hash; var currentURL = data.url + urlSeparator + params + '&scrollActivationWidth=false&postMessageEvents=true' + hash;
var upcomingURL = data.url + urlSeparator + params + '&controls=false' + hash; var upcomingURL = data.url + urlSeparator + params + '&scrollActivationWidth=false&controls=false' + hash;
currentSlide = document.createElement( 'iframe' ); currentSlide = document.createElement( 'iframe' );
currentSlide.setAttribute( 'width', 1280 ); currentSlide.setAttribute( 'width', 1280 );
+1 -1
View File
@@ -4,4 +4,4 @@
* *
* @author Jon Snyder <snyder.jon@gmail.com>, February 2013 * @author Jon Snyder <snyder.jon@gmail.com>, February 2013
*/ */
export default()=>{let e,t,n,l,i,o,r;function s(){t=document.createElement("div"),t.classList.add("searchbox"),t.style.position="absolute",t.style.top="10px",t.style.right="10px",t.style.zIndex=10,t.innerHTML='<input type="search" class="searchinput" placeholder="Search..." style="vertical-align: top;"/>\n\t\t</span>',n=t.querySelector(".searchinput"),n.style.width="240px",n.style.fontSize="14px",n.style.padding="4px 6px",n.style.color="#000",n.style.background="#fff",n.style.borderRadius="2px",n.style.border="0",n.style.outline="0",n.style.boxShadow="0 2px 18px rgba(0, 0, 0, 0.2)",n.style["-webkit-appearance"]="none",e.getRevealElement().appendChild(t),n.addEventListener("keyup",(function(t){if(13===t.keyCode)t.preventDefault(),function(){if(o){var t=n.value;""===t?(r&&r.remove(),l=null):(r=new c("slidecontent"),l=r.apply(t),i=0)}l&&(l.length&&l.length<=i&&(i=0),l.length>i&&(e.slide(l[i].h,l[i].v),i++))}(),o=!1;else o=!0}),!1),d()}function a(){t||s(),t.style.display="inline",n.focus(),n.select()}function d(){t||s(),t.style.display="none",r&&r.remove()}function c(t,n){var l=document.getElementById(t)||document.body,i=n||"EM",o=new RegExp("^(?:"+i+"|SCRIPT|FORM)$"),r=["#ff6","#a0ffff","#9f9","#f99","#f6f"],s=[],a=0,d="",c=[];this.setRegex=function(e){e=e.replace(/^[^\w]+|[^\w]+$/g,"").replace(/[^\w'-]+/g,"|"),d=new RegExp("("+e+")","i")},this.getRegex=function(){return d.toString().replace(/^\/\\b\(|\)\\b\/i$/g,"").replace(/\|/g," ")},this.hiliteWords=function(t){if(null!=t&&t&&d&&!o.test(t.nodeName)){if(t.hasChildNodes())for(var n=0;n<t.childNodes.length;n++)this.hiliteWords(t.childNodes[n]);var l,p;if(3==t.nodeType)if((l=t.nodeValue)&&(p=d.exec(l))){for(var u=t;null!=u&&"SECTION"!=u.nodeName;)u=u.parentNode;var h=e.getIndices(u),f=c.length,y=!1;for(n=0;n<f;n++)c[n].h===h.h&&c[n].v===h.v&&(y=!0);y||c.push(h),s[p[0].toLowerCase()]||(s[p[0].toLowerCase()]=r[a++%r.length]);var g=document.createElement(i);g.appendChild(document.createTextNode(p[0])),g.style.backgroundColor=s[p[0].toLowerCase()],g.style.fontStyle="inherit",g.style.color="#000";var v=t.splitText(p.index);v.nodeValue=v.nodeValue.substring(p[0].length),t.parentNode.insertBefore(g,v)}}},this.remove=function(){for(var e,t=document.getElementsByTagName(i);t.length&&(e=t[0]);)e.parentNode.replaceChild(e.firstChild,e)},this.apply=function(e){if(null!=e&&e)return this.remove(),this.setRegex(e),this.hiliteWords(l),c}}return{id:"search",init:n=>{e=n,e.registerKeyboardShortcut("CTRL + Shift + F","Search"),document.addEventListener("keydown",(function(e){"F"==e.key&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),t||s(),"inline"!==t.style.display?a():d())}),!1)},open:a}}; const e=()=>{let e,t,n,l,o,i,r;function s(){t=document.createElement("div"),t.classList.add("searchbox"),t.style.position="absolute",t.style.top="10px",t.style.right="10px",t.style.zIndex=10,t.innerHTML='<input type="search" class="searchinput" placeholder="Search..." style="vertical-align: top;"/>\n\t\t</span>',n=t.querySelector(".searchinput"),n.style.width="240px",n.style.fontSize="14px",n.style.padding="4px 6px",n.style.color="#000",n.style.background="#fff",n.style.borderRadius="2px",n.style.border="0",n.style.outline="0",n.style.boxShadow="0 2px 18px rgba(0, 0, 0, 0.2)",n.style["-webkit-appearance"]="none",e.getRevealElement().appendChild(t),n.addEventListener("keyup",(function(t){if(13===t.keyCode)t.preventDefault(),function(){if(i){var t=n.value;""===t?(r&&r.remove(),l=null):(r=new c("slidecontent"),l=r.apply(t),o=0)}l&&(l.length&&l.length<=o&&(o=0),l.length>o&&(e.slide(l[o].h,l[o].v),o++))}(),i=!1;else i=!0}),!1),d()}function a(){t||s(),t.style.display="inline",n.focus(),n.select()}function d(){t||s(),t.style.display="none",r&&r.remove()}function c(t,n){var l=document.getElementById(t)||document.body,o=n||"EM",i=new RegExp("^(?:"+o+"|SCRIPT|FORM)$"),r=["#ff6","#a0ffff","#9f9","#f99","#f6f"],s=[],a=0,d="",c=[];this.setRegex=function(e){e=e.replace(/^[^\w]+|[^\w]+$/g,"").replace(/[^\w'-]+/g,"|"),d=new RegExp("("+e+")","i")},this.getRegex=function(){return d.toString().replace(/^\/\\b\(|\)\\b\/i$/g,"").replace(/\|/g," ")},this.hiliteWords=function(t){if(null!=t&&t&&d&&!i.test(t.nodeName)){if(t.hasChildNodes())for(var n=0;n<t.childNodes.length;n++)this.hiliteWords(t.childNodes[n]);var l,p;if(3==t.nodeType)if((l=t.nodeValue)&&(p=d.exec(l))){for(var u=t;null!=u&&"SECTION"!=u.nodeName;)u=u.parentNode;var h=e.getIndices(u),f=c.length,y=!1;for(n=0;n<f;n++)c[n].h===h.h&&c[n].v===h.v&&(y=!0);y||c.push(h),s[p[0].toLowerCase()]||(s[p[0].toLowerCase()]=r[a++%r.length]);var g=document.createElement(o);g.appendChild(document.createTextNode(p[0])),g.style.backgroundColor=s[p[0].toLowerCase()],g.style.fontStyle="inherit",g.style.color="#000";var v=t.splitText(p.index);v.nodeValue=v.nodeValue.substring(p[0].length),t.parentNode.insertBefore(g,v)}}},this.remove=function(){for(var e,t=document.getElementsByTagName(o);t.length&&(e=t[0]);)e.parentNode.replaceChild(e.firstChild,e)},this.apply=function(e){if(null!=e&&e)return this.remove(),this.setRegex(e),this.hiliteWords(l),c}}return{id:"search",init:n=>{e=n,e.registerKeyboardShortcut("CTRL + Shift + F","Search"),document.addEventListener("keydown",(function(e){"F"==e.key&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),t||s(),"inline"!==t.style.display?a():d())}),!1)},open:a}};export{e as default};
+2 -2
View File
@@ -1,11 +1,11 @@
/*! /*!
* reveal.js Zoom plugin * reveal.js Zoom plugin
*/ */
const e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(o){var n=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:n)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;o[i]&&!e.isOverview()&&(o.preventDefault(),t.to({x:o.clientX,y:o.clientY,scale:d,pan:!1}))}))},destroy:()=>{t.reset()}};var t=function(){var e=1,o=0,n=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,o){var n=r();if(t.width=t.width||1,t.height=t.height||1,t.x-=(window.innerWidth-t.width*o)/2,t.y-=(window.innerHeight-t.height*o)/2,l)if(1===o)document.body.style.transform="";else{var i=n.x+"px "+n.y+"px",d="translate("+-t.x+"px,"+-t.y+"px) scale("+o+")";document.body.style.transformOrigin=i,document.body.style.transform=d}else 1===o?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(n.x+t.x)/o+"px",document.body.style.top=-(n.y+t.y)/o+"px",document.body.style.width=100*o+"%",document.body.style.height=100*o+"%",document.body.style.zoom=o);e=o,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function c(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=r();n<i?window.scroll(d.x,d.y-14/e*(1-n/i)):n>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),o<t?window.scroll(d.x-14/e*(1-o/t),d.y):o>window.innerWidth-t&&window.scroll(d.x+(1-(window.innerWidth-o)/t)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="transform 0.8s ease"),document.addEventListener("keyup",(function(o){1!==e&&27===o.keyCode&&t.out()})),document.addEventListener("mousemove",(function(t){1!==e&&(o=t.clientX,n=t.clientY)})),{to:function(o){if(1!==e)t.out();else{if(o.x=o.x||0,o.y=o.y||0,o.element){var n=o.element.getBoundingClientRect();o.x=n.left-20,o.y=n.top-20,o.width=n.width+40,o.height=n.height+40}void 0!==o.width&&void 0!==o.height&&(o.scale=Math.max(Math.min(window.innerWidth/o.width,window.innerHeight/o.height),1)),o.scale>1&&(o.x*=o.scale,o.y*=o.scale,s(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}(); const e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(t){var n=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:n)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;t[i]&&!e.isOverview()&&(t.preventDefault(),o.to({x:t.clientX,y:t.clientY,scale:d,pan:!1}))}))},destroy:()=>{o.reset()}};var t=()=>e,o=function(){var e=1,t=0,n=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,o){var n=r();if(t.width=t.width||1,t.height=t.height||1,t.x-=(window.innerWidth-t.width*o)/2,t.y-=(window.innerHeight-t.height*o)/2,l)if(1===o)document.body.style.transform="";else{var i=n.x+"px "+n.y+"px",d="translate("+-t.x+"px,"+-t.y+"px) scale("+o+")";document.body.style.transformOrigin=i,document.body.style.transform=d}else 1===o?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(n.x+t.x)/o+"px",document.body.style.top=-(n.y+t.y)/o+"px",document.body.style.width=100*o+"%",document.body.style.height=100*o+"%",document.body.style.zoom=o);e=o,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function c(){var o=.12*window.innerWidth,i=.12*window.innerHeight,d=r();n<i?window.scroll(d.x,d.y-14/e*(1-n/i)):n>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),t<o?window.scroll(d.x-14/e*(1-t/o),d.y):t>window.innerWidth-o&&window.scroll(d.x+(1-(window.innerWidth-t)/o)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="transform 0.8s ease"),document.addEventListener("keyup",(function(t){1!==e&&27===t.keyCode&&o.out()})),document.addEventListener("mousemove",(function(o){1!==e&&(t=o.clientX,n=o.clientY)})),{to:function(t){if(1!==e)o.out();else{if(t.x=t.x||0,t.y=t.y||0,t.element){var n=t.element.getBoundingClientRect();t.x=n.left-20,t.y=n.top-20,t.width=n.width+40,t.height=n.height+40}void 0!==t.width&&void 0!==t.height&&(t.scale=Math.max(Math.min(window.innerWidth/t.width,window.innerHeight/t.height),1)),t.scale>1&&(t.x*=t.scale,t.y*=t.scale,s(t,t.scale),!1!==t.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}();
/*! /*!
* zoom.js 0.3 (modified for use with reveal.js) * zoom.js 0.3 (modified for use with reveal.js)
* http://lab.hakim.se/zoom-js * http://lab.hakim.se/zoom-js
* MIT licensed * MIT licensed
* *
* Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
*/export default()=>e; */export{t as default};
+115
View File
@@ -0,0 +1,115 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js - Test Scroll View</title>
<link rel="stylesheet" href="../dist/reveal.css">
<link rel="stylesheet" href="../node_modules/qunit/qunit/qunit.css">
<script src="../node_modules/qunit/qunit/qunit.js"></script>
</head>
<body style="overflow: auto;">
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<div class="reveal" style="opacity: 0; pointer-events: none;">
<div class="slides">
<section>
<h1>slide 1</h1>
</section>
<section>
<h1>slide 2</h1>
</section>
<section>
<h1>slide 3</h1>
<p class="fragment">fragment 1</p>
<p class="fragment">fragment 2</p>
<p class="fragment">fragment 3</p>
</section>
<section>
<h1>slide 4</h1>
</section>
</div>
</div>
<script src="../dist/reveal.js"></script>
<script>
QUnit.config.testTimeout = 30000;
QUnit.config.reorder = false;
function getScrollHeight() {
return Reveal.getViewportElement().scrollHeight;
}
function getViewportHeight() {
return Reveal.getViewportElement().offsetHeight;
}
Reveal.initialize({ view: 'scroll' }).then( async () => {
QUnit.module( 'Scroll View' );
QUnit.test( 'Activates', assert => {
assert.ok( getScrollHeight() > getViewportHeight(), 'Is overflowing' );
});
QUnit.test( 'Can be toggled via API', assert => {
Reveal.toggleScrollView( false );
assert.ok( getScrollHeight() <= getViewportHeight(), 'Is not overflowing' );
Reveal.toggleScrollView( true );
assert.ok( getScrollHeight() > getViewportHeight(), 'Is overflowing' );
});
QUnit.test( 'Changes present slide when scrolling', assert => {
assert.timeout( 200 );
assert.expect( 2 );
const slides = document.querySelectorAll( '.reveal .slides section' );
assert.ok( slides[0].classList.contains( 'present' ), 'First slide is present' );
Reveal.getViewportElement().scrollTop = getViewportHeight() * 1;
return new Promise( resolve => {
setTimeout(() => {
assert.ok( slides[1].classList.contains( 'present' ), 'Second slide is present' );
resolve();
}, 100);
} );
});
QUnit.test( 'Fires slideschanged event when scrolling', assert => {
assert.timeout( 200 );
assert.expect( 2 );
const slides = document.querySelectorAll( '.reveal .slides section' );
return new Promise( resolve => {
let callback = ( event ) => {
Reveal.off( 'slidechanged', callback );
assert.ok( true, 'slidechanged event fired' );
assert.ok( event.currentSlide.classList.contains( 'present' ), 'slidechanged provides reference to currentSlide' );
resolve();
}
Reveal.on( 'slidechanged', callback );
Reveal.getViewportElement().scrollTop = getViewportHeight() * 2;
});
});
} );
</script>
</body>
</html>