Permalink
739 lines (652 sloc) 19 KB
<!DOCTYPE html>
<meta charset="utf-8">
<title>The Title Of Your Presentation</title>
<!-- Optional: on every page: header and footer -->
<header>
Hi, I'm a header
</header>
<footer>by John Doe</footer>
<!-- Your Slides -->
<!-- One section is one slide -->
<section>
<!-- This is the first slide -->
<h1>My Presentation</h1>
<footer>by John Doe</footer>
</section>
<section>
<p>Some random text: But I've never been to the moon! You can see how I lived before I met you. Also Zoidberg.
I could if you hadn't turned on the light and shut off my stereo.</p>
</section>
<section>
<h3>An incremental list</h3>
<ul>
<li class="next">Item 1
<li class="next">Item 2
<li class="next">Item 3
<ul>
<li class="next"> Item 3.1
<li class="next"> Item 3.2
</ul>
</ul>
<div role="note">Some notes. They are only visible using onstage shell.</div>
</section>
<section>
<h3>More incrementals</h3>
<p class="next">Not only list elements can appear incrementally</p>
<p><mark class="next">Styles</mark> can be incremental
<mark class="next">too</mark></p>
</section>
<section>
<h3>Even more incrementals</h3>
<p>
<span class="next" next-order="3">They</span>
<span class="next" next-order="5">can</span>
<span class="next" next-order="2">even</span>
<span class="next" next-order="1">appear</span>
<span class="next" next-order="7">in</span>
<span class="next" next-order="4">any</span>
<span class="next" next-order="6">order</span>
<span class="next" next-order="8">!</span>
</p>
</section>
<section>
<blockquote>
Who's brave enough to fly into something we all keep calling a death sphere?
</blockquote>
<details>
<p>In the onstage shell, notes scroll rather than overflow:</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac dui eu est feugiat lacinia sit amet nec leo. Mauris eu ipsum leo. Nulla mi odio, cursus sed sollicitudin non, fringilla id magna. Suspendisse sit amet posuere elit. Maecenas iaculis, turpis a placerat imperdiet, libero lorem feugiat nisi, nec tincidunt diam nibh sit amet massa. Vestibulum quis adipiscing tellus. Maecenas sollicitudin sodales pulvinar. Donec dui ipsum, bibendum facilisis consequat interdum, tempus ut mauris. Aliquam ut dolor nec odio scelerisque bibendum quis in neque. Aliquam dui dui, pulvinar quis fermentum quis, gravida eu augue. Nunc tristique dolor a urna pulvinar bibendum. Curabitur mollis cursus neque, in scelerisque metus porta non. Donec tempor enim in nibh vestibulum et convallis nisi malesuada. Duis ut lectus sed metus venenatis porttitor id pharetra quam. Suspendisse sapien turpis, ornare in molestie et, gravida eget turpis.
</p>
</details>
</section>
<section>
<h1>Part two</h1>
</section>
<section>
<figure> <!-- Figures are used to display images and videos fullpage -->
<img src="http://placekitten.com/g/800/600">
<figcaption>An image</figcaption>
</figure>
<div role="note">Kittens are so cute!</div>
</section>
<section>
<figure> <!-- Videos are automatically played -->
<video src="http://videos.cdn.mozilla.net/brand/Mozilla_Firefox_Manifesto_v0.2_640.webm" poster="http://www.mozilla.org/images/about/poster.jpg"></video>
<figcaption>A video</figcaption>
</figure>
</section>
<section>
<h1>End!</h1>
</section>
<!-- Your Style -->
<!-- Define the style of your presentation -->
<!-- Maybe a font from http://www.google.com/webfonts ? -->
<link href='http://fonts.googleapis.com/css?family=Oswald' rel='stylesheet'>
<style>
html, .view body { background-color: black; counter-reset: slideidx; }
body, .view section {
background-color: white; border-radius: 12px;
font-family: 'Oswald', arial, serif;
}
section, .view head > title {
font-size: 2rem;
}
.view section:after {
counter-increment: slideidx;
content: counter(slideidx, decimal-leading-zero);
position: absolute; bottom: -80px; right: 100px;
color: white;
}
.view head > title {
color: white;
text-align: center;
margin: 1em 0 1em 0;
}
h1 {
margin: 120px 0 30px 0;
text-align: center;
font-size: 5rem;
}
h2 {
text-align: center;
}
section > h3 {
margin: 50px 50px 40px 50px;
border-bottom: 0.1px solid;
}
pre {
overflow: hidden;
font-size: 1.25rem;
margin: 0 75px 0 75px;
padding: 10px;
border: 1px solid;
font-weight: bold;
background-color: #F7F7F7;
width:80%
}
ul, ol {
margin: 40px 100px 0 100px;
}
li > ul, ol {
margin: 0 0 15px 50px;
list-style-image: none; /* in case parent list has some */
}
mark.next:not([active]) {
visibility: visible; /* override the default behavior where next is hidden */
background-color: inherit; /* and disable highlighting instead */
}
p {
margin: 75px 75px 0 75px;
font-size: 3rem;
}
table {
margin: auto;
font-size:2.5rem;
text-align: center;
}
blockquote {
height: 100%;
background-color: black;
color: white;
font-size: 3.75rem;
padding: 50px;
}
blockquote:before {
content: open-quote;
}
blockquote:after {
content: close-quote;
}
/* Figures are displayed full-page, with the caption
on top of the image/video */
figure {
background-color: black;
width: 100%;
height: 100%;
}
figure > * {
position: absolute;
}
figure > img, figure > video {
width: 100%; height: 100%;
}
figcaption {
margin: 70px;
font-size: 3rem;
}
header {
background-color: #F3F4F8;
border-bottom: 1px solid #CCC;
}
footer {
background-color: #F3F4F8;
border-top: 1px solid #CCC;
padding-bottom: 4px; /* remember progress bar */
}
section footer {
padding: 10px;
}
/* Transition effect */
/* Feel free to change the transition effect for original
animations. See here:
https://developer.mozilla.org/en/CSS/CSS_transitions
How to use CSS3 Transitions: */
section {
transition: left 400ms linear 0s;
}
.view section {
transition: none;
}
.view section[aria-selected] {
border: 5px red solid;
}
@media screen {
/* Before */
section { left: -150%; }
/* Now */
section[aria-selected] { left: 0; }
/* After */
section[aria-selected] ~ section { left: +150%; }
}
/* The progressbar, at the bottom of the slides, show the global
progress of the presentation. */
#progress-bar {
height: 4px;
background: #AAA;
}
</style>
<!-- {{{{ dzslides core
#
#
# __ __ __ . __ ___ __
# | \ / /__` | | | \ |__ /__`
# |__/ /_ .__/ |___ | |__/ |___ .__/ core :€
#
#
# The following block of code is not supposed to be edited.
# But if you want to change the behavior of these slides,
# feel free to hack it!
#
-->
<div id="progress-bar"></div>
<!-- Default Style -->
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
[role="note"] { display: none; }
html {
font-size: 16px;
}
body {
width: 800px; height: 600px;
position: absolute; top: 50%; left: 50%;
overflow: hidden;
display: none;
}
.view body {
position: static;
margin: 0; padding: 0;
width: 100%; height: 100%;
display: inline-block;
overflow: visible; overflow-x: hidden;
/* undo Dz.onresize */
transform: none !important;
}
.view head, .view head > title { display: block }
section {
position: absolute;
pointer-events: none;
width: 100%; height: 100%;
}
.view section {
pointer-events: auto;
position: static;
width: 800px; height: 600px;
margin: -150px -200px;
float: left;
transform: scale(.4);
}
.view section > * { pointer-events: none; }
section[aria-selected] { pointer-events: auto; }
html { overflow: hidden; }
html.view { overflow: visible; }
body.loaded { display: block; }
.next:not([active]) {visibility: hidden; }
#progress-bar{
bottom: 0;
position: absolute;
transition: width 400ms linear 0s;
}
.view #progress-bar {
display: none;
}
header {
text-align: right;
position: absolute;
top: 0;
width: 100%;
}
footer {
text-align: right;
position: absolute;
bottom: 0;
width: 100%;
}
.view header { display: none; }
.view footer { display: none; }
@media print {
section {
transition: none;
transform: none;
position: static;
page-break-inside: avoid;
}
body { overflow: visible; }
#progress-bar{ display:none; }
}
/*
**************************************
Uncomment the following for 16:9 slides
**************************************
html { font-size: 12px; }
body { height: 450px; }
.view section {
height: 450px;
margin: -140px -200px;
transform: scale(.3);
}
*/
</style>
<script>
var Dz = {
remoteWindows: [],
idx: -1,
step: 0,
html: null,
slides: null,
progressBar : null,
params: {
autoplay: "1"
}
};
Dz.init = function() {
document.body.className = "loaded";
this.slides = Array.prototype.slice.call($$("body > section"));
this.progressBar = $("#progress-bar");
this.html = document.body.parentNode;
this.setupParams();
this.onhashchange();
this.setupTouchEvents();
this.onresize();
this.setupView();
}
Dz.setupParams = function() {
var p = window.location.search.substr(1).split('&');
p.forEach(function(e, i, a) {
var keyVal = e.split('=');
Dz.params[keyVal[0]] = decodeURIComponent(keyVal[1]);
});
// Specific params handling
if (!+this.params.autoplay)
$$.forEach($$("video"), function(v){ v.controls = true });
}
Dz.onkeydown = function(aEvent) {
// Don't intercept keyboard shortcuts
if (aEvent.altKey
|| aEvent.ctrlKey
|| aEvent.metaKey
|| aEvent.shiftKey) {
return;
}
if ( aEvent.keyCode == 37 // left arrow
|| aEvent.keyCode == 38 // up arrow
|| aEvent.keyCode == 33 // page up
) {
aEvent.preventDefault();
this.back();
}
if ( aEvent.keyCode == 39 // right arrow
|| aEvent.keyCode == 40 // down arrow
|| aEvent.keyCode == 34 // page down
) {
aEvent.preventDefault();
this.forward();
}
if (aEvent.keyCode == 35) { // end
aEvent.preventDefault();
this.goEnd();
}
if (aEvent.keyCode == 36) { // home
aEvent.preventDefault();
this.goStart();
}
if (aEvent.keyCode == 32) { // space
aEvent.preventDefault();
this.toggleContent();
}
if (aEvent.keyCode == 70) { // f
aEvent.preventDefault();
this.goFullscreen();
}
if (aEvent.keyCode == 79 //o
|| aEvent.keyCode == 27 //Esc
) {
aEvent.preventDefault();
this.toggleView();
}
}
/* Touch Events */
Dz.setupTouchEvents = function() {
var orgX, newX;
var tracking = false;
var db = document.body;
db.addEventListener("touchstart", start.bind(this), false);
db.addEventListener("touchmove", move.bind(this), false);
function start(aEvent) {
aEvent.preventDefault();
tracking = true;
orgX = aEvent.changedTouches[0].pageX;
}
function move(aEvent) {
if (!tracking) return;
newX = aEvent.changedTouches[0].pageX;
if (orgX - newX > 100) {
tracking = false;
this.forward();
} else {
if (orgX - newX < -100) {
tracking = false;
this.back();
}
}
}
}
Dz.setupView = function() {
document.body.addEventListener("click", function ( e ) {
if (!Dz.html.classList.contains("view")) return;
if (!e.target || e.target.nodeName != "SECTION") return;
Dz.html.classList.remove("view");
Dz.setCursor(Dz.slides.indexOf(e.target) + 1);
}, false);
}
/* Adapt the size of the slides to the window */
Dz.onresize = function() {
var db = document.body;
var sx = db.clientWidth / window.innerWidth;
var sy = db.clientHeight / window.innerHeight;
var transform = "scale(" + (1/Math.max(sx, sy)) + ")";
db.style.transform = transform;
db.style.marginTop = -db.clientHeight / 2 + "px";
db.style.marginLeft = -db.clientWidth / 2 + "px";
}
Dz.getNotes = function(aIdx) {
var s = $("section:nth-of-type(" + aIdx + ")");
var d = s.$("[role='note']");
return d ? d.innerHTML : "";
}
Dz.onmessage = function(aEvent) {
var argv = aEvent.data.split(" "), argc = argv.length;
argv.forEach(function(e, i, a) { a[i] = decodeURIComponent(e) });
var win = aEvent.source;
if (argv[0] === "REGISTER" && argc === 1) {
this.remoteWindows.push(win);
this.postMsg(win, "REGISTERED", document.title, this.slides.length);
this.postMsg(win, "CURSOR", this.idx + "." + this.step);
return;
}
if (argv[0] === "BACK" && argc === 1)
this.back();
if (argv[0] === "FORWARD" && argc === 1)
this.forward();
if (argv[0] === "START" && argc === 1)
this.goStart();
if (argv[0] === "END" && argc === 1)
this.goEnd();
if (argv[0] === "TOGGLE_CONTENT" && argc === 1)
this.toggleContent();
if (argv[0] === "SET_CURSOR" && argc === 2)
window.location.hash = "#" + argv[1];
if (argv[0] === "GET_CURSOR" && argc === 1)
this.postMsg(win, "CURSOR", this.idx + "." + this.step);
if (argv[0] === "GET_NOTES" && argc === 1)
this.postMsg(win, "NOTES", this.getNotes(this.idx));
}
Dz.toggleContent = function() {
// If a Video is present in this new slide, play it.
// If a Video is present in the previous slide, stop it.
var s = $("section[aria-selected]");
if (s) {
var video = s.$("video");
if (video) {
if (video.ended || video.paused) {
video.play();
} else {
video.pause();
}
}
}
}
Dz.setCursor = function(aIdx, aStep) {
// If the user change the slide number in the URL bar, jump
// to this slide.
aStep = (aStep != 0 && typeof aStep !== "undefined") ? "." + aStep : ".0";
window.location.hash = "#" + aIdx + aStep;
}
Dz.onhashchange = function() {
var cursor = window.location.hash.split("#"),
newidx = 1,
newstep = 0;
if (cursor.length == 2) {
newidx = ~~cursor[1].split(".")[0];
newstep = ~~cursor[1].split(".")[1];
if (newstep > Dz.slides[newidx - 1].$$('.next').length) {
newstep = 0;
newidx++;
}
}
this.setProgress(newidx, newstep);
if (newidx != this.idx) {
this.setSlide(newidx);
}
if (newstep != this.step) {
this.setIncremental(newstep);
}
for (var i = 0; i < this.remoteWindows.length; i++) {
this.postMsg(this.remoteWindows[i], "CURSOR", this.idx + "." + this.step);
}
}
Dz.back = function() {
if (this.idx == 1) {
return;
}
this.setCursor(this.idx - 1,
this.slides[this.idx - 2].$$('.next[active]').length);
}
Dz.forward = function() {
if (this.idx >= this.slides.length &&
this.step >= this.slides[this.idx - 1].$$('.next').length) {
return;
}
if (this.html.classList.contains("view") ||
this.step >= this.slides[this.idx - 1].$$('.next').length) {
this.setCursor(this.idx + 1,
this.slides[this.idx].$$('.next[active]').length);
} else {
this.setCursor(this.idx, this.step + 1);
}
}
Dz.goStart = function() {
this.setCursor(1, 0);
}
Dz.goEnd = function() {
var lastIdx = this.slides.length;
var lastStep = this.slides[lastIdx - 1].$$('.next').length;
this.setCursor(lastIdx, lastStep);
}
Dz.toggleView = function() {
this.html.classList.toggle("view");
if (this.html.classList.contains("view")) {
$("section[aria-selected]").scrollIntoView(true);
}
}
Dz.setSlide = function(aIdx) {
this.idx = aIdx;
var old = $("section[aria-selected]");
var next = $("section:nth-of-type("+ this.idx +")");
if (old) {
old.removeAttribute("aria-selected");
var video = old.$("video");
if (video) {
video.pause();
}
}
if (next) {
next.setAttribute("aria-selected", "true");
if (this.html.classList.contains("view")) {
next.scrollIntoView();
} else {
var video = next.$("video");
if (video && !!+this.params.autoplay) {
video.play();
}
}
} else {
// That should not happen
this.idx = -1;
// console.warn("Slide doesn't exist.");
}
}
Dz.setIncremental = function(aStep) {
this.step = aStep;
var incrementals = Array.prototype.slice.call(this.slides[this.idx - 1].$$('.next')).sort(function(a, b) {
return Number(a.getAttribute('next-order')) - Number(b.getAttribute('next-order'));
});
var next = incrementals[this.step - 1];
if (next) {
next.setAttribute('active', true);
} else {
this.setCursor(this.idx, 0);
}
return next;
}
Dz.goFullscreen = function() {
var html = $('html'),
requestFullscreen = html.requestFullscreen || html.requestFullScreen || html.mozRequestFullScreen || html.webkitRequestFullScreen;
if (requestFullscreen) {
requestFullscreen.apply(html);
}
}
Dz.setProgress = function(aIdx, aStep) {
var slide = $("section:nth-of-type("+ aIdx +")");
if (!slide)
return;
var steps = slide.$$('.next').length + 1,
slideSize = 100 / (this.slides.length - 1),
stepSize = slideSize / steps;
this.progressBar.style.width = ((aIdx - 1) * slideSize + aStep * stepSize) + '%';
}
Dz.postMsg = function(aWin, aMsg) { // [arg0, [arg1...]]
aMsg = [aMsg];
for (var i = 2; i < arguments.length; i++)
aMsg.push(encodeURIComponent(arguments[i]));
aWin.postMessage(aMsg.join(" "), "*");
}
function init() {
Dz.init();
window.onkeydown = Dz.onkeydown.bind(Dz);
window.onresize = Dz.onresize.bind(Dz);
window.onhashchange = Dz.onhashchange.bind(Dz);
window.onmessage = Dz.onmessage.bind(Dz);
}
window.onload = init;
// Helpers
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
// closest thing possible to the ECMAScript 5 internal IsCallable
// function
if (typeof this !== "function")
throw new TypeError(
"Function.prototype.bind - what is trying to be fBound is not callable"
);
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply( this instanceof fNOP ? this : oThis || window,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
var $ = (HTMLElement.prototype.$ = function(aQuery) {
return this.querySelector(aQuery);
}).bind(document);
var $$ = (HTMLElement.prototype.$$ = function(aQuery) {
return this.querySelectorAll(aQuery);
}).bind(document);
$$.forEach = function(nodeList, fun) {
Array.prototype.forEach.call(nodeList, fun);
}
</script>
<!-- vim: set fdm=marker: }}} -->