aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Loomans <noahloomans@gmail.com>2017-05-10 15:31:30 +0200
committerNoah Loomans <noahloomans@gmail.com>2017-05-10 15:31:30 +0200
commit212124e022e68f8c03bfe24bdf08787404126c8c (patch)
tree6bd4f47b881236ee9bfc5a09aa5d746ea7aa9b19
parent6cbf4d867d840014fbbb646e04002395fcec1fb0 (diff)
Add ICT in de Wolken presentation
-rw-r--r--_layouts/slides.html19
-rw-r--r--slides/reveal.js/reveal.css1365
-rw-r--r--slides/reveal.js/reveal.js4961
-rw-r--r--slides/reveal.js/theme/blood.css315
-rw-r--r--slides/reveal.js/zenburn.css80
-rw-r--r--slides/security/6char-words.txt1494
-rw-r--r--slides/security/8char-words.txt1162
-rw-r--r--slides/security/index.html24
-rw-r--r--slides/security/more-then-6char-words.txt6359
-rw-r--r--slides/security/script.js22
-rw-r--r--slides/security/style.css31
-rw-r--r--slides/xss/index.html79
-rw-r--r--slides/xss/script.js6
-rw-r--r--slides/xss/style.css26
14 files changed, 15943 insertions, 0 deletions
diff --git a/_layouts/slides.html b/_layouts/slides.html
new file mode 100644
index 0000000..db2243a
--- /dev/null
+++ b/_layouts/slides.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>{{ page.title }}</title>
+ <link rel="stylesheet" href="/slides/reveal.js/reveal.css">
+ <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
+ {% for style in page.styles %}
+ <link rel="stylesheet" href="{{ style }}">
+ {% endfor %}
+ </head>
+ <body>
+ {{ content }}
+ <script src="/slides/reveal.js/reveal.js"></script>
+ {% for script in page.scripts %}
+ <script src="{{ script }}"></script>
+ {% endfor %}
+ </body>
+</html>
diff --git a/slides/reveal.js/reveal.css b/slides/reveal.js/reveal.css
new file mode 100644
index 0000000..430dcde
--- /dev/null
+++ b/slides/reveal.js/reveal.css
@@ -0,0 +1,1365 @@
+/*!
+ * reveal.js
+ * http://lab.hakim.se/reveal-js
+ * MIT licensed
+ *
+ * Copyright (C) 2016 Hakim El Hattab, http://hakim.se
+ */
+/*********************************************
+ * RESET STYLES
+ *********************************************/
+html, body, .reveal div, .reveal span, .reveal applet, .reveal object, .reveal iframe,
+.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .reveal p, .reveal blockquote, .reveal pre,
+.reveal a, .reveal abbr, .reveal acronym, .reveal address, .reveal big, .reveal cite, .reveal code,
+.reveal del, .reveal dfn, .reveal em, .reveal img, .reveal ins, .reveal kbd, .reveal q, .reveal s, .reveal samp,
+.reveal small, .reveal strike, .reveal strong, .reveal sub, .reveal sup, .reveal tt, .reveal var,
+.reveal b, .reveal u, .reveal center,
+.reveal dl, .reveal dt, .reveal dd, .reveal ol, .reveal ul, .reveal li,
+.reveal fieldset, .reveal form, .reveal label, .reveal legend,
+.reveal table, .reveal caption, .reveal tbody, .reveal tfoot, .reveal thead, .reveal tr, .reveal th, .reveal td,
+.reveal article, .reveal aside, .reveal canvas, .reveal details, .reveal embed,
+.reveal figure, .reveal figcaption, .reveal footer, .reveal header, .reveal hgroup,
+.reveal menu, .reveal nav, .reveal output, .reveal ruby, .reveal section, .reveal summary,
+.reveal time, .reveal mark, .reveal audio, .reveal video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline; }
+
+.reveal article, .reveal aside, .reveal details, .reveal figcaption, .reveal figure,
+.reveal footer, .reveal header, .reveal hgroup, .reveal menu, .reveal nav, .reveal section {
+ display: block; }
+
+/*********************************************
+ * GLOBAL STYLES
+ *********************************************/
+html,
+body {
+ width: 100%;
+ height: 100%;
+ overflow: hidden; }
+
+body {
+ position: relative;
+ line-height: 1;
+ background-color: #fff;
+ color: #000; }
+
+/*********************************************
+ * VIEW FRAGMENTS
+ *********************************************/
+.reveal .slides section .fragment {
+ opacity: 0;
+ visibility: hidden;
+ -webkit-transition: all .2s ease;
+ transition: all .2s ease; }
+ .reveal .slides section .fragment.visible {
+ opacity: 1;
+ visibility: inherit; }
+
+.reveal .slides section .fragment.grow {
+ opacity: 1;
+ visibility: inherit; }
+ .reveal .slides section .fragment.grow.visible {
+ -webkit-transform: scale(1.3);
+ transform: scale(1.3); }
+
+.reveal .slides section .fragment.shrink {
+ opacity: 1;
+ visibility: inherit; }
+ .reveal .slides section .fragment.shrink.visible {
+ -webkit-transform: scale(0.7);
+ transform: scale(0.7); }
+
+.reveal .slides section .fragment.zoom-in {
+ -webkit-transform: scale(0.1);
+ transform: scale(0.1); }
+ .reveal .slides section .fragment.zoom-in.visible {
+ -webkit-transform: none;
+ transform: none; }
+
+.reveal .slides section .fragment.fade-out {
+ opacity: 1;
+ visibility: inherit; }
+ .reveal .slides section .fragment.fade-out.visible {
+ opacity: 0;
+ visibility: hidden; }
+
+.reveal .slides section .fragment.semi-fade-out {
+ opacity: 1;
+ visibility: inherit; }
+ .reveal .slides section .fragment.semi-fade-out.visible {
+ opacity: 0.5;
+ visibility: inherit; }
+
+.reveal .slides section .fragment.strike {
+ opacity: 1;
+ visibility: inherit; }
+ .reveal .slides section .fragment.strike.visible {
+ text-decoration: line-through; }
+
+.reveal .slides section .fragment.fade-up {
+ -webkit-transform: translate(0, 20%);
+ transform: translate(0, 20%); }
+ .reveal .slides section .fragment.fade-up.visible {
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0); }
+
+.reveal .slides section .fragment.fade-down {
+ -webkit-transform: translate(0, -20%);
+ transform: translate(0, -20%); }
+ .reveal .slides section .fragment.fade-down.visible {
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0); }
+
+.reveal .slides section .fragment.fade-right {
+ -webkit-transform: translate(-20%, 0);
+ transform: translate(-20%, 0); }
+ .reveal .slides section .fragment.fade-right.visible {
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0); }
+
+.reveal .slides section .fragment.fade-left {
+ -webkit-transform: translate(20%, 0);
+ transform: translate(20%, 0); }
+ .reveal .slides section .fragment.fade-left.visible {
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0); }
+
+.reveal .slides section .fragment.current-visible {
+ opacity: 0;
+ visibility: hidden; }
+ .reveal .slides section .fragment.current-visible.current-fragment {
+ opacity: 1;
+ visibility: inherit; }
+
+.reveal .slides section .fragment.highlight-red,
+.reveal .slides section .fragment.highlight-current-red,
+.reveal .slides section .fragment.highlight-green,
+.reveal .slides section .fragment.highlight-current-green,
+.reveal .slides section .fragment.highlight-blue,
+.reveal .slides section .fragment.highlight-current-blue {
+ opacity: 1;
+ visibility: inherit; }
+
+.reveal .slides section .fragment.highlight-red.visible {
+ color: #ff2c2d; }
+
+.reveal .slides section .fragment.highlight-green.visible {
+ color: #17ff2e; }
+
+.reveal .slides section .fragment.highlight-blue.visible {
+ color: #1b91ff; }
+
+.reveal .slides section .fragment.highlight-current-red.current-fragment {
+ color: #ff2c2d; }
+
+.reveal .slides section .fragment.highlight-current-green.current-fragment {
+ color: #17ff2e; }
+
+.reveal .slides section .fragment.highlight-current-blue.current-fragment {
+ color: #1b91ff; }
+
+/*********************************************
+ * DEFAULT ELEMENT STYLES
+ *********************************************/
+/* Fixes issue in Chrome where italic fonts did not appear when printing to PDF */
+.reveal:after {
+ content: '';
+ font-style: italic; }
+
+.reveal iframe {
+ z-index: 1; }
+
+/** Prevents layering issues in certain browser/transition combinations */
+.reveal a {
+ position: relative; }
+
+.reveal .stretch {
+ max-width: none;
+ max-height: none; }
+
+.reveal pre.stretch code {
+ height: 100%;
+ max-height: 100%;
+ box-sizing: border-box; }
+
+/*********************************************
+ * CONTROLS
+ *********************************************/
+.reveal .controls {
+ display: none;
+ position: fixed;
+ width: 110px;
+ height: 110px;
+ z-index: 30;
+ right: 10px;
+ bottom: 10px;
+ -webkit-user-select: none; }
+
+.reveal .controls button {
+ padding: 0;
+ position: absolute;
+ opacity: 0.05;
+ width: 0;
+ height: 0;
+ background-color: transparent;
+ border: 12px solid transparent;
+ -webkit-transform: scale(0.9999);
+ transform: scale(0.9999);
+ -webkit-transition: all 0.2s ease;
+ transition: all 0.2s ease;
+ -webkit-appearance: none;
+ -webkit-tap-highlight-color: transparent; }
+
+.reveal .controls .enabled {
+ opacity: 0.7;
+ cursor: pointer; }
+
+.reveal .controls .enabled:active {
+ margin-top: 1px; }
+
+.reveal .controls .navigate-left {
+ top: 42px;
+ border-right-width: 22px;
+ border-right-color: #000; }
+
+.reveal .controls .navigate-left.fragmented {
+ opacity: 0.3; }
+
+.reveal .controls .navigate-right {
+ left: 74px;
+ top: 42px;
+ border-left-width: 22px;
+ border-left-color: #000; }
+
+.reveal .controls .navigate-right.fragmented {
+ opacity: 0.3; }
+
+.reveal .controls .navigate-up {
+ left: 42px;
+ border-bottom-width: 22px;
+ border-bottom-color: #000; }
+
+.reveal .controls .navigate-up.fragmented {
+ opacity: 0.3; }
+
+.reveal .controls .navigate-down {
+ left: 42px;
+ top: 74px;
+ border-top-width: 22px;
+ border-top-color: #000; }
+
+.reveal .controls .navigate-down.fragmented {
+ opacity: 0.3; }
+
+/*********************************************
+ * PROGRESS BAR
+ *********************************************/
+.reveal .progress {
+ position: fixed;
+ display: none;
+ height: 3px;
+ width: 100%;
+ bottom: 0;
+ left: 0;
+ z-index: 10;
+ background-color: rgba(0, 0, 0, 0.2); }
+
+.reveal .progress:after {
+ content: '';
+ display: block;
+ position: absolute;
+ height: 20px;
+ width: 100%;
+ top: -20px; }
+
+.reveal .progress span {
+ display: block;
+ height: 100%;
+ width: 0px;
+ background-color: #000;
+ -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+ transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
+
+/*********************************************
+ * SLIDE NUMBER
+ *********************************************/
+.reveal .slide-number {
+ position: fixed;
+ display: block;
+ right: 8px;
+ bottom: 8px;
+ z-index: 31;
+ font-family: Helvetica, sans-serif;
+ font-size: 12px;
+ line-height: 1;
+ color: #fff;
+ background-color: rgba(0, 0, 0, 0.4);
+ padding: 5px; }
+
+.reveal .slide-number-delimiter {
+ margin: 0 3px; }
+
+/*********************************************
+ * SLIDES
+ *********************************************/
+.reveal {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ -ms-touch-action: none;
+ touch-action: none; }
+
+.reveal .slides {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ margin: auto;
+ overflow: visible;
+ z-index: 1;
+ text-align: center;
+ -webkit-perspective: 600px;
+ perspective: 600px;
+ -webkit-perspective-origin: 50% 40%;
+ perspective-origin: 50% 40%; }
+
+.reveal .slides > section {
+ -ms-perspective: 600px; }
+
+.reveal .slides > section,
+.reveal .slides > section > section {
+ display: none;
+ position: absolute;
+ width: 100%;
+ padding: 20px 0px;
+ z-index: 10;
+ -webkit-transform-style: flat;
+ transform-style: flat;
+ -webkit-transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+ transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
+
+/* Global transition speed settings */
+.reveal[data-transition-speed="fast"] .slides section {
+ -webkit-transition-duration: 400ms;
+ transition-duration: 400ms; }
+
+.reveal[data-transition-speed="slow"] .slides section {
+ -webkit-transition-duration: 1200ms;
+ transition-duration: 1200ms; }
+
+/* Slide-specific transition speed overrides */
+.reveal .slides section[data-transition-speed="fast"] {
+ -webkit-transition-duration: 400ms;
+ transition-duration: 400ms; }
+
+.reveal .slides section[data-transition-speed="slow"] {
+ -webkit-transition-duration: 1200ms;
+ transition-duration: 1200ms; }
+
+.reveal .slides > section.stack {
+ padding-top: 0;
+ padding-bottom: 0; }
+
+.reveal .slides > section.present,
+.reveal .slides > section > section.present {
+ display: block;
+ z-index: 11;
+ opacity: 1; }
+
+.reveal.center,
+.reveal.center .slides,
+.reveal.center .slides section {
+ min-height: 0 !important; }
+
+/* Don't allow interaction with invisible slides */
+.reveal .slides > section.future,
+.reveal .slides > section > section.future,
+.reveal .slides > section.past,
+.reveal .slides > section > section.past {
+ pointer-events: none; }
+
+.reveal.overview .slides > section,
+.reveal.overview .slides > section > section {
+ pointer-events: auto; }
+
+.reveal .slides > section.past,
+.reveal .slides > section.future,
+.reveal .slides > section > section.past,
+.reveal .slides > section > section.future {
+ opacity: 0; }
+
+/*********************************************
+ * Mixins for readability of transitions
+ *********************************************/
+/*********************************************
+ * SLIDE TRANSITION
+ * Aliased 'linear' for backwards compatibility
+ *********************************************/
+.reveal.slide section {
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.reveal .slides > section[data-transition=slide].past,
+.reveal .slides > section[data-transition~=slide-out].past,
+.reveal.slide .slides > section:not([data-transition]).past {
+ -webkit-transform: translate(-150%, 0);
+ transform: translate(-150%, 0); }
+
+.reveal .slides > section[data-transition=slide].future,
+.reveal .slides > section[data-transition~=slide-in].future,
+.reveal.slide .slides > section:not([data-transition]).future {
+ -webkit-transform: translate(150%, 0);
+ transform: translate(150%, 0); }
+
+.reveal .slides > section > section[data-transition=slide].past,
+.reveal .slides > section > section[data-transition~=slide-out].past,
+.reveal.slide .slides > section > section:not([data-transition]).past {
+ -webkit-transform: translate(0, -150%);
+ transform: translate(0, -150%); }
+
+.reveal .slides > section > section[data-transition=slide].future,
+.reveal .slides > section > section[data-transition~=slide-in].future,
+.reveal.slide .slides > section > section:not([data-transition]).future {
+ -webkit-transform: translate(0, 150%);
+ transform: translate(0, 150%); }
+
+.reveal.linear section {
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.reveal .slides > section[data-transition=linear].past,
+.reveal .slides > section[data-transition~=linear-out].past,
+.reveal.linear .slides > section:not([data-transition]).past {
+ -webkit-transform: translate(-150%, 0);
+ transform: translate(-150%, 0); }
+
+.reveal .slides > section[data-transition=linear].future,
+.reveal .slides > section[data-transition~=linear-in].future,
+.reveal.linear .slides > section:not([data-transition]).future {
+ -webkit-transform: translate(150%, 0);
+ transform: translate(150%, 0); }
+
+.reveal .slides > section > section[data-transition=linear].past,
+.reveal .slides > section > section[data-transition~=linear-out].past,
+.reveal.linear .slides > section > section:not([data-transition]).past {
+ -webkit-transform: translate(0, -150%);
+ transform: translate(0, -150%); }
+
+.reveal .slides > section > section[data-transition=linear].future,
+.reveal .slides > section > section[data-transition~=linear-in].future,
+.reveal.linear .slides > section > section:not([data-transition]).future {
+ -webkit-transform: translate(0, 150%);
+ transform: translate(0, 150%); }
+
+/*********************************************
+ * CONVEX TRANSITION
+ * Aliased 'default' for backwards compatibility
+ *********************************************/
+.reveal .slides section[data-transition=default].stack,
+.reveal.default .slides section.stack {
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d; }
+
+.reveal .slides > section[data-transition=default].past,
+.reveal .slides > section[data-transition~=default-out].past,
+.reveal.default .slides > section:not([data-transition]).past {
+ -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); }
+
+.reveal .slides > section[data-transition=default].future,
+.reveal .slides > section[data-transition~=default-in].future,
+.reveal.default .slides > section:not([data-transition]).future {
+ -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); }
+
+.reveal .slides > section > section[data-transition=default].past,
+.reveal .slides > section > section[data-transition~=default-out].past,
+.reveal.default .slides > section > section:not([data-transition]).past {
+ -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0);
+ transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); }
+
+.reveal .slides > section > section[data-transition=default].future,
+.reveal .slides > section > section[data-transition~=default-in].future,
+.reveal.default .slides > section > section:not([data-transition]).future {
+ -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0);
+ transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); }
+
+.reveal .slides section[data-transition=convex].stack,
+.reveal.convex .slides section.stack {
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d; }
+
+.reveal .slides > section[data-transition=convex].past,
+.reveal .slides > section[data-transition~=convex-out].past,
+.reveal.convex .slides > section:not([data-transition]).past {
+ -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); }
+
+.reveal .slides > section[data-transition=convex].future,
+.reveal .slides > section[data-transition~=convex-in].future,
+.reveal.convex .slides > section:not([data-transition]).future {
+ -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); }
+
+.reveal .slides > section > section[data-transition=convex].past,
+.reveal .slides > section > section[data-transition~=convex-out].past,
+.reveal.convex .slides > section > section:not([data-transition]).past {
+ -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0);
+ transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); }
+
+.reveal .slides > section > section[data-transition=convex].future,
+.reveal .slides > section > section[data-transition~=convex-in].future,
+.reveal.convex .slides > section > section:not([data-transition]).future {
+ -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0);
+ transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); }
+
+/*********************************************
+ * CONCAVE TRANSITION
+ *********************************************/
+.reveal .slides section[data-transition=concave].stack,
+.reveal.concave .slides section.stack {
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d; }
+
+.reveal .slides > section[data-transition=concave].past,
+.reveal .slides > section[data-transition~=concave-out].past,
+.reveal.concave .slides > section:not([data-transition]).past {
+ -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); }
+
+.reveal .slides > section[data-transition=concave].future,
+.reveal .slides > section[data-transition~=concave-in].future,
+.reveal.concave .slides > section:not([data-transition]).future {
+ -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); }
+
+.reveal .slides > section > section[data-transition=concave].past,
+.reveal .slides > section > section[data-transition~=concave-out].past,
+.reveal.concave .slides > section > section:not([data-transition]).past {
+ -webkit-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0);
+ transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); }
+
+.reveal .slides > section > section[data-transition=concave].future,
+.reveal .slides > section > section[data-transition~=concave-in].future,
+.reveal.concave .slides > section > section:not([data-transition]).future {
+ -webkit-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0);
+ transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); }
+
+/*********************************************
+ * ZOOM TRANSITION
+ *********************************************/
+.reveal .slides section[data-transition=zoom],
+.reveal.zoom .slides section:not([data-transition]) {
+ -webkit-transition-timing-function: ease;
+ transition-timing-function: ease; }
+
+.reveal .slides > section[data-transition=zoom].past,
+.reveal .slides > section[data-transition~=zoom-out].past,
+.reveal.zoom .slides > section:not([data-transition]).past {
+ visibility: hidden;
+ -webkit-transform: scale(16);
+ transform: scale(16); }
+
+.reveal .slides > section[data-transition=zoom].future,
+.reveal .slides > section[data-transition~=zoom-in].future,
+.reveal.zoom .slides > section:not([data-transition]).future {
+ visibility: hidden;
+ -webkit-transform: scale(0.2);
+ transform: scale(0.2); }
+
+.reveal .slides > section > section[data-transition=zoom].past,
+.reveal .slides > section > section[data-transition~=zoom-out].past,
+.reveal.zoom .slides > section > section:not([data-transition]).past {
+ -webkit-transform: translate(0, -150%);
+ transform: translate(0, -150%); }
+
+.reveal .slides > section > section[data-transition=zoom].future,
+.reveal .slides > section > section[data-transition~=zoom-in].future,
+.reveal.zoom .slides > section > section:not([data-transition]).future {
+ -webkit-transform: translate(0, 150%);
+ transform: translate(0, 150%); }
+
+/*********************************************
+ * CUBE TRANSITION
+ *********************************************/
+.reveal.cube .slides {
+ -webkit-perspective: 1300px;
+ perspective: 1300px; }
+
+.reveal.cube .slides section {
+ padding: 30px;
+ min-height: 700px;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ box-sizing: border-box;
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d; }
+
+.reveal.center.cube .slides section {
+ min-height: 0; }
+
+.reveal.cube .slides section:not(.stack):before {
+ content: '';
+ position: absolute;
+ display: block;
+ width: 100%;
+ height: 100%;
+ left: 0;
+ top: 0;
+ background: rgba(0, 0, 0, 0.1);
+ border-radius: 4px;
+ -webkit-transform: translateZ(-20px);
+ transform: translateZ(-20px); }
+
+.reveal.cube .slides section:not(.stack):after {
+ content: '';
+ position: absolute;
+ display: block;
+ width: 90%;
+ height: 30px;
+ left: 5%;
+ bottom: 0;
+ background: none;
+ z-index: 1;
+ border-radius: 4px;
+ box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2);
+ -webkit-transform: translateZ(-90px) rotateX(65deg);
+ transform: translateZ(-90px) rotateX(65deg); }
+
+.reveal.cube .slides > section.stack {
+ padding: 0;
+ background: none; }
+
+.reveal.cube .slides > section.past {
+ -webkit-transform-origin: 100% 0%;
+ transform-origin: 100% 0%;
+ -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg);
+ transform: translate3d(-100%, 0, 0) rotateY(-90deg); }
+
+.reveal.cube .slides > section.future {
+ -webkit-transform-origin: 0% 0%;
+ transform-origin: 0% 0%;
+ -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg);
+ transform: translate3d(100%, 0, 0) rotateY(90deg); }
+
+.reveal.cube .slides > section > section.past {
+ -webkit-transform-origin: 0% 100%;
+ transform-origin: 0% 100%;
+ -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg);
+ transform: translate3d(0, -100%, 0) rotateX(90deg); }
+
+.reveal.cube .slides > section > section.future {
+ -webkit-transform-origin: 0% 0%;
+ transform-origin: 0% 0%;
+ -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg);
+ transform: translate3d(0, 100%, 0) rotateX(-90deg); }
+
+/*********************************************
+ * PAGE TRANSITION
+ *********************************************/
+.reveal.page .slides {
+ -webkit-perspective-origin: 0% 50%;
+ perspective-origin: 0% 50%;
+ -webkit-perspective: 3000px;
+ perspective: 3000px; }
+
+.reveal.page .slides section {
+ padding: 30px;
+ min-height: 700px;
+ box-sizing: border-box;
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d; }
+
+.reveal.page .slides section.past {
+ z-index: 12; }
+
+.reveal.page .slides section:not(.stack):before {
+ content: '';
+ position: absolute;
+ display: block;
+ width: 100%;
+ height: 100%;
+ left: 0;
+ top: 0;
+ background: rgba(0, 0, 0, 0.1);
+ -webkit-transform: translateZ(-20px);
+ transform: translateZ(-20px); }
+
+.reveal.page .slides section:not(.stack):after {
+ content: '';
+ position: absolute;
+ display: block;
+ width: 90%;
+ height: 30px;
+ left: 5%;
+ bottom: 0;
+ background: none;
+ z-index: 1;
+ border-radius: 4px;
+ box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2);
+ -webkit-transform: translateZ(-90px) rotateX(65deg); }
+
+.reveal.page .slides > section.stack {
+ padding: 0;
+ background: none; }
+
+.reveal.page .slides > section.past {
+ -webkit-transform-origin: 0% 0%;
+ transform-origin: 0% 0%;
+ -webkit-transform: translate3d(-40%, 0, 0) rotateY(-80deg);
+ transform: translate3d(-40%, 0, 0) rotateY(-80deg); }
+
+.reveal.page .slides > section.future {
+ -webkit-transform-origin: 100% 0%;
+ transform-origin: 100% 0%;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0); }
+
+.reveal.page .slides > section > section.past {
+ -webkit-transform-origin: 0% 0%;
+ transform-origin: 0% 0%;
+ -webkit-transform: translate3d(0, -40%, 0) rotateX(80deg);
+ transform: translate3d(0, -40%, 0) rotateX(80deg); }
+
+.reveal.page .slides > section > section.future {
+ -webkit-transform-origin: 0% 100%;
+ transform-origin: 0% 100%;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0); }
+
+/*********************************************
+ * FADE TRANSITION
+ *********************************************/
+.reveal .slides section[data-transition=fade],
+.reveal.fade .slides section:not([data-transition]),
+.reveal.fade .slides > section > section:not([data-transition]) {
+ -webkit-transform: none;
+ transform: none;
+ -webkit-transition: opacity 0.5s;
+ transition: opacity 0.5s; }
+
+.reveal.fade.overview .slides section,
+.reveal.fade.overview .slides > section > section {
+ -webkit-transition: none;
+ transition: none; }
+
+/*********************************************
+ * NO TRANSITION
+ *********************************************/
+.reveal .slides section[data-transition=none],
+.reveal.none .slides section:not([data-transition]) {
+ -webkit-transform: none;
+ transform: none;
+ -webkit-transition: none;
+ transition: none; }
+
+/*********************************************
+ * PAUSED MODE
+ *********************************************/
+.reveal .pause-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: black;
+ visibility: hidden;
+ opacity: 0;
+ z-index: 100;
+ -webkit-transition: all 1s ease;
+ transition: all 1s ease; }
+
+.reveal.paused .pause-overlay {
+ visibility: visible;
+ opacity: 1; }
+
+/*********************************************
+ * FALLBACK
+ *********************************************/
+.no-transforms {
+ overflow-y: auto; }
+
+.no-transforms .reveal .slides {
+ position: relative;
+ width: 80%;
+ height: auto !important;
+ top: 0;
+ left: 50%;
+ margin: 0;
+ text-align: center; }
+
+.no-transforms .reveal .controls,
+.no-transforms .reveal .progress {
+ display: none !important; }
+
+.no-transforms .reveal .slides section {
+ display: block !important;
+ opacity: 1 !important;
+ position: relative !important;
+ height: auto;
+ min-height: 0;
+ top: 0;
+ left: -50%;
+ margin: 70px 0;
+ -webkit-transform: none;
+ transform: none; }
+
+.no-transforms .reveal .slides section section {
+ left: 0; }
+
+.reveal .no-transition,
+.reveal .no-transition * {
+ -webkit-transition: none !important;
+ transition: none !important; }
+
+/*********************************************
+ * PER-SLIDE BACKGROUNDS
+ *********************************************/
+.reveal .backgrounds {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ -webkit-perspective: 600px;
+ perspective: 600px; }
+
+.reveal .slide-background {
+ display: none;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ visibility: hidden;
+ background-color: transparent;
+ background-position: 50% 50%;
+ background-repeat: no-repeat;
+ background-size: cover;
+ -webkit-transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+ transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
+
+.reveal .slide-background.stack {
+ display: block; }
+
+.reveal .slide-background.present {
+ opacity: 1;
+ visibility: visible; }
+
+.print-pdf .reveal .slide-background {
+ opacity: 1 !important;
+ visibility: visible !important; }
+
+/* Video backgrounds */
+.reveal .slide-background video {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ max-width: none;
+ max-height: none;
+ top: 0;
+ left: 0; }
+
+/* Immediate transition style */
+.reveal[data-background-transition=none] > .backgrounds .slide-background,
+.reveal > .backgrounds .slide-background[data-background-transition=none] {
+ -webkit-transition: none;
+ transition: none; }
+
+/* Slide */
+.reveal[data-background-transition=slide] > .backgrounds .slide-background,
+.reveal > .backgrounds .slide-background[data-background-transition=slide] {
+ opacity: 1;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.reveal[data-background-transition=slide] > .backgrounds .slide-background.past,
+.reveal > .backgrounds .slide-background.past[data-background-transition=slide] {
+ -webkit-transform: translate(-100%, 0);
+ transform: translate(-100%, 0); }
+
+.reveal[data-background-transition=slide] > .backgrounds .slide-background.future,
+.reveal > .backgrounds .slide-background.future[data-background-transition=slide] {
+ -webkit-transform: translate(100%, 0);
+ transform: translate(100%, 0); }
+
+.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.past,
+.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=slide] {
+ -webkit-transform: translate(0, -100%);
+ transform: translate(0, -100%); }
+
+.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.future,
+.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=slide] {
+ -webkit-transform: translate(0, 100%);
+ transform: translate(0, 100%); }
+
+/* Convex */
+.reveal[data-background-transition=convex] > .backgrounds .slide-background.past,
+.reveal > .backgrounds .slide-background.past[data-background-transition=convex] {
+ opacity: 0;
+ -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); }
+
+.reveal[data-background-transition=convex] > .backgrounds .slide-background.future,
+.reveal > .backgrounds .slide-background.future[data-background-transition=convex] {
+ opacity: 0;
+ -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); }
+
+.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.past,
+.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=convex] {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0);
+ transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); }
+
+.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.future,
+.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=convex] {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); }
+
+/* Concave */
+.reveal[data-background-transition=concave] > .backgrounds .slide-background.past,
+.reveal > .backgrounds .slide-background.past[data-background-transition=concave] {
+ opacity: 0;
+ -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); }
+
+.reveal[data-background-transition=concave] > .backgrounds .slide-background.future,
+.reveal > .backgrounds .slide-background.future[data-background-transition=concave] {
+ opacity: 0;
+ -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); }
+
+.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.past,
+.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=concave] {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0);
+ transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); }
+
+.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.future,
+.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=concave] {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); }
+
+/* Zoom */
+.reveal[data-background-transition=zoom] > .backgrounds .slide-background,
+.reveal > .backgrounds .slide-background[data-background-transition=zoom] {
+ -webkit-transition-timing-function: ease;
+ transition-timing-function: ease; }
+
+.reveal[data-background-transition=zoom] > .backgrounds .slide-background.past,
+.reveal > .backgrounds .slide-background.past[data-background-transition=zoom] {
+ opacity: 0;
+ visibility: hidden;
+ -webkit-transform: scale(16);
+ transform: scale(16); }
+
+.reveal[data-background-transition=zoom] > .backgrounds .slide-background.future,
+.reveal > .backgrounds .slide-background.future[data-background-transition=zoom] {
+ opacity: 0;
+ visibility: hidden;
+ -webkit-transform: scale(0.2);
+ transform: scale(0.2); }
+
+.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.past,
+.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=zoom] {
+ opacity: 0;
+ visibility: hidden;
+ -webkit-transform: scale(16);
+ transform: scale(16); }
+
+.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.future,
+.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=zoom] {
+ opacity: 0;
+ visibility: hidden;
+ -webkit-transform: scale(0.2);
+ transform: scale(0.2); }
+
+/* Global transition speed settings */
+.reveal[data-transition-speed="fast"] > .backgrounds .slide-background {
+ -webkit-transition-duration: 400ms;
+ transition-duration: 400ms; }
+
+.reveal[data-transition-speed="slow"] > .backgrounds .slide-background {
+ -webkit-transition-duration: 1200ms;
+ transition-duration: 1200ms; }
+
+/*********************************************
+ * OVERVIEW
+ *********************************************/
+.reveal.overview {
+ -webkit-perspective-origin: 50% 50%;
+ perspective-origin: 50% 50%;
+ -webkit-perspective: 700px;
+ perspective: 700px; }
+ .reveal.overview .slides {
+ -moz-transform-style: preserve-3d; }
+ .reveal.overview .slides section {
+ height: 100%;
+ top: 0 !important;
+ opacity: 1 !important;
+ overflow: hidden;
+ visibility: visible !important;
+ cursor: pointer;
+ box-sizing: border-box; }
+ .reveal.overview .slides section:hover,
+ .reveal.overview .slides section.present {
+ outline: 10px solid rgba(150, 150, 150, 0.4);
+ outline-offset: 10px; }
+ .reveal.overview .slides section .fragment {
+ opacity: 1;
+ -webkit-transition: none;
+ transition: none; }
+ .reveal.overview .slides section:after,
+ .reveal.overview .slides section:before {
+ display: none !important; }
+ .reveal.overview .slides > section.stack {
+ padding: 0;
+ top: 0 !important;
+ background: none;
+ outline: none;
+ overflow: visible; }
+ .reveal.overview .backgrounds {
+ -webkit-perspective: inherit;
+ perspective: inherit;
+ -moz-transform-style: preserve-3d; }
+ .reveal.overview .backgrounds .slide-background {
+ opacity: 1;
+ visibility: visible;
+ outline: 10px solid rgba(150, 150, 150, 0.1);
+ outline-offset: 10px; }
+
+.reveal.overview .slides section,
+.reveal.overview-deactivating .slides section {
+ -webkit-transition: none;
+ transition: none; }
+
+.reveal.overview .backgrounds .slide-background,
+.reveal.overview-deactivating .backgrounds .slide-background {
+ -webkit-transition: none;
+ transition: none; }
+
+.reveal.overview-animated .slides {
+ -webkit-transition: -webkit-transform 0.4s ease;
+ transition: transform 0.4s ease; }
+
+/*********************************************
+ * RTL SUPPORT
+ *********************************************/
+.reveal.rtl .slides,
+.reveal.rtl .slides h1,
+.reveal.rtl .slides h2,
+.reveal.rtl .slides h3,
+.reveal.rtl .slides h4,
+.reveal.rtl .slides h5,
+.reveal.rtl .slides h6 {
+ direction: rtl;
+ font-family: sans-serif; }
+
+.reveal.rtl pre,
+.reveal.rtl code {
+ direction: ltr; }
+
+.reveal.rtl ol,
+.reveal.rtl ul {
+ text-align: right; }
+
+.reveal.rtl .progress span {
+ float: right; }
+
+/*********************************************
+ * PARALLAX BACKGROUND
+ *********************************************/
+.reveal.has-parallax-background .backgrounds {
+ -webkit-transition: all 0.8s ease;
+ transition: all 0.8s ease; }
+
+/* Global transition speed settings */
+.reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds {
+ -webkit-transition-duration: 400ms;
+ transition-duration: 400ms; }
+
+.reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds {
+ -webkit-transition-duration: 1200ms;
+ transition-duration: 1200ms; }
+
+/*********************************************
+ * LINK PREVIEW OVERLAY
+ *********************************************/
+.reveal .overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 1000;
+ background: rgba(0, 0, 0, 0.9);
+ opacity: 0;
+ visibility: hidden;
+ -webkit-transition: all 0.3s ease;
+ transition: all 0.3s ease; }
+
+.reveal .overlay.visible {
+ opacity: 1;
+ visibility: visible; }
+
+.reveal .overlay .spinner {
+ position: absolute;
+ display: block;
+ top: 50%;
+ left: 50%;
+ width: 32px;
+ height: 32px;
+ margin: -16px 0 0 -16px;
+ z-index: 10;
+ background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D);
+ visibility: visible;
+ opacity: 0.6;
+ -webkit-transition: all 0.3s ease;
+ transition: all 0.3s ease; }
+
+.reveal .overlay header {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 40px;
+ z-index: 2;
+ border-bottom: 1px solid #222; }
+
+.reveal .overlay header a {
+ display: inline-block;
+ width: 40px;
+ height: 40px;
+ line-height: 36px;
+ padding: 0 10px;
+ float: right;
+ opacity: 0.6;
+ box-sizing: border-box; }
+
+.reveal .overlay header a:hover {
+ opacity: 1; }
+
+.reveal .overlay header a .icon {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ background-position: 50% 50%;
+ background-size: 100%;
+ background-repeat: no-repeat; }
+
+.reveal .overlay header a.close .icon {
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC); }
+
+.reveal .overlay header a.external .icon {
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==); }
+
+.reveal .overlay .viewport {
+ position: absolute;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ top: 40px;
+ right: 0;
+ bottom: 0;
+ left: 0; }
+
+.reveal .overlay.overlay-preview .viewport iframe {
+ width: 100%;
+ height: 100%;
+ max-width: 100%;
+ max-height: 100%;
+ border: 0;
+ opacity: 0;
+ visibility: hidden;
+ -webkit-transition: all 0.3s ease;
+ transition: all 0.3s ease; }
+
+.reveal .overlay.overlay-preview.loaded .viewport iframe {
+ opacity: 1;
+ visibility: visible; }
+
+.reveal .overlay.overlay-preview.loaded .viewport-inner {
+ position: absolute;
+ z-index: -1;
+ left: 0;
+ top: 45%;
+ width: 100%;
+ text-align: center;
+ letter-spacing: normal; }
+
+.reveal .overlay.overlay-preview .x-frame-error {
+ opacity: 0;
+ -webkit-transition: opacity 0.3s ease 0.3s;
+ transition: opacity 0.3s ease 0.3s; }
+
+.reveal .overlay.overlay-preview.loaded .x-frame-error {
+ opacity: 1; }
+
+.reveal .overlay.overlay-preview.loaded .spinner {
+ opacity: 0;
+ visibility: hidden;
+ -webkit-transform: scale(0.2);
+ transform: scale(0.2); }
+
+.reveal .overlay.overlay-help .viewport {
+ overflow: auto;
+ color: #fff; }
+
+.reveal .overlay.overlay-help .viewport .viewport-inner {
+ width: 600px;
+ margin: auto;
+ padding: 20px 20px 80px 20px;
+ text-align: center;
+ letter-spacing: normal; }
+
+.reveal .overlay.overlay-help .viewport .viewport-inner .title {
+ font-size: 20px; }
+
+.reveal .overlay.overlay-help .viewport .viewport-inner table {
+ border: 1px solid #fff;
+ border-collapse: collapse;
+ font-size: 16px; }
+
+.reveal .overlay.overlay-help .viewport .viewport-inner table th,
+.reveal .overlay.overlay-help .viewport .viewport-inner table td {
+ width: 200px;
+ padding: 14px;
+ border: 1px solid #fff;
+ vertical-align: middle; }
+
+.reveal .overlay.overlay-help .viewport .viewport-inner table th {
+ padding-top: 20px;
+ padding-bottom: 20px; }
+
+/*********************************************
+ * PLAYBACK COMPONENT
+ *********************************************/
+.reveal .playback {
+ position: fixed;
+ left: 15px;
+ bottom: 20px;
+ z-index: 30;
+ cursor: pointer;
+ -webkit-transition: all 400ms ease;
+ transition: all 400ms ease; }
+
+.reveal.overview .playback {
+ opacity: 0;
+ visibility: hidden; }
+
+/*********************************************
+ * ROLLING LINKS
+ *********************************************/
+.reveal .roll {
+ display: inline-block;
+ line-height: 1.2;
+ overflow: hidden;
+ vertical-align: top;
+ -webkit-perspective: 400px;
+ perspective: 400px;
+ -webkit-perspective-origin: 50% 50%;
+ perspective-origin: 50% 50%; }
+
+.reveal .roll:hover {
+ background: none;
+ text-shadow: none; }
+
+.reveal .roll span {
+ display: block;
+ position: relative;
+ padding: 0 2px;
+ pointer-events: none;
+ -webkit-transition: all 400ms ease;
+ transition: all 400ms ease;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.reveal .roll:hover span {
+ background: rgba(0, 0, 0, 0.5);
+ -webkit-transform: translate3d(0px, 0px, -45px) rotateX(90deg);
+ transform: translate3d(0px, 0px, -45px) rotateX(90deg); }
+
+.reveal .roll span:after {
+ content: attr(data-title);
+ display: block;
+ position: absolute;
+ left: 0;
+ top: 0;
+ padding: 0 2px;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+ -webkit-transform: translate3d(0px, 110%, 0px) rotateX(-90deg);
+ transform: translate3d(0px, 110%, 0px) rotateX(-90deg); }
+
+/*********************************************
+ * SPEAKER NOTES
+ *********************************************/
+.reveal aside.notes {
+ display: none; }
+
+.reveal .speaker-notes {
+ display: none;
+ position: absolute;
+ width: 70%;
+ max-height: 15%;
+ left: 15%;
+ bottom: 26px;
+ padding: 10px;
+ z-index: 1;
+ font-size: 18px;
+ line-height: 1.4;
+ color: #fff;
+ background-color: rgba(0, 0, 0, 0.5);
+ overflow: auto;
+ box-sizing: border-box;
+ text-align: left;
+ font-family: Helvetica, sans-serif;
+ -webkit-overflow-scrolling: touch; }
+
+.reveal .speaker-notes.visible:not(:empty) {
+ display: block; }
+
+@media screen and (max-width: 1024px) {
+ .reveal .speaker-notes {
+ font-size: 14px; } }
+
+@media screen and (max-width: 600px) {
+ .reveal .speaker-notes {
+ width: 90%;
+ left: 5%; } }
+
+/*********************************************
+ * ZOOM PLUGIN
+ *********************************************/
+.zoomed .reveal *,
+.zoomed .reveal *:before,
+.zoomed .reveal *:after {
+ -webkit-backface-visibility: visible !important;
+ backface-visibility: visible !important; }
+
+.zoomed .reveal .progress,
+.zoomed .reveal .controls {
+ opacity: 0; }
+
+.zoomed .reveal .roll span {
+ background: none; }
+
+.zoomed .reveal .roll span:after {
+ visibility: hidden; }
diff --git a/slides/reveal.js/reveal.js b/slides/reveal.js/reveal.js
new file mode 100644
index 0000000..f802566
--- /dev/null
+++ b/slides/reveal.js/reveal.js
@@ -0,0 +1,4961 @@
+/*!
+ * reveal.js
+ * http://lab.hakim.se/reveal-js
+ * MIT licensed
+ *
+ * Copyright (C) 2016 Hakim El Hattab, http://hakim.se
+ */
+(function( root, factory ) {
+ if( typeof define === 'function' && define.amd ) {
+ // AMD. Register as an anonymous module.
+ define( function() {
+ root.Reveal = factory();
+ return root.Reveal;
+ } );
+ } else if( typeof exports === 'object' ) {
+ // Node. Does not work with strict CommonJS.
+ module.exports = factory();
+ } else {
+ // Browser globals.
+ root.Reveal = factory();
+ }
+}( this, function() {
+
+ 'use strict';
+
+ var Reveal;
+
+ // The reveal.js version
+ var VERSION = '3.4.1';
+
+ var SLIDES_SELECTOR = '.slides section',
+ HORIZONTAL_SLIDES_SELECTOR = '.slides>section',
+ VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section',
+ HOME_SLIDE_SELECTOR = '.slides>section:first-of-type',
+ UA = navigator.userAgent,
+
+ // Configuration defaults, can be overridden at initialization time
+ config = {
+
+ // The "normal" size of the presentation, aspect ratio will be preserved
+ // when the presentation is scaled to fit different resolutions
+ width: 960,
+ height: 700,
+
+ // Factor of the display size that should remain empty around the content
+ margin: 0.04,
+
+ // Bounds for smallest/largest possible scale to apply to content
+ minScale: 0.2,
+ maxScale: 2.0,
+
+ // Display controls in the bottom right corner
+ controls: true,
+
+ // Display a presentation progress bar
+ progress: true,
+
+ // Display the page number of the current slide
+ slideNumber: false,
+
+ // Push each slide change to the browser history
+ history: false,
+
+ // Enable keyboard shortcuts for navigation
+ keyboard: true,
+
+ // Optional function that blocks keyboard events when retuning false
+ keyboardCondition: null,
+
+ // Enable the slide overview mode
+ overview: true,
+
+ // Vertical centering of slides
+ center: true,
+
+ // Enables touch navigation on devices with touch input
+ touch: true,
+
+ // Loop the presentation
+ loop: false,
+
+ // Change the presentation direction to be RTL
+ rtl: false,
+
+ // Randomizes the order of slides each time the presentation loads
+ shuffle: false,
+
+ // Turns fragments on and off globally
+ fragments: true,
+
+ // Flags if the presentation is running in an embedded mode,
+ // i.e. contained within a limited portion of the screen
+ embedded: false,
+
+ // Flags if we should show a help overlay when the question-mark
+ // key is pressed
+ help: true,
+
+ // Flags if it should be possible to pause the presentation (blackout)
+ pause: true,
+
+ // Flags if speaker notes should be visible to all viewers
+ showNotes: false,
+
+ // Number of milliseconds between automatically proceeding to the
+ // next slide, disabled when set to 0, this value can be overwritten
+ // by using a data-autoslide attribute on your slides
+ autoSlide: 0,
+
+ // Stop auto-sliding after user input
+ autoSlideStoppable: true,
+
+ // Use this method for navigation when auto-sliding (defaults to navigateNext)
+ autoSlideMethod: null,
+
+ // Enable slide navigation via mouse wheel
+ mouseWheel: false,
+
+ // Apply a 3D roll to links on hover
+ rollingLinks: false,
+
+ // Hides the address bar on mobile devices
+ hideAddressBar: true,
+
+ // Opens links in an iframe preview overlay
+ previewLinks: false,
+
+ // Exposes the reveal.js API through window.postMessage
+ postMessage: true,
+
+ // Dispatches all reveal.js events to the parent window through postMessage
+ postMessageEvents: false,
+
+ // Focuses body when page changes visibility to ensure keyboard shortcuts work
+ focusBodyOnPageVisibilityChange: true,
+
+ // Transition style
+ transition: 'slide', // none/fade/slide/convex/concave/zoom
+
+ // Transition speed
+ transitionSpeed: 'default', // default/fast/slow
+
+ // Transition style for full page slide backgrounds
+ backgroundTransition: 'fade', // none/fade/slide/convex/concave/zoom
+
+ // Parallax background image
+ parallaxBackgroundImage: '', // CSS syntax, e.g. "a.jpg"
+
+ // Parallax background size
+ parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px"
+
+ // Amount of pixels to move the parallax background per slide step
+ parallaxBackgroundHorizontal: null,
+ parallaxBackgroundVertical: null,
+
+ // The maximum number of pages a single slide can expand onto when printing
+ // to PDF, unlimited by default
+ pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY,
+
+ // Number of slides away from the current that are visible
+ viewDistance: 3,
+
+ // Script dependencies to load
+ dependencies: []
+
+ },
+
+ // Flags if Reveal.initialize() has been called
+ initialized = false,
+
+ // Flags if reveal.js is loaded (has dispatched the 'ready' event)
+ loaded = false,
+
+ // Flags if the overview mode is currently active
+ overview = false,
+
+ // Holds the dimensions of our overview slides, including margins
+ overviewSlideWidth = null,
+ overviewSlideHeight = null,
+
+ // The horizontal and vertical index of the currently active slide
+ indexh,
+ indexv,
+
+ // The previous and current slide HTML elements
+ previousSlide,
+ currentSlide,
+
+ previousBackground,
+
+ // Slides may hold a data-state attribute which we pick up and apply
+ // as a class to the body. This list contains the combined state of
+ // all current slides.
+ state = [],
+
+ // The current scale of the presentation (see width/height config)
+ scale = 1,
+
+ // CSS transform that is currently applied to the slides container,
+ // split into two groups
+ slidesTransform = { layout: '', overview: '' },
+
+ // Cached references to DOM elements
+ dom = {},
+
+ // Features supported by the browser, see #checkCapabilities()
+ features = {},
+
+ // Client is a mobile device, see #checkCapabilities()
+ isMobileDevice,
+
+ // Client is a desktop Chrome, see #checkCapabilities()
+ isChrome,
+
+ // Throttles mouse wheel navigation
+ lastMouseWheelStep = 0,
+
+ // Delays updates to the URL due to a Chrome thumbnailer bug
+ writeURLTimeout = 0,
+
+ // Flags if the interaction event listeners are bound
+ eventsAreBound = false,
+
+ // The current auto-slide duration
+ autoSlide = 0,
+
+ // Auto slide properties
+ autoSlidePlayer,
+ autoSlideTimeout = 0,
+ autoSlideStartTime = -1,
+ autoSlidePaused = false,
+
+ // Holds information about the currently ongoing touch input
+ touch = {
+ startX: 0,
+ startY: 0,
+ startSpan: 0,
+ startCount: 0,
+ captured: false,
+ threshold: 40
+ },
+
+ // Holds information about the keyboard shortcuts
+ keyboardShortcuts = {
+ 'N , SPACE': 'Next slide',
+ 'P': 'Previous slide',
+ '&#8592; , H': 'Navigate left',
+ '&#8594; , L': 'Navigate right',
+ '&#8593; , K': 'Navigate up',
+ '&#8595; , J': 'Navigate down',
+ 'Home': 'First slide',
+ 'End': 'Last slide',
+ 'B , .': 'Pause',
+ 'F': 'Fullscreen',
+ 'ESC, O': 'Slide overview'
+ };
+
+ /**
+ * Starts up the presentation if the client is capable.
+ */
+ function initialize( options ) {
+
+ // Make sure we only initialize once
+ if( initialized === true ) return;
+
+ initialized = true;
+
+ checkCapabilities();
+
+ if( !features.transforms2d && !features.transforms3d ) {
+ document.body.setAttribute( 'class', 'no-transforms' );
+
+ // Since JS won't be running any further, we load all lazy
+ // loading elements upfront
+ var images = toArray( document.getElementsByTagName( 'img' ) ),
+ iframes = toArray( document.getElementsByTagName( 'iframe' ) );
+
+ var lazyLoadable = images.concat( iframes );
+
+ for( var i = 0, len = lazyLoadable.length; i < len; i++ ) {
+ var element = lazyLoadable[i];
+ if( element.getAttribute( 'data-src' ) ) {
+ element.setAttribute( 'src', element.getAttribute( 'data-src' ) );
+ element.removeAttribute( 'data-src' );
+ }
+ }
+
+ // If the browser doesn't support core features we won't be
+ // using JavaScript to control the presentation
+ return;
+ }
+
+ // Cache references to key DOM elements
+ dom.wrapper = document.querySelector( '.reveal' );
+ dom.slides = document.querySelector( '.reveal .slides' );
+
+ // Force a layout when the whole page, incl fonts, has loaded
+ window.addEventListener( 'load', layout, false );
+
+ var query = Reveal.getQueryHash();
+
+ // Do not accept new dependencies via query config to avoid
+ // the potential of malicious script injection
+ if( typeof query['dependencies'] !== 'undefined' ) delete query['dependencies'];
+
+ // Copy options over to our config object
+ extend( config, options );
+ extend( config, query );
+
+ // Hide the address bar in mobile browsers
+ hideAddressBar();
+
+ // Loads the dependencies and continues to #start() once done
+ load();
+
+ }
+
+ /**
+ * Inspect the client to see what it's capable of, this
+ * should only happens once per runtime.
+ */
+ function checkCapabilities() {
+
+ isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( UA );
+ isChrome = /chrome/i.test( UA ) && !/edge/i.test( UA );
+
+ var testElement = document.createElement( 'div' );
+
+ features.transforms3d = 'WebkitPerspective' in testElement.style ||
+ 'MozPerspective' in testElement.style ||
+ 'msPerspective' in testElement.style ||
+ 'OPerspective' in testElement.style ||
+ 'perspective' in testElement.style;
+
+ features.transforms2d = 'WebkitTransform' in testElement.style ||
+ 'MozTransform' in testElement.style ||
+ 'msTransform' in testElement.style ||
+ 'OTransform' in testElement.style ||
+ 'transform' in testElement.style;
+
+ features.requestAnimationFrameMethod = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
+ features.requestAnimationFrame = typeof features.requestAnimationFrameMethod === 'function';
+
+ features.canvas = !!document.createElement( 'canvas' ).getContext;
+
+ // Transitions in the overview are disabled in desktop and
+ // Safari due to lag
+ features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( UA );
+
+ // Flags if we should use zoom instead of transform to scale
+ // up slides. Zoom produces crisper results but has a lot of
+ // xbrowser quirks so we only use it in whitelsited browsers.
+ features.zoom = 'zoom' in testElement.style && !isMobileDevice &&
+ ( isChrome || /Version\/[\d\.]+.*Safari/.test( UA ) );
+
+ }
+
+ /**
+ * Loads the dependencies of reveal.js. Dependencies are
+ * defined via the configuration option 'dependencies'
+ * and will be loaded prior to starting/binding reveal.js.
+ * Some dependencies may have an 'async' flag, if so they
+ * will load after reveal.js has been started up.
+ */
+ function load() {
+
+ var scripts = [],
+ scriptsAsync = [],
+ scriptsToPreload = 0;
+
+ // Called once synchronous scripts finish loading
+ function proceed() {
+ if( scriptsAsync.length ) {
+ // Load asynchronous scripts
+ head.js.apply( null, scriptsAsync );
+ }
+
+ start();
+ }
+
+ function loadScript( s ) {
+ head.ready( s.src.match( /([\w\d_\-]*)\.?js$|[^\\\/]*$/i )[0], function() {
+ // Extension may contain callback functions
+ if( typeof s.callback === 'function' ) {
+ s.callback.apply( this );
+ }
+
+ if( --scriptsToPreload === 0 ) {
+ proceed();
+ }
+ });
+ }
+
+ for( var i = 0, len = config.dependencies.length; i < len; i++ ) {
+ var s = config.dependencies[i];
+
+ // Load if there's no condition or the condition is truthy
+ if( !s.condition || s.condition() ) {
+ if( s.async ) {
+ scriptsAsync.push( s.src );
+ }
+ else {
+ scripts.push( s.src );
+ }
+
+ loadScript( s );
+ }
+ }
+
+ if( scripts.length ) {
+ scriptsToPreload = scripts.length;
+
+ // Load synchronous scripts
+ head.js.apply( null, scripts );
+ }
+ else {
+ proceed();
+ }
+
+ }
+
+ /**
+ * Starts up reveal.js by binding input events and navigating
+ * to the current URL deeplink if there is one.
+ */
+ function start() {
+
+ // Make sure we've got all the DOM elements we need
+ setupDOM();
+
+ // Listen to messages posted to this window
+ setupPostMessage();
+
+ // Prevent the slides from being scrolled out of view
+ setupScrollPrevention();
+
+ // Resets all vertical slides so that only the first is visible
+ resetVerticalSlides();
+
+ // Updates the presentation to match the current configuration values
+ configure();
+
+ // Read the initial hash
+ readURL();
+
+ // Update all backgrounds
+ updateBackground( true );
+
+ // Notify listeners that the presentation is ready but use a 1ms
+ // timeout to ensure it's not fired synchronously after #initialize()
+ setTimeout( function() {
+ // Enable transitions now that we're loaded
+ dom.slides.classList.remove( 'no-transition' );
+
+ loaded = true;
+
+ dom.wrapper.classList.add( 'ready' );
+
+ dispatchEvent( 'ready', {
+ 'indexh': indexh,
+ 'indexv': indexv,
+ 'currentSlide': currentSlide
+ } );
+ }, 1 );
+
+ // Special setup and config is required when printing to PDF
+ if( isPrintingPDF() ) {
+ removeEventListeners();
+
+ // The document needs to have loaded for the PDF layout
+ // measurements to be accurate
+ if( document.readyState === 'complete' ) {
+ setupPDF();
+ }
+ else {
+ window.addEventListener( 'load', setupPDF );
+ }
+ }
+
+ }
+
+ /**
+ * Finds and stores references to DOM elements which are
+ * required by the presentation. If a required element is
+ * not found, it is created.
+ */
+ function setupDOM() {
+
+ // Prevent transitions while we're loading
+ dom.slides.classList.add( 'no-transition' );
+
+ // Background element
+ dom.background = createSingletonNode( dom.wrapper, 'div', 'backgrounds', null );
+
+ // Progress bar
+ dom.progress = createSingletonNode( dom.wrapper, 'div', 'progress', '<span></span>' );
+ dom.progressbar = dom.progress.querySelector( 'span' );
+
+ // Arrow controls
+ createSingletonNode( dom.wrapper, 'aside', 'controls',
+ '<button class="navigate-left" aria-label="previous slide"></button>' +
+ '<button class="navigate-right" aria-label="next slide"></button>' +
+ '<button class="navigate-up" aria-label="above slide"></button>' +
+ '<button class="navigate-down" aria-label="below slide"></button>' );
+
+ // Slide number
+ dom.slideNumber = createSingletonNode( dom.wrapper, 'div', 'slide-number', '' );
+
+ // Element containing notes that are visible to the audience
+ dom.speakerNotes = createSingletonNode( dom.wrapper, 'div', 'speaker-notes', null );
+ dom.speakerNotes.setAttribute( 'data-prevent-swipe', '' );
+ dom.speakerNotes.setAttribute( 'tabindex', '0' );
+
+ // Overlay graphic which is displayed during the paused mode
+ createSingletonNode( dom.wrapper, 'div', 'pause-overlay', null );
+
+ // Cache references to elements
+ dom.controls = document.querySelector( '.reveal .controls' );
+
+ dom.wrapper.setAttribute( 'role', 'application' );
+
+ // There can be multiple instances of controls throughout the page
+ dom.controlsLeft = toArray( document.querySelectorAll( '.navigate-left' ) );
+ dom.controlsRight = toArray( document.querySelectorAll( '.navigate-right' ) );
+ dom.controlsUp = toArray( document.querySelectorAll( '.navigate-up' ) );
+ dom.controlsDown = toArray( document.querySelectorAll( '.navigate-down' ) );
+ dom.controlsPrev = toArray( document.querySelectorAll( '.navigate-prev' ) );
+ dom.controlsNext = toArray( document.querySelectorAll( '.navigate-next' ) );
+
+ dom.statusDiv = createStatusDiv();
+ }
+
+ /**
+ * Creates a hidden div with role aria-live to announce the
+ * current slide content. Hide the div off-screen to make it
+ * available only to Assistive Technologies.
+ *
+ * @return {HTMLElement}
+ */
+ function createStatusDiv() {
+
+ var statusDiv = document.getElementById( 'aria-status-div' );
+ if( !statusDiv ) {
+ statusDiv = document.createElement( 'div' );
+ statusDiv.style.position = 'absolute';
+ statusDiv.style.height = '1px';
+ statusDiv.style.width = '1px';
+ statusDiv.style.overflow = 'hidden';
+ statusDiv.style.clip = 'rect( 1px, 1px, 1px, 1px )';
+ statusDiv.setAttribute( 'id', 'aria-status-div' );
+ statusDiv.setAttribute( 'aria-live', 'polite' );
+ statusDiv.setAttribute( 'aria-atomic','true' );
+ dom.wrapper.appendChild( statusDiv );
+ }
+ return statusDiv;
+
+ }
+
+ /**
+ * Converts the given HTML element into a string of text
+ * that can be announced to a screen reader. Hidden
+ * elements are excluded.
+ */
+ function getStatusText( node ) {
+
+ var text = '';
+
+ // Text node
+ if( node.nodeType === 3 ) {
+ text += node.textContent;
+ }
+ // Element node
+ else if( node.nodeType === 1 ) {
+
+ var isAriaHidden = node.getAttribute( 'aria-hidden' );
+ var isDisplayHidden = window.getComputedStyle( node )['display'] === 'none';
+ if( isAriaHidden !== 'true' && !isDisplayHidden ) {
+
+ toArray( node.childNodes ).forEach( function( child ) {
+ text += getStatusText( child );
+ } );
+
+ }
+
+ }
+
+ return text;
+
+ }
+
+ /**
+ * Configures the presentation for printing to a static
+ * PDF.
+ */
+ function setupPDF() {
+
+ var slideSize = getComputedSlideSize( window.innerWidth, window.innerHeight );
+
+ // Dimensions of the PDF pages
+ var pageWidth = Math.floor( slideSize.width * ( 1 + config.margin ) ),
+ pageHeight = Math.floor( slideSize.height * ( 1 + config.margin ) );
+
+ // Dimensions of slides within the pages
+ var slideWidth = slideSize.width,
+ slideHeight = slideSize.height;
+
+ // Let the browser know what page size we want to print
+ injectStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0 0 -1px 0;}' );
+
+ // Limit the size of certain elements to the dimensions of the slide
+ injectStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' );
+
+ document.body.classList.add( 'print-pdf' );
+ document.body.style.width = pageWidth + 'px';
+ document.body.style.height = pageHeight + 'px';
+
+ // Add each slide's index as attributes on itself, we need these
+ // indices to generate slide numbers below
+ toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) {
+ hslide.setAttribute( 'data-index-h', h );
+
+ if( hslide.classList.contains( 'stack' ) ) {
+ toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) {
+ vslide.setAttribute( 'data-index-h', h );
+ vslide.setAttribute( 'data-index-v', v );
+ } );
+ }
+ } );
+
+ // Slide and slide background layout
+ toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
+
+ // Vertical stacks are not centred since their section
+ // children will be
+ if( slide.classList.contains( 'stack' ) === false ) {
+ // Center the slide inside of the page, giving the slide some margin
+ var left = ( pageWidth - slideWidth ) / 2,
+ top = ( pageHeight - slideHeight ) / 2;
+
+ var contentHeight = slide.scrollHeight;
+ var numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 );
+
+ // Adhere to configured pages per slide limit
+ numberOfPages = Math.min( numberOfPages, config.pdfMaxPagesPerSlide );
+
+ // Center slides vertically
+ if( numberOfPages === 1 && config.center || slide.classList.contains( 'center' ) ) {
+ top = Math.max( ( pageHeight - contentHeight ) / 2, 0 );
+ }
+
+ // Wrap the slide in a page element and hide its overflow
+ // so that no page ever flows onto another
+ var page = document.createElement( 'div' );
+ page.className = 'pdf-page';
+ page.style.height = ( pageHeight * numberOfPages ) + 'px';
+ slide.parentNode.insertBefore( page, slide );
+ page.appendChild( slide );
+
+ // Position the slide inside of the page
+ slide.style.left = left + 'px';
+ slide.style.top = top + 'px';
+ slide.style.width = slideWidth + 'px';
+
+ if( slide.slideBackgroundElement ) {
+ page.insertBefore( slide.slideBackgroundElement, slide );
+ }
+
+ // Inject notes if `showNotes` is enabled
+ if( config.showNotes ) {
+
+ // Are there notes for this slide?
+ var notes = getSlideNotes( slide );
+ if( notes ) {
+
+ var notesSpacing = 8;
+ var notesLayout = typeof config.showNotes === 'string' ? config.showNotes : 'inline';
+ var notesElement = document.createElement( 'div' );
+ notesElement.classList.add( 'speaker-notes' );
+ notesElement.classList.add( 'speaker-notes-pdf' );
+ notesElement.setAttribute( 'data-layout', notesLayout );
+ notesElement.innerHTML = notes;
+
+ if( notesLayout === 'separate-page' ) {
+ page.parentNode.insertBefore( notesElement, page.nextSibling );
+ }
+ else {
+ notesElement.style.left = notesSpacing + 'px';
+ notesElement.style.bottom = notesSpacing + 'px';
+ notesElement.style.width = ( pageWidth - notesSpacing*2 ) + 'px';
+ page.appendChild( notesElement );
+ }
+
+ }
+
+ }
+
+ // Inject slide numbers if `slideNumbers` are enabled
+ if( config.slideNumber ) {
+ var slideNumberH = parseInt( slide.getAttribute( 'data-index-h' ), 10 ) + 1,
+ slideNumberV = parseInt( slide.getAttribute( 'data-index-v' ), 10 ) + 1;
+
+ var numberElement = document.createElement( 'div' );
+ numberElement.classList.add( 'slide-number' );
+ numberElement.classList.add( 'slide-number-pdf' );
+ numberElement.innerHTML = formatSlideNumber( slideNumberH, '.', slideNumberV );
+ page.appendChild( numberElement );
+ }
+ }
+
+ } );
+
+ // Show all fragments
+ toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' .fragment' ) ).forEach( function( fragment ) {
+ fragment.classList.add( 'visible' );
+ } );
+
+ // Notify subscribers that the PDF layout is good to go
+ dispatchEvent( 'pdf-ready' );
+
+ }
+
+ /**
+ * This is an unfortunate necessity. Some actions – such as
+ * an input field being focused in an iframe or using the
+ * keyboard to expand text selection beyond the bounds of
+ * a slide – can trigger our content to be pushed out of view.
+ * This scrolling can not be prevented by hiding overflow in
+ * CSS (we already do) so we have to resort to repeatedly
+ * checking if the slides have been offset :(
+ */
+ function setupScrollPrevention() {
+
+ setInterval( function() {
+ if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {
+ dom.wrapper.scrollTop = 0;
+ dom.wrapper.scrollLeft = 0;
+ }
+ }, 1000 );
+
+ }
+
+ /**
+ * Creates an HTML element and returns a reference to it.
+ * If the element already exists the existing instance will
+ * be returned.
+ *
+ * @param {HTMLElement} container
+ * @param {string} tagname
+ * @param {string} classname
+ * @param {string} innerHTML
+ *
+ * @return {HTMLElement}
+ */
+ function createSingletonNode( container, tagname, classname, innerHTML ) {
+
+ // Find all nodes matching the description
+ var nodes = container.querySelectorAll( '.' + classname );
+
+ // Check all matches to find one which is a direct child of
+ // the specified container
+ for( var i = 0; i < nodes.length; i++ ) {
+ var testNode = nodes[i];
+ if( testNode.parentNode === container ) {
+ return testNode;
+ }
+ }
+
+ // If no node was found, create it now
+ var node = document.createElement( tagname );
+ node.classList.add( classname );
+ if( typeof innerHTML === 'string' ) {
+ node.innerHTML = innerHTML;
+ }
+ container.appendChild( node );
+
+ return node;
+
+ }
+
+ /**
+ * Creates the slide background elements and appends them
+ * to the background container. One element is created per
+ * slide no matter if the given slide has visible background.
+ */
+ function createBackgrounds() {
+
+ var printMode = isPrintingPDF();
+
+ // Clear prior backgrounds
+ dom.background.innerHTML = '';
+ dom.background.classList.add( 'no-transition' );
+
+ // Iterate over all horizontal slides
+ toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( slideh ) {
+
+ var backgroundStack = createBackground( slideh, dom.background );
+
+ // Iterate over all vertical slides
+ toArray( slideh.querySelectorAll( 'section' ) ).forEach( function( slidev ) {
+
+ createBackground( slidev, backgroundStack );
+
+ backgroundStack.classList.add( 'stack' );
+
+ } );
+
+ } );
+
+ // Add parallax background if specified
+ if( config.parallaxBackgroundImage ) {
+
+ dom.background.style.backgroundImage = 'url("' + config.parallaxBackgroundImage + '")';
+ dom.background.style.backgroundSize = config.parallaxBackgroundSize;
+
+ // Make sure the below properties are set on the element - these properties are
+ // needed for proper transitions to be set on the element via CSS. To remove
+ // annoying background slide-in effect when the presentation starts, apply
+ // these properties after short time delay
+ setTimeout( function() {
+ dom.wrapper.classList.add( 'has-parallax-background' );
+ }, 1 );
+
+ }
+ else {
+
+ dom.background.style.backgroundImage = '';
+ dom.wrapper.classList.remove( 'has-parallax-background' );
+
+ }
+
+ }
+
+ /**
+ * Creates a background for the given slide.
+ *
+ * @param {HTMLElement} slide
+ * @param {HTMLElement} container The element that the background
+ * should be appended to
+ * @return {HTMLElement} New background div
+ */
+ function createBackground( slide, container ) {
+
+ var data = {
+ background: slide.getAttribute( 'data-background' ),
+ backgroundSize: slide.getAttribute( 'data-background-size' ),
+ backgroundImage: slide.getAttribute( 'data-background-image' ),
+ backgroundVideo: slide.getAttribute( 'data-background-video' ),
+ backgroundIframe: slide.getAttribute( 'data-background-iframe' ),
+ backgroundColor: slide.getAttribute( 'data-background-color' ),
+ backgroundRepeat: slide.getAttribute( 'data-background-repeat' ),
+ backgroundPosition: slide.getAttribute( 'data-background-position' ),
+ backgroundTransition: slide.getAttribute( 'data-background-transition' )
+ };
+
+ var element = document.createElement( 'div' );
+
+ // Carry over custom classes from the slide to the background
+ element.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' );
+
+ if( data.background ) {
+ // Auto-wrap image urls in url(...)
+ if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)$/gi.test( data.background ) ) {
+ slide.setAttribute( 'data-background-image', data.background );
+ }
+ else {
+ element.style.background = data.background;
+ }
+ }
+
+ // Create a hash for this combination of background settings.
+ // This is used to determine when two slide backgrounds are
+ // the same.
+ if( data.background || data.backgroundColor || data.backgroundImage || data.backgroundVideo || data.backgroundIframe ) {
+ element.setAttribute( 'data-background-hash', data.background +
+ data.backgroundSize +
+ data.backgroundImage +
+ data.backgroundVideo +
+ data.backgroundIframe +
+ data.backgroundColor +
+ data.backgroundRepeat +
+ data.backgroundPosition +
+ data.backgroundTransition );
+ }
+
+ // Additional and optional background properties
+ if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize;
+ if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;
+ if( data.backgroundRepeat ) element.style.backgroundRepeat = data.backgroundRepeat;
+ if( data.backgroundPosition ) element.style.backgroundPosition = data.backgroundPosition;
+ if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition );
+
+ container.appendChild( element );
+
+ // If backgrounds are being recreated, clear old classes
+ slide.classList.remove( 'has-dark-background' );
+ slide.classList.remove( 'has-light-background' );
+
+ slide.slideBackgroundElement = element;
+
+ // If this slide has a background color, add a class that
+ // signals if it is light or dark. If the slide has no background
+ // color, no class will be set
+ var computedBackgroundStyle = window.getComputedStyle( element );
+ if( computedBackgroundStyle && computedBackgroundStyle.backgroundColor ) {
+ var rgb = colorToRgb( computedBackgroundStyle.backgroundColor );
+
+ // Ignore fully transparent backgrounds. Some browsers return
+ // rgba(0,0,0,0) when reading the computed background color of
+ // an element with no background
+ if( rgb && rgb.a !== 0 ) {
+ if( colorBrightness( computedBackgroundStyle.backgroundColor ) < 128 ) {
+ slide.classList.add( 'has-dark-background' );
+ }
+ else {
+ slide.classList.add( 'has-light-background' );
+ }
+ }
+ }
+
+ return element;
+
+ }
+
+ /**
+ * Registers a listener to postMessage events, this makes it
+ * possible to call all reveal.js API methods from another
+ * window. For example:
+ *
+ * revealWindow.postMessage( JSON.stringify({
+ * method: 'slide',
+ * args: [ 2 ]
+ * }), '*' );
+ */
+ function setupPostMessage() {
+
+ if( config.postMessage ) {
+ window.addEventListener( 'message', function ( event ) {
+ var data = event.data;
+
+ // Make sure we're dealing with JSON
+ if( typeof data === 'string' && data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) {
+ data = JSON.parse( data );
+
+ // Check if the requested method can be found
+ if( data.method && typeof Reveal[data.method] === 'function' ) {
+ Reveal[data.method].apply( Reveal, data.args );
+ }
+ }
+ }, false );
+ }
+
+ }
+
+ /**
+ * Applies the configuration settings from the config
+ * object. May be called multiple times.
+ *
+ * @param {object} options
+ */
+ function configure( options ) {
+
+ var numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length;
+
+ dom.wrapper.classList.remove( config.transition );
+
+ // New config options may be passed when this method
+ // is invoked through the API after initialization
+ if( typeof options === 'object' ) extend( config, options );
+
+ // Force linear transition based on browser capabilities
+ if( features.transforms3d === false ) config.transition = 'linear';
+
+ dom.wrapper.classList.add( config.transition );
+
+ dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed );
+ dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );
+
+ dom.controls.style.display = config.controls ? 'block' : 'none';
+ dom.progress.style.display = config.progress ? 'block' : 'none';
+ dom.slideNumber.style.display = config.slideNumber && !isPrintingPDF() ? 'block' : 'none';
+
+ if( config.shuffle ) {
+ shuffle();
+ }
+
+ if( config.rtl ) {
+ dom.wrapper.classList.add( 'rtl' );
+ }
+ else {
+ dom.wrapper.classList.remove( 'rtl' );
+ }
+
+ if( config.center ) {
+ dom.wrapper.classList.add( 'center' );
+ }
+ else {
+ dom.wrapper.classList.remove( 'center' );
+ }
+
+ // Exit the paused mode if it was configured off
+ if( config.pause === false ) {
+ resume();
+ }
+
+ if( config.showNotes ) {
+ dom.speakerNotes.classList.add( 'visible' );
+ dom.speakerNotes.setAttribute( 'data-layout', typeof config.showNotes === 'string' ? config.showNotes : 'inline' );
+ }
+ else {
+ dom.speakerNotes.classList.remove( 'visible' );
+ }
+
+ if( config.mouseWheel ) {
+ document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
+ document.addEventListener( 'mousewheel', onDocumentMouseScroll, false );
+ }
+ else {
+ document.removeEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
+ document.removeEventListener( 'mousewheel', onDocumentMouseScroll, false );
+ }
+
+ // Rolling 3D links
+ if( config.rollingLinks ) {
+ enableRollingLinks();
+ }
+ else {
+ disableRollingLinks();
+ }
+
+ // Iframe link previews
+ if( config.previewLinks ) {
+ enablePreviewLinks();
+ }
+ else {
+ disablePreviewLinks();
+ enablePreviewLinks( '[data-preview-link]' );
+ }
+
+ // Remove existing auto-slide controls
+ if( autoSlidePlayer ) {
+ autoSlidePlayer.destroy();
+ autoSlidePlayer = null;
+ }
+
+ // Generate auto-slide controls if needed
+ if( numberOfSlides > 1 && config.autoSlide && config.autoSlideStoppable && features.canvas && features.requestAnimationFrame ) {
+ autoSlidePlayer = new Playback( dom.wrapper, function() {
+ return Math.min( Math.max( ( Date.now() - autoSlideStartTime ) / autoSlide, 0 ), 1 );
+ } );
+
+ autoSlidePlayer.on( 'click', onAutoSlidePlayerClick );
+ autoSlidePaused = false;
+ }
+
+ // When fragments are turned off they should be visible
+ if( config.fragments === false ) {
+ toArray( dom.slides.querySelectorAll( '.fragment' ) ).forEach( function( element ) {
+ element.classList.add( 'visible' );
+ element.classList.remove( 'current-fragment' );
+ } );
+ }
+
+ sync();
+
+ }
+
+ /**
+ * Binds all event listeners.
+ */
+ function addEventListeners() {
+
+ eventsAreBound = true;
+
+ window.addEventListener( 'hashchange', onWindowHashChange, false );
+ window.addEventListener( 'resize', onWindowResize, false );
+
+ if( config.touch ) {
+ dom.wrapper.addEventListener( 'touchstart', onTouchStart, false );
+ dom.wrapper.addEventListener( 'touchmove', onTouchMove, false );
+ dom.wrapper.addEventListener( 'touchend', onTouchEnd, false );
+
+ // Support pointer-style touch interaction as well
+ if( window.navigator.pointerEnabled ) {
+ // IE 11 uses un-prefixed version of pointer events
+ dom.wrapper.addEventListener( 'pointerdown', onPointerDown, false );
+ dom.wrapper.addEventListener( 'pointermove', onPointerMove, false );
+ dom.wrapper.addEventListener( 'pointerup', onPointerUp, false );
+ }
+ else if( window.navigator.msPointerEnabled ) {
+ // IE 10 uses prefixed version of pointer events
+ dom.wrapper.addEventListener( 'MSPointerDown', onPointerDown, false );
+ dom.wrapper.addEventListener( 'MSPointerMove', onPointerMove, false );
+ dom.wrapper.addEventListener( 'MSPointerUp', onPointerUp, false );
+ }
+ }
+
+ if( config.keyboard ) {
+ document.addEventListener( 'keydown', onDocumentKeyDown, false );
+ document.addEventListener( 'keypress', onDocumentKeyPress, false );
+ }
+
+ if( config.progress && dom.progress ) {
+ dom.progress.addEventListener( 'click', onProgressClicked, false );
+ }
+
+ if( config.focusBodyOnPageVisibilityChange ) {
+ var visibilityChange;
+
+ if( 'hidden' in document ) {
+ visibilityChange = 'visibilitychange';
+ }
+ else if( 'msHidden' in document ) {
+ visibilityChange = 'msvisibilitychange';
+ }
+ else if( 'webkitHidden' in document ) {
+ visibilityChange = 'webkitvisibilitychange';
+ }
+
+ if( visibilityChange ) {
+ document.addEventListener( visibilityChange, onPageVisibilityChange, false );
+ }
+ }
+
+ // Listen to both touch and click events, in case the device
+ // supports both
+ var pointerEvents = [ 'touchstart', 'click' ];
+
+ // Only support touch for Android, fixes double navigations in
+ // stock browser
+ if( UA.match( /android/gi ) ) {
+ pointerEvents = [ 'touchstart' ];
+ }
+
+ pointerEvents.forEach( function( eventName ) {
+ dom.controlsLeft.forEach( function( el ) { el.addEventListener( eventName, onNavigateLeftClicked, false ); } );
+ dom.controlsRight.forEach( function( el ) { el.addEventListener( eventName, onNavigateRightClicked, false ); } );
+ dom.controlsUp.forEach( function( el ) { el.addEventListener( eventName, onNavigateUpClicked, false ); } );
+ dom.controlsDown.forEach( function( el ) { el.addEventListener( eventName, onNavigateDownClicked, false ); } );
+ dom.controlsPrev.forEach( function( el ) { el.addEventListener( eventName, onNavigatePrevClicked, false ); } );
+ dom.controlsNext.forEach( function( el ) { el.addEventListener( eventName, onNavigateNextClicked, false ); } );
+ } );
+
+ }
+
+ /**
+ * Unbinds all event listeners.
+ */
+ function removeEventListeners() {
+
+ eventsAreBound = false;
+
+ document.removeEventListener( 'keydown', onDocumentKeyDown, false );
+ document.removeEventListener( 'keypress', onDocumentKeyPress, false );
+ window.removeEventListener( 'hashchange', onWindowHashChange, false );
+ window.removeEventListener( 'resize', onWindowResize, false );
+
+ dom.wrapper.removeEventListener( 'touchstart', onTouchStart, false );
+ dom.wrapper.removeEventListener( 'touchmove', onTouchMove, false );
+ dom.wrapper.removeEventListener( 'touchend', onTouchEnd, false );
+
+ // IE11
+ if( window.navigator.pointerEnabled ) {
+ dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false );
+ dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false );
+ dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false );
+ }
+ // IE10
+ else if( window.navigator.msPointerEnabled ) {
+ dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false );
+ dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false );
+ dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false );
+ }
+
+ if ( config.progress && dom.progress ) {
+ dom.progress.removeEventListener( 'click', onProgressClicked, false );
+ }
+
+ [ 'touchstart', 'click' ].forEach( function( eventName ) {
+ dom.controlsLeft.forEach( function( el ) { el.removeEventListener( eventName, onNavigateLeftClicked, false ); } );
+ dom.controlsRight.forEach( function( el ) { el.removeEventListener( eventName, onNavigateRightClicked, false ); } );
+ dom.controlsUp.forEach( function( el ) { el.removeEventListener( eventName, onNavigateUpClicked, false ); } );
+ dom.controlsDown.forEach( function( el ) { el.removeEventListener( eventName, onNavigateDownClicked, false ); } );
+ dom.controlsPrev.forEach( function( el ) { el.removeEventListener( eventName, onNavigatePrevClicked, false ); } );
+ dom.controlsNext.forEach( function( el ) { el.removeEventListener( eventName, onNavigateNextClicked, false ); } );
+ } );
+
+ }
+
+ /**
+ * Extend object a with the properties of object b.
+ * If there's a conflict, object b takes precedence.
+ *
+ * @param {object} a
+ * @param {object} b
+ */
+ function extend( a, b ) {
+
+ for( var i in b ) {
+ a[ i ] = b[ i ];
+ }
+
+ }
+
+ /**
+ * Converts the target object to an array.
+ *
+ * @param {object} o
+ * @return {object[]}
+ */
+ function toArray( o ) {
+
+ return Array.prototype.slice.call( o );
+
+ }
+
+ /**
+ * Utility for deserializing a value.
+ *
+ * @param {*} value
+ * @return {*}
+ */
+ function deserialize( value ) {
+
+ if( typeof value === 'string' ) {
+ if( value === 'null' ) return null;
+ else if( value === 'true' ) return true;
+ else if( value === 'false' ) return false;
+ else if( value.match( /^\d+$/ ) ) return parseFloat( value );
+ }
+
+ return value;
+
+ }
+
+ /**
+ * Measures the distance in pixels between point a
+ * and point b.
+ *
+ * @param {object} a point with x/y properties
+ * @param {object} b point with x/y properties
+ *
+ * @return {number}
+ */
+ function distanceBetween( a, b ) {
+
+ var dx = a.x - b.x,
+ dy = a.y - b.y;
+
+ return Math.sqrt( dx*dx + dy*dy );
+
+ }
+
+ /**
+ * Applies a CSS transform to the target element.
+ *
+ * @param {HTMLElement} element
+ * @param {string} transform
+ */
+ function transformElement( element, transform ) {
+
+ element.style.WebkitTransform = transform;
+ element.style.MozTransform = transform;
+ element.style.msTransform = transform;
+ element.style.transform = transform;
+
+ }
+
+ /**
+ * Applies CSS transforms to the slides container. The container
+ * is transformed from two separate sources: layout and the overview
+ * mode.
+ *
+ * @param {object} transforms
+ */
+ function transformSlides( transforms ) {
+
+ // Pick up new transforms from arguments
+ if( typeof transforms.layout === 'string' ) slidesTransform.layout = transforms.layout;
+ if( typeof transforms.overview === 'string' ) slidesTransform.overview = transforms.overview;
+
+ // Apply the transforms to the slides container
+ if( slidesTransform.layout ) {
+ transformElement( dom.slides, slidesTransform.layout + ' ' + slidesTransform.overview );
+ }
+ else {
+ transformElement( dom.slides, slidesTransform.overview );
+ }
+
+ }
+
+ /**
+ * Injects the given CSS styles into the DOM.
+ *
+ * @param {string} value
+ */
+ function injectStyleSheet( value ) {
+
+ var tag = document.createElement( 'style' );
+ tag.type = 'text/css';
+ if( tag.styleSheet ) {
+ tag.styleSheet.cssText = value;
+ }
+ else {
+ tag.appendChild( document.createTextNode( value ) );
+ }
+ document.getElementsByTagName( 'head' )[0].appendChild( tag );
+
+ }
+
+ /**
+ * Find the closest parent that matches the given
+ * selector.
+ *
+ * @param {HTMLElement} target The child element
+ * @param {String} selector The CSS selector to match
+ * the parents against
+ *
+ * @return {HTMLElement} The matched parent or null
+ * if no matching parent was found
+ */
+ function closestParent( target, selector ) {
+
+ var parent = target.parentNode;
+
+ while( parent ) {
+
+ // There's some overhead doing this each time, we don't
+ // want to rewrite the element prototype but should still
+ // be enough to feature detect once at startup...
+ var matchesMethod = parent.matches || parent.matchesSelector || parent.msMatchesSelector;
+
+ // If we find a match, we're all set
+ if( matchesMethod && matchesMethod.call( parent, selector ) ) {
+ return parent;
+ }
+
+ // Keep searching
+ parent = parent.parentNode;
+
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Converts various color input formats to an {r:0,g:0,b:0} object.
+ *
+ * @param {string} color The string representation of a color
+ * @example
+ * colorToRgb('#000');
+ * @example
+ * colorToRgb('#000000');
+ * @example
+ * colorToRgb('rgb(0,0,0)');
+ * @example
+ * colorToRgb('rgba(0,0,0)');
+ *
+ * @return {{r: number, g: number, b: number, [a]: number}|null}
+ */
+ function colorToRgb( color ) {
+
+ var hex3 = color.match( /^#([0-9a-f]{3})$/i );
+ if( hex3 && hex3[1] ) {
+ hex3 = hex3[1];
+ return {
+ r: parseInt( hex3.charAt( 0 ), 16 ) * 0x11,
+ g: parseInt( hex3.charAt( 1 ), 16 ) * 0x11,
+ b: parseInt( hex3.charAt( 2 ), 16 ) * 0x11
+ };
+ }
+
+ var hex6 = color.match( /^#([0-9a-f]{6})$/i );
+ if( hex6 && hex6[1] ) {
+ hex6 = hex6[1];
+ return {
+ r: parseInt( hex6.substr( 0, 2 ), 16 ),
+ g: parseInt( hex6.substr( 2, 2 ), 16 ),
+ b: parseInt( hex6.substr( 4, 2 ), 16 )
+ };
+ }
+
+ var rgb = color.match( /^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i );
+ if( rgb ) {
+ return {
+ r: parseInt( rgb[1], 10 ),
+ g: parseInt( rgb[2], 10 ),
+ b: parseInt( rgb[3], 10 )
+ };
+ }
+
+ var rgba = color.match( /^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i );
+ if( rgba ) {
+ return {
+ r: parseInt( rgba[1], 10 ),
+ g: parseInt( rgba[2], 10 ),
+ b: parseInt( rgba[3], 10 ),
+ a: parseFloat( rgba[4] )
+ };
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Calculates brightness on a scale of 0-255.
+ *
+ * @param {string} color See colorToRgb for supported formats.
+ * @see {@link colorToRgb}
+ */
+ function colorBrightness( color ) {
+
+ if( typeof color === 'string' ) color = colorToRgb( color );
+
+ if( color ) {
+ return ( color.r * 299 + color.g * 587 + color.b * 114 ) / 1000;
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Returns the remaining height within the parent of the
+ * target element.
+ *
+ * remaining height = [ configured parent height ] - [ current parent height ]
+ *
+ * @param {HTMLElement} element
+ * @param {number} [height]
+ */
+ function getRemainingHeight( element, height ) {
+
+ height = height || 0;
+
+ if( element ) {
+ var newHeight, oldHeight = element.style.height;
+
+ // Change the .stretch element height to 0 in order find the height of all
+ // the other elements
+ element.style.height = '0px';
+ newHeight = height - element.parentNode.offsetHeight;
+
+ // Restore the old height, just in case
+ element.style.height = oldHeight + 'px';
+
+ return newHeight;
+ }
+
+ return height;
+
+ }
+
+ /**
+ * Checks if this instance is being used to print a PDF.
+ */
+ function isPrintingPDF() {
+
+ return ( /print-pdf/gi ).test( window.location.search );
+
+ }
+
+ /**
+ * Hides the address bar if we're on a mobile device.
+ */
+ function hideAddressBar() {
+
+ if( config.hideAddressBar && isMobileDevice ) {
+ // Events that should trigger the address bar to hide
+ window.addEventListener( 'load', removeAddressBar, false );
+ window.addEventListener( 'orientationchange', removeAddressBar, false );
+ }
+
+ }
+
+ /**
+ * Causes the address bar to hide on mobile devices,
+ * more vertical space ftw.
+ */
+ function removeAddressBar() {
+
+ setTimeout( function() {
+ window.scrollTo( 0, 1 );
+ }, 10 );
+
+ }
+
+ /**
+ * Dispatches an event of the specified type from the
+ * reveal DOM element.
+ */
+ function dispatchEvent( type, args ) {
+
+ var event = document.createEvent( 'HTMLEvents', 1, 2 );
+ event.initEvent( type, true, true );
+ extend( event, args );
+ dom.wrapper.dispatchEvent( event );
+
+ // If we're in an iframe, post each reveal.js event to the
+ // parent window. Used by the notes plugin
+ if( config.postMessageEvents && window.parent !== window.self ) {
+ window.parent.postMessage( JSON.stringify({ namespace: 'reveal', eventName: type, state: getState() }), '*' );
+ }
+
+ }
+
+ /**
+ * Wrap all links in 3D goodness.
+ */
+ function enableRollingLinks() {
+
+ if( features.transforms3d && !( 'msPerspective' in document.body.style ) ) {
+ var anchors = dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' a' );
+
+ for( var i = 0, len = anchors.length; i < len; i++ ) {
+ var anchor = anchors[i];
+
+ if( anchor.textContent && !anchor.querySelector( '*' ) && ( !anchor.className || !anchor.classList.contains( anchor, 'roll' ) ) ) {
+ var span = document.createElement('span');
+ span.setAttribute('data-title', anchor.text);
+ span.innerHTML = anchor.innerHTML;
+
+ anchor.classList.add( 'roll' );
+ anchor.innerHTML = '';
+ anchor.appendChild(span);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Unwrap all 3D links.
+ */
+ function disableRollingLinks() {
+
+ var anchors = dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' a.roll' );
+
+ for( var i = 0, len = anchors.length; i < len; i++ ) {
+ var anchor = anchors[i];
+ var span = anchor.querySelector( 'span' );
+
+ if( span ) {
+ anchor.classList.remove( 'roll' );
+ anchor.innerHTML = span.innerHTML;
+ }
+ }
+
+ }
+
+ /**
+ * Bind preview frame links.
+ *
+ * @param {string} [selector=a] - selector for anchors
+ */
+ function enablePreviewLinks( selector ) {
+
+ var anchors = toArray( document.querySelectorAll( selector ? selector : 'a' ) );
+
+ anchors.forEach( function( element ) {
+ if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) {
+ element.addEventListener( 'click', onPreviewLinkClicked, false );
+ }
+ } );
+
+ }
+
+ /**
+ * Unbind preview frame links.
+ */
+ function disablePreviewLinks() {
+
+ var anchors = toArray( document.querySelectorAll( 'a' ) );
+
+ anchors.forEach( function( element ) {
+ if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) {
+ element.removeEventListener( 'click', onPreviewLinkClicked, false );
+ }
+ } );
+
+ }
+
+ /**
+ * Opens a preview window for the target URL.
+ *
+ * @param {string} url - url for preview iframe src
+ */
+ function showPreview( url ) {
+
+ closeOverlay();
+
+ dom.overlay = document.createElement( 'div' );
+ dom.overlay.classList.add( 'overlay' );
+ dom.overlay.classList.add( 'overlay-preview' );
+ dom.wrapper.appendChild( dom.overlay );
+
+ dom.overlay.innerHTML = [
+ '<header>',
+ '<a class="close" href="#"><span class="icon"></span></a>',
+ '<a class="external" href="'+ url +'" target="_blank"><span class="icon"></span></a>',
+ '</header>',
+ '<div class="spinner"></div>',
+ '<div class="viewport">',
+ '<iframe src="'+ url +'"></iframe>',
+ '<small class="viewport-inner">',
+ '<span class="x-frame-error">Unable to load iframe. This is likely due to the site\'s policy (x-frame-options).</span>',
+ '</small>',
+ '</div>'
+ ].join('');
+
+ dom.overlay.querySelector( 'iframe' ).addEventListener( 'load', function( event ) {
+ dom.overlay.classList.add( 'loaded' );
+ }, false );
+
+ dom.overlay.querySelector( '.close' ).addEventListener( 'click', function( event ) {
+ closeOverlay();
+ event.preventDefault();
+ }, false );
+
+ dom.overlay.querySelector( '.external' ).addEventListener( 'click', function( event ) {
+ closeOverlay();
+ }, false );
+
+ setTimeout( function() {
+ dom.overlay.classList.add( 'visible' );
+ }, 1 );
+
+ }
+
+ /**
+ * Opens an overlay window with help material.
+ */
+ function showHelp() {
+
+ if( config.help ) {
+
+ closeOverlay();
+
+ dom.overlay = document.createElement( 'div' );
+ dom.overlay.classList.add( 'overlay' );
+ dom.overlay.classList.add( 'overlay-help' );
+ dom.wrapper.appendChild( dom.overlay );
+
+ var html = '<p class="title">Keyboard Shortcuts</p><br/>';
+
+ html += '<table><th>KEY</th><th>ACTION</th>';
+ for( var key in keyboardShortcuts ) {
+ html += '<tr><td>' + key + '</td><td>' + keyboardShortcuts[ key ] + '</td></tr>';
+ }
+
+ html += '</table>';
+
+ dom.overlay.innerHTML = [
+ '<header>',
+ '<a class="close" href="#"><span class="icon"></span></a>',
+ '</header>',
+ '<div class="viewport">',
+ '<div class="viewport-inner">'+ html +'</div>',
+ '</div>'
+ ].join('');
+
+ dom.overlay.querySelector( '.close' ).addEventListener( 'click', function( event ) {
+ closeOverlay();
+ event.preventDefault();
+ }, false );
+
+ setTimeout( function() {
+ dom.overlay.classList.add( 'visible' );
+ }, 1 );
+
+ }
+
+ }
+
+ /**
+ * Closes any currently open overlay.
+ */
+ function closeOverlay() {
+
+ if( dom.overlay ) {
+ dom.overlay.parentNode.removeChild( dom.overlay );
+ dom.overlay = null;
+ }
+
+ }
+
+ /**
+ * Applies JavaScript-controlled layout rules to the
+ * presentation.
+ */
+ function layout() {
+
+ if( dom.wrapper && !isPrintingPDF() ) {
+
+ var size = getComputedSlideSize();
+
+ // Layout the contents of the slides
+ layoutSlideContents( config.width, config.height );
+
+ dom.slides.style.width = size.width + 'px';
+ dom.slides.style.height = size.height + 'px';
+
+ // Determine scale of content to fit within available space
+ scale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height );
+
+ // Respect max/min scale settings
+ scale = Math.max( scale, config.minScale );
+ scale = Math.min( scale, config.maxScale );
+
+ // Don't apply any scaling styles if scale is 1
+ if( scale === 1 ) {
+ dom.slides.style.zoom = '';
+ dom.slides.style.left = '';
+ dom.slides.style.top = '';
+ dom.slides.style.bottom = '';
+ dom.slides.style.right = '';
+ transformSlides( { layout: '' } );
+ }
+ else {
+ // Prefer zoom for scaling up so that content remains crisp.
+ // Don't use zoom to scale down since that can lead to shifts
+ // in text layout/line breaks.
+ if( scale > 1 && features.zoom ) {
+ dom.slides.style.zoom = scale;
+ dom.slides.style.left = '';
+ dom.slides.style.top = '';
+ dom.slides.style.bottom = '';
+ dom.slides.style.right = '';
+ transformSlides( { layout: '' } );
+ }
+ // Apply scale transform as a fallback
+ else {
+ dom.slides.style.zoom = '';
+ dom.slides.style.left = '50%';
+ dom.slides.style.top = '50%';
+ dom.slides.style.bottom = 'auto';
+ dom.slides.style.right = 'auto';
+ transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } );
+ }
+ }
+
+ // Select all slides, vertical and horizontal
+ var slides = toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) );
+
+ for( var i = 0, len = slides.length; i < len; i++ ) {
+ var slide = slides[ i ];
+
+ // Don't bother updating invisible slides
+ if( slide.style.display === 'none' ) {
+ continue;
+ }
+
+ if( config.center || slide.classList.contains( 'center' ) ) {
+ // Vertical stacks are not centred since their section
+ // children will be
+ if( slide.classList.contains( 'stack' ) ) {
+ slide.style.top = 0;
+ }
+ else {
+ slide.style.top = Math.max( ( size.height - slide.scrollHeight ) / 2, 0 ) + 'px';
+ }
+ }
+ else {
+ slide.style.top = '';
+ }
+
+ }
+
+ updateProgress();
+ updateParallax();
+
+ }
+
+ }
+
+ /**
+ * Applies layout logic to the contents of all slides in
+ * the presentation.
+ *
+ * @param {string|number} width
+ * @param {string|number} height
+ */
+ function layoutSlideContents( width, height ) {
+
+ // Handle sizing of elements with the 'stretch' class
+ toArray( dom.slides.querySelectorAll( 'section > .stretch' ) ).forEach( function( element ) {
+
+ // Determine how much vertical space we can use
+ var remainingHeight = getRemainingHeight( element, height );
+
+ // Consider the aspect ratio of media elements
+ if( /(img|video)/gi.test( element.nodeName ) ) {
+ var nw = element.naturalWidth || element.videoWidth,
+ nh = element.naturalHeight || element.videoHeight;
+
+ var es = Math.min( width / nw, remainingHeight / nh );
+
+ element.style.width = ( nw * es ) + 'px';
+ element.style.height = ( nh * es ) + 'px';
+
+ }
+ else {
+ element.style.width = width + 'px';
+ element.style.height = remainingHeight + 'px';
+ }
+
+ } );
+
+ }
+
+ /**
+ * Calculates the computed pixel size of our slides. These
+ * values are based on the width and height configuration
+ * options.
+ *
+ * @param {number} [presentationWidth=dom.wrapper.offsetWidth]
+ * @param {number} [presentationHeight=dom.wrapper.offsetHeight]
+ */
+ function getComputedSlideSize( presentationWidth, presentationHeight ) {
+
+ var size = {
+ // Slide size
+ width: config.width,
+ height: config.height,
+
+ // Presentation size
+ presentationWidth: presentationWidth || dom.wrapper.offsetWidth,
+ presentationHeight: presentationHeight || dom.wrapper.offsetHeight
+ };
+
+ // Reduce available space by margin
+ size.presentationWidth -= ( size.presentationWidth * config.margin );
+ size.presentationHeight -= ( size.presentationHeight * config.margin );
+
+ // Slide width may be a percentage of available width
+ if( typeof size.width === 'string' && /%$/.test( size.width ) ) {
+ size.width = parseInt( size.width, 10 ) / 100 * size.presentationWidth;
+ }
+
+ // Slide height may be a percentage of available height
+ if( typeof size.height === 'string' && /%$/.test( size.height ) ) {
+ size.height = parseInt( size.height, 10 ) / 100 * size.presentationHeight;
+ }
+
+ return size;
+
+ }
+
+ /**
+ * Stores the vertical index of a stack so that the same
+ * vertical slide can be selected when navigating to and
+ * from the stack.
+ *
+ * @param {HTMLElement} stack The vertical stack element
+ * @param {string|number} [v=0] Index to memorize
+ */
+ function setPreviousVerticalIndex( stack, v ) {
+
+ if( typeof stack === 'object' && typeof stack.setAttribute === 'function' ) {
+ stack.setAttribute( 'data-previous-indexv', v || 0 );
+ }
+
+ }
+
+ /**
+ * Retrieves the vertical index which was stored using
+ * #setPreviousVerticalIndex() or 0 if no previous index
+ * exists.
+ *
+ * @param {HTMLElement} stack The vertical stack element
+ */
+ function getPreviousVerticalIndex( stack ) {
+
+ if( typeof stack === 'object' && typeof stack.setAttribute === 'function' && stack.classList.contains( 'stack' ) ) {
+ // Prefer manually defined start-indexv
+ var attributeName = stack.hasAttribute( 'data-start-indexv' ) ? 'data-start-indexv' : 'data-previous-indexv';
+
+ return parseInt( stack.getAttribute( attributeName ) || 0, 10 );
+ }
+
+ return 0;
+
+ }
+
+ /**
+ * Displays the overview of slides (quick nav) by scaling
+ * down and arranging all slide elements.
+ */
+ function activateOverview() {
+
+ // Only proceed if enabled in config
+ if( config.overview && !isOverview() ) {
+
+ overview = true;
+
+ dom.wrapper.classList.add( 'overview' );
+ dom.wrapper.classList.remove( 'overview-deactivating' );
+
+ if( features.overviewTransitions ) {
+ setTimeout( function() {
+ dom.wrapper.classList.add( 'overview-animated' );
+ }, 1 );
+ }
+
+ // Don't auto-slide while in overview mode
+ cancelAutoSlide();
+
+ // Move the backgrounds element into the slide container to
+ // that the same scaling is applied
+ dom.slides.appendChild( dom.background );
+
+ // Clicking on an overview slide navigates to it
+ toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
+ if( !slide.classList.contains( 'stack' ) ) {
+ slide.addEventListener( 'click', onOverviewSlideClicked, true );
+ }
+ } );
+
+ // Calculate slide sizes
+ var margin = 70;
+ var slideSize = getComputedSlideSize();
+ overviewSlideWidth = slideSize.width + margin;
+ overviewSlideHeight = slideSize.height + margin;
+
+ // Reverse in RTL mode
+ if( config.rtl ) {
+ overviewSlideWidth = -overviewSlideWidth;
+ }
+
+ updateSlidesVisibility();
+ layoutOverview();
+ updateOverview();
+
+ layout();
+
+ // Notify observers of the overview showing
+ dispatchEvent( 'overviewshown', {
+ 'indexh': indexh,
+ 'indexv': indexv,
+ 'currentSlide': currentSlide
+ } );
+
+ }
+
+ }
+
+ /**
+ * Uses CSS transforms to position all slides in a grid for
+ * display inside of the overview mode.
+ */
+ function layoutOverview() {
+
+ // Layout slides
+ toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) {
+ hslide.setAttribute( 'data-index-h', h );
+ transformElement( hslide, 'translate3d(' + ( h * overviewSlideWidth ) + 'px, 0, 0)' );
+
+ if( hslide.classList.contains( 'stack' ) ) {
+
+ toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) {
+ vslide.setAttribute( 'data-index-h', h );
+ vslide.setAttribute( 'data-index-v', v );
+
+ transformElement( vslide, 'translate3d(0, ' + ( v * overviewSlideHeight ) + 'px, 0)' );
+ } );
+
+ }
+ } );
+
+ // Layout slide backgrounds
+ toArray( dom.background.childNodes ).forEach( function( hbackground, h ) {
+ transformElement( hbackground, 'translate3d(' + ( h * overviewSlideWidth ) + 'px, 0, 0)' );
+
+ toArray( hbackground.querySelectorAll( '.slide-background' ) ).forEach( function( vbackground, v ) {
+ transformElement( vbackground, 'translate3d(0, ' + ( v * overviewSlideHeight ) + 'px, 0)' );
+ } );
+ } );
+
+ }
+
+ /**
+ * Moves the overview viewport to the current slides.
+ * Called each time the current slide changes.
+ */
+ function updateOverview() {
+
+ transformSlides( {
+ overview: [
+ 'translateX('+ ( -indexh * overviewSlideWidth ) +'px)',
+ 'translateY('+ ( -indexv * overviewSlideHeight ) +'px)',
+ 'translateZ('+ ( window.innerWidth < 400 ? -1000 : -2500 ) +'px)'
+ ].join( ' ' )
+ } );
+
+ }
+
+ /**
+ * Exits the slide overview and enters the currently
+ * active slide.
+ */
+ function deactivateOverview() {
+
+ // Only proceed if enabled in config
+ if( config.overview ) {
+
+ overview = false;
+
+ dom.wrapper.classList.remove( 'overview' );
+ dom.wrapper.classList.remove( 'overview-animated' );
+
+ // Temporarily add a class so that transitions can do different things
+ // depending on whether they are exiting/entering overview, or just
+ // moving from slide to slide
+ dom.wrapper.classList.add( 'overview-deactivating' );
+
+ setTimeout( function () {
+ dom.wrapper.classList.remove( 'overview-deactivating' );
+ }, 1 );
+
+ // Move the background element back out
+ dom.wrapper.appendChild( dom.background );
+
+ // Clean up changes made to slides
+ toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
+ transformElement( slide, '' );
+
+ slide.removeEventListener( 'click', onOverviewSlideClicked, true );
+ } );
+
+ // Clean up changes made to backgrounds
+ toArray( dom.background.querySelectorAll( '.slide-background' ) ).forEach( function( background ) {
+ transformElement( background, '' );
+ } );
+
+ transformSlides( { overview: '' } );
+
+ slide( indexh, indexv );
+
+ layout();
+
+ cueAutoSlide();
+
+ // Notify observers of the overview hiding
+ dispatchEvent( 'overviewhidden', {
+ 'indexh': indexh,
+ 'indexv': indexv,
+ 'currentSlide': currentSlide
+ } );
+
+ }
+ }
+
+ /**
+ * Toggles the slide overview mode on and off.
+ *
+ * @param {Boolean} [override] Flag which overrides the
+ * toggle logic and forcibly sets the desired state. True means
+ * overview is open, false means it's closed.
+ */
+ function toggleOverview( override ) {
+
+ if( typeof override === 'boolean' ) {
+ override ? activateOverview() : deactivateOverview();
+ }
+ else {
+ isOverview() ? deactivateOverview() : activateOverview();
+ }
+
+ }
+
+ /**
+ * Checks if the overview is currently active.
+ *
+ * @return {Boolean} true if the overview is active,
+ * false otherwise
+ */
+ function isOverview() {
+
+ return overview;
+
+ }
+
+ /**
+ * Checks if the current or specified slide is vertical
+ * (nested within another slide).
+ *
+ * @param {HTMLElement} [slide=currentSlide] The slide to check
+ * orientation of
+ * @return {Boolean}
+ */
+ function isVerticalSlide( slide ) {
+
+ // Prefer slide argument, otherwise use current slide
+ slide = slide ? slide : currentSlide;
+
+ return slide && slide.parentNode && !!slide.parentNode.nodeName.match( /section/i );
+
+ }
+
+ /**
+ * Handling the fullscreen functionality via the fullscreen API
+ *
+ * @see http://fullscreen.spec.whatwg.org/
+ * @see https://developer.mozilla.org/en-US/docs/DOM/Using_fullscreen_mode
+ */
+ function enterFullscreen() {
+
+ var element = document.documentElement;
+
+ // Check which implementation is available
+ var requestMethod = element.requestFullscreen ||
+ element.webkitRequestFullscreen ||
+ element.webkitRequestFullScreen ||
+ element.mozRequestFullScreen ||
+ element.msRequestFullscreen;
+
+ if( requestMethod ) {
+ requestMethod.apply( element );
+ }
+
+ }
+
+ /**
+ * Enters the paused mode which fades everything on screen to
+ * black.
+ */
+ function pause() {
+
+ if( config.pause ) {
+ var wasPaused = dom.wrapper.classList.contains( 'paused' );
+
+ cancelAutoSlide();
+ dom.wrapper.classList.add( 'paused' );
+
+ if( wasPaused === false ) {
+ dispatchEvent( 'paused' );
+ }
+ }
+
+ }
+
+ /**
+ * Exits from the paused mode.
+ */
+ function resume() {
+
+ var wasPaused = dom.wrapper.classList.contains( 'paused' );
+ dom.wrapper.classList.remove( 'paused' );
+
+ cueAutoSlide();
+
+ if( wasPaused ) {
+ dispatchEvent( 'resumed' );
+ }
+
+ }
+
+ /**
+ * Toggles the paused mode on and off.
+ */
+ function togglePause( override ) {
+
+ if( typeof override === 'boolean' ) {
+ override ? pause() : resume();
+ }
+ else {
+ isPaused() ? resume() : pause();
+ }
+
+ }
+
+ /**
+ * Checks if we are currently in the paused mode.
+ *
+ * @return {Boolean}
+ */
+ function isPaused() {
+
+ return dom.wrapper.classList.contains( 'paused' );
+
+ }
+
+ /**
+ * Toggles the auto slide mode on and off.
+ *
+ * @param {Boolean} [override] Flag which sets the desired state.
+ * True means autoplay starts, false means it stops.
+ */
+
+ function toggleAutoSlide( override ) {
+
+ if( typeof override === 'boolean' ) {
+ override ? resumeAutoSlide() : pauseAutoSlide();
+ }
+
+ else {
+ autoSlidePaused ? resumeAutoSlide() : pauseAutoSlide();
+ }
+
+ }
+
+ /**
+ * Checks if the auto slide mode is currently on.
+ *
+ * @return {Boolean}
+ */
+ function isAutoSliding() {
+
+ return !!( autoSlide && !autoSlidePaused );
+
+ }
+
+ /**
+ * Steps from the current point in the presentation to the
+ * slide which matches the specified horizontal and vertical
+ * indices.
+ *
+ * @param {number} [h=indexh] Horizontal index of the target slide
+ * @param {number} [v=indexv] Vertical index of the target slide
+ * @param {number} [f] Index of a fragment within the
+ * target slide to activate
+ * @param {number} [o] Origin for use in multimaster environments
+ */
+ function slide( h, v, f, o ) {
+
+ // Remember where we were at before
+ previousSlide = currentSlide;
+
+ // Query all horizontal slides in the deck
+ var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR );
+
+ // Abort if there are no slides
+ if( horizontalSlides.length === 0 ) return;
+
+ // If no vertical index is specified and the upcoming slide is a
+ // stack, resume at its previous vertical index
+ if( v === undefined && !isOverview() ) {
+ v = getPreviousVerticalIndex( horizontalSlides[ h ] );
+ }
+
+ // If we were on a vertical stack, remember what vertical index
+ // it was on so we can resume at the same position when returning
+ if( previousSlide && previousSlide.parentNode && previousSlide.parentNode.classList.contains( 'stack' ) ) {
+ setPreviousVerticalIndex( previousSlide.parentNode, indexv );
+ }
+
+ // Remember the state before this slide
+ var stateBefore = state.concat();
+
+ // Reset the state array
+ state.length = 0;
+
+ var indexhBefore = indexh || 0,
+ indexvBefore = indexv || 0;
+
+ // Activate and transition to the new slide
+ indexh = updateSlides( HORIZONTAL_SLIDES_SELECTOR, h === undefined ? indexh : h );
+ indexv = updateSlides( VERTICAL_SLIDES_SELECTOR, v === undefined ? indexv : v );
+
+ // Update the visibility of slides now that the indices have changed
+ updateSlidesVisibility();
+
+ layout();
+
+ // Apply the new state
+ stateLoop: for( var i = 0, len = state.length; i < len; i++ ) {
+ // Check if this state existed on the previous slide. If it
+ // did, we will avoid adding it repeatedly
+ for( var j = 0; j < stateBefore.length; j++ ) {
+ if( stateBefore[j] === state[i] ) {
+ stateBefore.splice( j, 1 );
+ continue stateLoop;
+ }
+ }
+
+ document.documentElement.classList.add( state[i] );
+
+ // Dispatch custom event matching the state's name
+ dispatchEvent( state[i] );
+ }
+
+ // Clean up the remains of the previous state
+ while( stateBefore.length ) {
+ document.documentElement.classList.remove( stateBefore.pop() );
+ }
+
+ // Update the overview if it's currently active
+ if( isOverview() ) {
+ updateOverview();
+ }
+
+ // Find the current horizontal slide and any possible vertical slides
+ // within it
+ var currentHorizontalSlide = horizontalSlides[ indexh ],
+ currentVerticalSlides = currentHorizontalSlide.querySelectorAll( 'section' );
+
+ // Store references to the previous and current slides
+ currentSlide = currentVerticalSlides[ indexv ] || currentHorizontalSlide;
+
+ // Show fragment, if specified
+ if( typeof f !== 'undefined' ) {
+ navigateFragment( f );
+ }
+
+ // Dispatch an event if the slide changed
+ var slideChanged = ( indexh !== indexhBefore || indexv !== indexvBefore );
+ if( slideChanged ) {
+ dispatchEvent( 'slidechanged', {
+ 'indexh': indexh,
+ 'indexv': indexv,
+ 'previousSlide': previousSlide,
+ 'currentSlide': currentSlide,
+ 'origin': o
+ } );
+ }
+ else {
+ // Ensure that the previous slide is never the same as the current
+ previousSlide = null;
+ }
+
+ // Solves an edge case where the previous slide maintains the
+ // 'present' class when navigating between adjacent vertical
+ // stacks
+ if( previousSlide ) {
+ previousSlide.classList.remove( 'present' );
+ previousSlide.setAttribute( 'aria-hidden', 'true' );
+
+ // Reset all slides upon navigate to home
+ // Issue: #285
+ if ( dom.wrapper.querySelector( HOME_SLIDE_SELECTOR ).classList.contains( 'present' ) ) {
+ // Launch async task
+ setTimeout( function () {
+ var slides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.stack') ), i;
+ for( i in slides ) {
+ if( slides[i] ) {
+ // Reset stack
+ setPreviousVerticalIndex( slides[i], 0 );
+ }
+ }
+ }, 0 );
+ }
+ }
+
+ // Handle embedded content
+ if( slideChanged || !previousSlide ) {
+ stopEmbeddedContent( previousSlide );
+ startEmbeddedContent( currentSlide );
+ }
+
+ // Announce the current slide contents, for screen readers
+ dom.statusDiv.textContent = getStatusText( currentSlide );
+
+ updateControls();
+ updateProgress();
+ updateBackground();
+ updateParallax();
+ updateSlideNumber();
+ updateNotes();
+
+ // Update the URL hash
+ writeURL();
+
+ cueAutoSlide();
+
+ }
+
+ /**
+ * Syncs the presentation with the current DOM. Useful
+ * when new slides or control elements are added or when
+ * the configuration has changed.
+ */
+ function sync() {
+
+ // Subscribe to input
+ removeEventListeners();
+ addEventListeners();
+
+ // Force a layout to make sure the current config is accounted for
+ layout();
+
+ // Reflect the current autoSlide value
+ autoSlide = config.autoSlide;
+
+ // Start auto-sliding if it's enabled
+ cueAutoSlide();
+
+ // Re-create the slide backgrounds
+ createBackgrounds();
+
+ // Write the current hash to the URL
+ writeURL();
+
+ sortAllFragments();
+
+ updateControls();
+ updateProgress();
+ updateBackground( true );
+ updateSlideNumber();
+ updateSlidesVisibility();
+ updateNotes();
+
+ formatEmbeddedContent();
+ startEmbeddedContent( currentSlide );
+
+ if( isOverview() ) {
+ layoutOverview();
+ }
+
+ }
+
+ /**
+ * Resets all vertical slides so that only the first
+ * is visible.
+ */
+ function resetVerticalSlides() {
+
+ var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
+ horizontalSlides.forEach( function( horizontalSlide ) {
+
+ var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
+ verticalSlides.forEach( function( verticalSlide, y ) {
+
+ if( y > 0 ) {
+ verticalSlide.classList.remove( 'present' );
+ verticalSlide.classList.remove( 'past' );
+ verticalSlide.classList.add( 'future' );
+ verticalSlide.setAttribute( 'aria-hidden', 'true' );
+ }
+
+ } );
+
+ } );
+
+ }
+
+ /**
+ * Sorts and formats all of fragments in the
+ * presentation.
+ */
+ function sortAllFragments() {
+
+ var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
+ horizontalSlides.forEach( function( horizontalSlide ) {
+
+ var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
+ verticalSlides.forEach( function( verticalSlide, y ) {
+
+ sortFragments( verticalSlide.querySelectorAll( '.fragment' ) );
+
+ } );
+
+ if( verticalSlides.length === 0 ) sortFragments( horizontalSlide.querySelectorAll( '.fragment' ) );
+
+ } );
+
+ }
+
+ /**
+ * Randomly shuffles all slides in the deck.
+ */
+ function shuffle() {
+
+ var slides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
+
+ slides.forEach( function( slide ) {
+
+ // Insert this slide next to another random slide. This may
+ // cause the slide to insert before itself but that's fine.
+ dom.slides.insertBefore( slide, slides[ Math.floor( Math.random() * slides.length ) ] );
+
+ } );
+
+ }
+
+ /**
+ * Updates one dimension of slides by showing the slide
+ * with the specified index.
+ *
+ * @param {string} selector A CSS selector that will fetch
+ * the group of slides we are working with
+ * @param {number} index The index of the slide that should be
+ * shown
+ *
+ * @return {number} The index of the slide that is now shown,
+ * might differ from the passed in index if it was out of
+ * bounds.
+ */
+ function updateSlides( selector, index ) {
+
+ // Select all slides and convert the NodeList result to
+ // an array
+ var slides = toArray( dom.wrapper.querySelectorAll( selector ) ),
+ slidesLength = slides.length;
+
+ var printMode = isPrintingPDF();
+
+ if( slidesLength ) {
+
+ // Should the index loop?
+ if( config.loop ) {
+ index %= slidesLength;
+
+ if( index < 0 ) {
+ index = slidesLength + index;
+ }
+ }
+
+ // Enforce max and minimum index bounds
+ index = Math.max( Math.min( index, slidesLength - 1 ), 0 );
+
+ for( var i = 0; i < slidesLength; i++ ) {
+ var element = slides[i];
+
+ var reverse = config.rtl && !isVerticalSlide( element );
+
+ element.classList.remove( 'past' );
+ element.classList.remove( 'present' );
+ element.classList.remove( 'future' );
+
+ // http://www.w3.org/html/wg/drafts/html/master/editing.html#the-hidden-attribute
+ element.setAttribute( 'hidden', '' );
+ element.setAttribute( 'aria-hidden', 'true' );
+
+ // If this element contains vertical slides
+ if( element.querySelector( 'section' ) ) {
+ element.classList.add( 'stack' );
+ }
+
+ // If we're printing static slides, all slides are "present"
+ if( printMode ) {
+ element.classList.add( 'present' );
+ continue;
+ }
+
+ if( i < index ) {
+ // Any element previous to index is given the 'past' class
+ element.classList.add( reverse ? 'future' : 'past' );
+
+ if( config.fragments ) {
+ var pastFragments = toArray( element.querySelectorAll( '.fragment' ) );
+
+ // Show all fragments on prior slides
+ while( pastFragments.length ) {
+ var pastFragment = pastFragments.pop();
+ pastFragment.classList.add( 'visible' );
+ pastFragment.classList.remove( 'current-fragment' );
+ }
+ }
+ }
+ else if( i > index ) {
+ // Any element subsequent to index is given the 'future' class
+ element.classList.add( reverse ? 'past' : 'future' );
+
+ if( config.fragments ) {
+ var futureFragments = toArray( element.querySelectorAll( '.fragment.visible' ) );
+
+ // No fragments in future slides should be visible ahead of time
+ while( futureFragments.length ) {
+ var futureFragment = futureFragments.pop();
+ futureFragment.classList.remove( 'visible' );
+ futureFragment.classList.remove( 'current-fragment' );
+ }
+ }
+ }
+ }
+
+ // Mark the current slide as present
+ slides[index].classList.add( 'present' );
+ slides[index].removeAttribute( 'hidden' );
+ slides[index].removeAttribute( 'aria-hidden' );
+
+ // If this slide has a state associated with it, add it
+ // onto the current state of the deck
+ var slideState = slides[index].getAttribute( 'data-state' );
+ if( slideState ) {
+ state = state.concat( slideState.split( ' ' ) );
+ }
+
+ }
+ else {
+ // Since there are no slides we can't be anywhere beyond the
+ // zeroth index
+ index = 0;
+ }
+
+ return index;
+
+ }
+
+ /**
+ * Optimization method; hide all slides that are far away
+ * from the present slide.
+ */
+ function updateSlidesVisibility() {
+
+ // Select all slides and convert the NodeList result to
+ // an array
+ var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ),
+ horizontalSlidesLength = horizontalSlides.length,
+ distanceX,
+ distanceY;
+
+ if( horizontalSlidesLength && typeof indexh !== 'undefined' ) {
+
+ // The number of steps away from the present slide that will
+ // be visible
+ var viewDistance = isOverview() ? 10 : config.viewDistance;
+
+ // Limit view distance on weaker devices
+ if( isMobileDevice ) {
+ viewDistance = isOverview() ? 6 : 2;
+ }
+
+ // All slides need to be visible when exporting to PDF
+ if( isPrintingPDF() ) {
+ viewDistance = Number.MAX_VALUE;
+ }
+
+ for( var x = 0; x < horizontalSlidesLength; x++ ) {
+ var horizontalSlide = horizontalSlides[x];
+
+ var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) ),
+ verticalSlidesLength = verticalSlides.length;
+
+ // Determine how far away this slide is from the present
+ distanceX = Math.abs( ( indexh || 0 ) - x ) || 0;
+
+ // If the presentation is looped, distance should measure
+ // 1 between the first and last slides
+ if( config.loop ) {
+ distanceX = Math.abs( ( ( indexh || 0 ) - x ) % ( horizontalSlidesLength - viewDistance ) ) || 0;
+ }
+
+ // Show the horizontal slide if it's within the view distance
+ if( distanceX < viewDistance ) {
+ showSlide( horizontalSlide );
+ }
+ else {
+ hideSlide( horizontalSlide );
+ }
+
+ if( verticalSlidesLength ) {
+
+ var oy = getPreviousVerticalIndex( horizontalSlide );
+
+ for( var y = 0; y < verticalSlidesLength; y++ ) {
+ var verticalSlide = verticalSlides[y];
+
+ distanceY = x === ( indexh || 0 ) ? Math.abs( ( indexv || 0 ) - y ) : Math.abs( y - oy );
+
+ if( distanceX + distanceY < viewDistance ) {
+ showSlide( verticalSlide );
+ }
+ else {
+ hideSlide( verticalSlide );
+ }
+ }
+
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * Pick up notes from the current slide and display them
+ * to the viewer.
+ *
+ * @see {@link config.showNotes}
+ */
+ function updateNotes() {
+
+ if( config.showNotes && dom.speakerNotes && currentSlide && !isPrintingPDF() ) {
+
+ dom.speakerNotes.innerHTML = getSlideNotes() || '';
+
+ }
+
+ }
+
+ /**
+ * Updates the progress bar to reflect the current slide.
+ */
+ function updateProgress() {
+
+ // Update progress if enabled
+ if( config.progress && dom.progressbar ) {
+
+ dom.progressbar.style.width = getProgress() * dom.wrapper.offsetWidth + 'px';
+
+ }
+
+ }
+
+ /**
+ * Updates the slide number div to reflect the current slide.
+ *
+ * The following slide number formats are available:
+ * "h.v": horizontal . vertical slide number (default)
+ * "h/v": horizontal / vertical slide number
+ * "c": flattened slide number
+ * "c/t": flattened slide number / total slides
+ */
+ function updateSlideNumber() {
+
+ // Update slide number if enabled
+ if( config.slideNumber && dom.slideNumber ) {
+
+ var value = [];
+ var format = 'h.v';
+
+ // Check if a custom number format is available
+ if( typeof config.slideNumber === 'string' ) {
+ format = config.slideNumber;
+ }
+
+ switch( format ) {
+ case 'c':
+ value.push( getSlidePastCount() + 1 );
+ break;
+ case 'c/t':
+ value.push( getSlidePastCount() + 1, '/', getTotalSlides() );
+ break;
+ case 'h/v':
+ value.push( indexh + 1 );
+ if( isVerticalSlide() ) value.push( '/', indexv + 1 );
+ break;
+ default:
+ value.push( indexh + 1 );
+ if( isVerticalSlide() ) value.push( '.', indexv + 1 );
+ }
+
+ dom.slideNumber.innerHTML = formatSlideNumber( value[0], value[1], value[2] );
+ }
+
+ }
+
+ /**
+ * Applies HTML formatting to a slide number before it's
+ * written to the DOM.
+ *
+ * @param {number} a Current slide
+ * @param {string} delimiter Character to separate slide numbers
+ * @param {(number|*)} b Total slides
+ * @return {string} HTML string fragment
+ */
+ function formatSlideNumber( a, delimiter, b ) {
+
+ if( typeof b === 'number' && !isNaN( b ) ) {
+ return '<span class="slide-number-a">'+ a +'</span>' +
+ '<span class="slide-number-delimiter">'+ delimiter +'</span>' +
+ '<span class="slide-number-b">'+ b +'</span>';
+ }
+ else {
+ return '<span class="slide-number-a">'+ a +'</span>';
+ }
+
+ }
+
+ /**
+ * Updates the state of all control/navigation arrows.
+ */
+ function updateControls() {
+
+ var routes = availableRoutes();
+ var fragments = availableFragments();
+
+ // Remove the 'enabled' class from all directions
+ dom.controlsLeft.concat( dom.controlsRight )
+ .concat( dom.controlsUp )
+ .concat( dom.controlsDown )
+ .concat( dom.controlsPrev )
+ .concat( dom.controlsNext ).forEach( function( node ) {
+ node.classList.remove( 'enabled' );
+ node.classList.remove( 'fragmented' );
+
+ // Set 'disabled' attribute on all directions
+ node.setAttribute( 'disabled', 'disabled' );
+ } );
+
+ // Add the 'enabled' class to the available routes; remove 'disabled' attribute to enable buttons
+ if( routes.left ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
+ if( routes.right ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
+ if( routes.up ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
+ if( routes.down ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
+
+ // Prev/next buttons
+ if( routes.left || routes.up ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
+ if( routes.right || routes.down ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
+
+ // Highlight fragment directions
+ if( currentSlide ) {
+
+ // Always apply fragment decorator to prev/next buttons
+ if( fragments.prev ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
+ if( fragments.next ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
+
+ // Apply fragment decorators to directional buttons based on
+ // what slide axis they are in
+ if( isVerticalSlide( currentSlide ) ) {
+ if( fragments.prev ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
+ if( fragments.next ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
+ }
+ else {
+ if( fragments.prev ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
+ if( fragments.next ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
+ }
+
+ }
+
+ }
+
+ /**
+ * Updates the background elements to reflect the current
+ * slide.
+ *
+ * @param {boolean} includeAll If true, the backgrounds of
+ * all vertical slides (not just the present) will be updated.
+ */
+ function updateBackground( includeAll ) {
+
+ var currentBackground = null;
+
+ // Reverse past/future classes when in RTL mode
+ var horizontalPast = config.rtl ? 'future' : 'past',
+ horizontalFuture = config.rtl ? 'past' : 'future';
+
+ // Update the classes of all backgrounds to match the
+ // states of their slides (past/present/future)
+ toArray( dom.background.childNodes ).forEach( function( backgroundh, h ) {
+
+ backgroundh.classList.remove( 'past' );
+ backgroundh.classList.remove( 'present' );
+ backgroundh.classList.remove( 'future' );
+
+ if( h < indexh ) {
+ backgroundh.classList.add( horizontalPast );
+ }
+ else if ( h > indexh ) {
+ backgroundh.classList.add( horizontalFuture );
+ }
+ else {
+ backgroundh.classList.add( 'present' );
+
+ // Store a reference to the current background element
+ currentBackground = backgroundh;
+ }
+
+ if( includeAll || h === indexh ) {
+ toArray( backgroundh.querySelectorAll( '.slide-background' ) ).forEach( function( backgroundv, v ) {
+
+ backgroundv.classList.remove( 'past' );
+ backgroundv.classList.remove( 'present' );
+ backgroundv.classList.remove( 'future' );
+
+ if( v < indexv ) {
+ backgroundv.classList.add( 'past' );
+ }
+ else if ( v > indexv ) {
+ backgroundv.classList.add( 'future' );
+ }
+ else {
+ backgroundv.classList.add( 'present' );
+
+ // Only if this is the present horizontal and vertical slide
+ if( h === indexh ) currentBackground = backgroundv;
+ }
+
+ } );
+ }
+
+ } );
+
+ // Stop any currently playing video background
+ if( previousBackground ) {
+
+ var previousVideo = previousBackground.querySelector( 'video' );
+ if( previousVideo ) previousVideo.pause();
+
+ }
+
+ if( currentBackground ) {
+
+ // Start video playback
+ var currentVideo = currentBackground.querySelector( 'video' );
+ if( currentVideo ) {
+
+ var startVideo = function() {
+ currentVideo.currentTime = 0;
+ currentVideo.play();
+ currentVideo.removeEventListener( 'loadeddata', startVideo );
+ };
+
+ if( currentVideo.readyState > 1 ) {
+ startVideo();
+ }
+ else {
+ currentVideo.addEventListener( 'loadeddata', startVideo );
+ }
+
+ }
+
+ var backgroundImageURL = currentBackground.style.backgroundImage || '';
+
+ // Restart GIFs (doesn't work in Firefox)
+ if( /\.gif/i.test( backgroundImageURL ) ) {
+ currentBackground.style.backgroundImage = '';
+ window.getComputedStyle( currentBackground ).opacity;
+ currentBackground.style.backgroundImage = backgroundImageURL;
+ }
+
+ // Don't transition between identical backgrounds. This
+ // prevents unwanted flicker.
+ var previousBackgroundHash = previousBackground ? previousBackground.getAttribute( 'data-background-hash' ) : null;
+ var currentBackgroundHash = currentBackground.getAttribute( 'data-background-hash' );
+ if( currentBackgroundHash && currentBackgroundHash === previousBackgroundHash && currentBackground !== previousBackground ) {
+ dom.background.classList.add( 'no-transition' );
+ }
+
+ previousBackground = currentBackground;
+
+ }
+
+ // If there's a background brightness flag for this slide,
+ // bubble it to the .reveal container
+ if( currentSlide ) {
+ [ 'has-light-background', 'has-dark-background' ].forEach( function( classToBubble ) {
+ if( currentSlide.classList.contains( classToBubble ) ) {
+ dom.wrapper.classList.add( classToBubble );
+ }
+ else {
+ dom.wrapper.classList.remove( classToBubble );
+ }
+ } );
+ }
+
+ // Allow the first background to apply without transition
+ setTimeout( function() {
+ dom.background.classList.remove( 'no-transition' );
+ }, 1 );
+
+ }
+
+ /**
+ * Updates the position of the parallax background based
+ * on the current slide index.
+ */
+ function updateParallax() {
+
+ if( config.parallaxBackgroundImage ) {
+
+ var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ),
+ verticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR );
+
+ var backgroundSize = dom.background.style.backgroundSize.split( ' ' ),
+ backgroundWidth, backgroundHeight;
+
+ if( backgroundSize.length === 1 ) {
+ backgroundWidth = backgroundHeight = parseInt( backgroundSize[0], 10 );
+ }
+ else {
+ backgroundWidth = parseInt( backgroundSize[0], 10 );
+ backgroundHeight = parseInt( backgroundSize[1], 10 );
+ }
+
+ var slideWidth = dom.background.offsetWidth,
+ horizontalSlideCount = horizontalSlides.length,
+ horizontalOffsetMultiplier,
+ horizontalOffset;
+
+ if( typeof config.parallaxBackgroundHorizontal === 'number' ) {
+ horizontalOffsetMultiplier = config.parallaxBackgroundHorizontal;
+ }
+ else {
+ horizontalOffsetMultiplier = horizontalSlideCount > 1 ? ( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 ) : 0;
+ }
+
+ horizontalOffset = horizontalOffsetMultiplier * indexh * -1;
+
+ var slideHeight = dom.background.offsetHeight,
+ verticalSlideCount = verticalSlides.length,
+ verticalOffsetMultiplier,
+ verticalOffset;
+
+ if( typeof config.parallaxBackgroundVertical === 'number' ) {
+ verticalOffsetMultiplier = config.parallaxBackgroundVertical;
+ }
+ else {
+ verticalOffsetMultiplier = ( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 );
+ }
+
+ verticalOffset = verticalSlideCount > 0 ? verticalOffsetMultiplier * indexv : 0;
+
+ dom.background.style.backgroundPosition = horizontalOffset + 'px ' + -verticalOffset + 'px';
+
+ }
+
+ }
+
+ /**
+ * Called when the given slide is within the configured view
+ * distance. Shows the slide element and loads any content
+ * that is set to load lazily (data-src).
+ *
+ * @param {HTMLElement} slide Slide to show
+ */
+ function showSlide( slide ) {
+
+ // Show the slide element
+ slide.style.display = 'block';
+
+ // Media elements with data-src attributes
+ toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src]' ) ).forEach( function( element ) {
+ element.setAttribute( 'src', element.getAttribute( 'data-src' ) );
+ element.removeAttribute( 'data-src' );
+ } );
+
+ // Media elements with <source> children
+ toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( media ) {
+ var sources = 0;
+
+ toArray( media.querySelectorAll( 'source[data-src]' ) ).forEach( function( source ) {
+ source.setAttribute( 'src', source.getAttribute( 'data-src' ) );
+ source.removeAttribute( 'data-src' );
+ sources += 1;
+ } );
+
+ // If we rewrote sources for this video/audio element, we need
+ // to manually tell it to load from its new origin
+ if( sources > 0 ) {
+ media.load();
+ }
+ } );
+
+
+ // Show the corresponding background element
+ var indices = getIndices( slide );
+ var background = getSlideBackground( indices.h, indices.v );
+ if( background ) {
+ background.style.display = 'block';
+
+ // If the background contains media, load it
+ if( background.hasAttribute( 'data-loaded' ) === false ) {
+ background.setAttribute( 'data-loaded', 'true' );
+
+ var backgroundImage = slide.getAttribute( 'data-background-image' ),
+ backgroundVideo = slide.getAttribute( 'data-background-video' ),
+ backgroundVideoLoop = slide.hasAttribute( 'data-background-video-loop' ),
+ backgroundVideoMuted = slide.hasAttribute( 'data-background-video-muted' ),
+ backgroundIframe = slide.getAttribute( 'data-background-iframe' );
+
+ // Images
+ if( backgroundImage ) {
+ background.style.backgroundImage = 'url('+ backgroundImage +')';
+ }
+ // Videos
+ else if ( backgroundVideo && !isSpeakerNotes() ) {
+ var video = document.createElement( 'video' );
+
+ if( backgroundVideoLoop ) {
+ video.setAttribute( 'loop', '' );
+ }
+
+ if( backgroundVideoMuted ) {
+ video.muted = true;
+ }
+
+ // Support comma separated lists of video sources
+ backgroundVideo.split( ',' ).forEach( function( source ) {
+ video.innerHTML += '<source src="'+ source +'">';
+ } );
+
+ background.appendChild( video );
+ }
+ // Iframes
+ else if( backgroundIframe ) {
+ var iframe = document.createElement( 'iframe' );
+ iframe.setAttribute( 'src', backgroundIframe );
+ iframe.style.width = '100%';
+ iframe.style.height = '100%';
+ iframe.style.maxHeight = '100%';
+ iframe.style.maxWidth = '100%';
+
+ background.appendChild( iframe );
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Called when the given slide is moved outside of the
+ * configured view distance.
+ *
+ * @param {HTMLElement} slide
+ */
+ function hideSlide( slide ) {
+
+ // Hide the slide element
+ slide.style.display = 'none';
+
+ // Hide the corresponding background element
+ var indices = getIndices( slide );
+ var background = getSlideBackground( indices.h, indices.v );
+ if( background ) {
+ background.style.display = 'none';
+ }
+
+ }
+
+ /**
+ * Determine what available routes there are for navigation.
+ *
+ * @return {{left: boolean, right: boolean, up: boolean, down: boolean}}
+ */
+ function availableRoutes() {
+
+ var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ),
+ verticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR );
+
+ var routes = {
+ left: indexh > 0 || config.loop,
+ right: indexh < horizontalSlides.length - 1 || config.loop,
+ up: indexv > 0,
+ down: indexv < verticalSlides.length - 1
+ };
+
+ // reverse horizontal controls for rtl
+ if( config.rtl ) {
+ var left = routes.left;
+ routes.left = routes.right;
+ routes.right = left;
+ }
+
+ return routes;
+
+ }
+
+ /**
+ * Returns an object describing the available fragment
+ * directions.
+ *
+ * @return {{prev: boolean, next: boolean}}
+ */
+ function availableFragments() {
+
+ if( currentSlide && config.fragments ) {
+ var fragments = currentSlide.querySelectorAll( '.fragment' );
+ var hiddenFragments = currentSlide.querySelectorAll( '.fragment:not(.visible)' );
+
+ return {
+ prev: fragments.length - hiddenFragments.length > 0,
+ next: !!hiddenFragments.length
+ };
+ }
+ else {
+ return { prev: false, next: false };
+ }
+
+ }
+
+ /**
+ * Enforces origin-specific format rules for embedded media.
+ */
+ function formatEmbeddedContent() {
+
+ var _appendParamToIframeSource = function( sourceAttribute, sourceURL, param ) {
+ toArray( dom.slides.querySelectorAll( 'iframe['+ sourceAttribute +'*="'+ sourceURL +'"]' ) ).forEach( function( el ) {
+ var src = el.getAttribute( sourceAttribute );
+ if( src && src.indexOf( param ) === -1 ) {
+ el.setAttribute( sourceAttribute, src + ( !/\?/.test( src ) ? '?' : '&' ) + param );
+ }
+ });
+ };
+
+ // YouTube frames must include "?enablejsapi=1"
+ _appendParamToIframeSource( 'src', 'youtube.com/embed/', 'enablejsapi=1' );
+ _appendParamToIframeSource( 'data-src', 'youtube.com/embed/', 'enablejsapi=1' );
+
+ // Vimeo frames must include "?api=1"
+ _appendParamToIframeSource( 'src', 'player.vimeo.com/', 'api=1' );
+ _appendParamToIframeSource( 'data-src', 'player.vimeo.com/', 'api=1' );
+
+ }
+
+ /**
+ * Start playback of any embedded content inside of
+ * the given element.
+ *
+ * @param {HTMLElement} slide
+ */
+ function startEmbeddedContent( element ) {
+
+ if( element && !isSpeakerNotes() ) {
+ // Restart GIFs
+ toArray( element.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) {
+ // Setting the same unchanged source like this was confirmed
+ // to work in Chrome, FF & Safari
+ el.setAttribute( 'src', el.getAttribute( 'src' ) );
+ } );
+
+ // HTML5 media elements
+ toArray( element.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
+ if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) {
+ return;
+ }
+
+ if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) {
+ el.play();
+ }
+ } );
+
+ // Normal iframes
+ toArray( element.querySelectorAll( 'iframe[src]' ) ).forEach( function( el ) {
+ if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) {
+ return;
+ }
+
+ startEmbeddedIframe( { target: el } );
+ } );
+
+ // Lazy loading iframes
+ toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) {
+ if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) {
+ return;
+ }
+
+ if( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) {
+ el.removeEventListener( 'load', startEmbeddedIframe ); // remove first to avoid dupes
+ el.addEventListener( 'load', startEmbeddedIframe );
+ el.setAttribute( 'src', el.getAttribute( 'data-src' ) );
+ }
+ } );
+ }
+
+ }
+
+ /**
+ * "Starts" the content of an embedded iframe using the
+ * postMessage API.
+ *
+ * @param {object} event - postMessage API event
+ */
+ function startEmbeddedIframe( event ) {
+
+ var iframe = event.target;
+
+ if( iframe && iframe.contentWindow ) {
+
+ // YouTube postMessage API
+ if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) {
+ iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' );
+ }
+ // Vimeo postMessage API
+ else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) {
+ iframe.contentWindow.postMessage( '{"method":"play"}', '*' );
+ }
+ // Generic postMessage API
+ else {
+ iframe.contentWindow.postMessage( 'slide:start', '*' );
+ }
+
+ }
+
+ }
+
+ /**
+ * Stop playback of any embedded content inside of
+ * the targeted slide.
+ *
+ * @param {HTMLElement} slide
+ */
+ function stopEmbeddedContent( slide ) {
+
+ if( slide && slide.parentNode ) {
+ // HTML5 media elements
+ toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
+ if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {
+ el.pause();
+ }
+ } );
+
+ // Generic postMessage API for non-lazy loaded iframes
+ toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
+ el.contentWindow.postMessage( 'slide:stop', '*' );
+ el.removeEventListener( 'load', startEmbeddedIframe );
+ });
+
+ // YouTube postMessage API
+ toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
+ if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
+ el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' );
+ }
+ });
+
+ // Vimeo postMessage API
+ toArray( slide.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) {
+ if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
+ el.contentWindow.postMessage( '{"method":"pause"}', '*' );
+ }
+ });
+
+ // Lazy loading iframes
+ toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) {
+ // Only removing the src doesn't actually unload the frame
+ // in all browsers (Firefox) so we set it to blank first
+ el.setAttribute( 'src', 'about:blank' );
+ el.removeAttribute( 'src' );
+ } );
+ }
+
+ }
+
+ /**
+ * Returns the number of past slides. This can be used as a global
+ * flattened index for slides.
+ *
+ * @return {number} Past slide count
+ */
+ function getSlidePastCount() {
+
+ var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
+
+ // The number of past slides
+ var pastCount = 0;
+
+ // Step through all slides and count the past ones
+ mainLoop: for( var i = 0; i < horizontalSlides.length; i++ ) {
+
+ var horizontalSlide = horizontalSlides[i];
+ var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
+
+ for( var j = 0; j < verticalSlides.length; j++ ) {
+
+ // Stop as soon as we arrive at the present
+ if( verticalSlides[j].classList.contains( 'present' ) ) {
+ break mainLoop;
+ }
+
+ pastCount++;
+
+ }
+
+ // Stop as soon as we arrive at the present
+ if( horizontalSlide.classList.contains( 'present' ) ) {
+ break;
+ }
+
+ // Don't count the wrapping section for vertical slides
+ if( horizontalSlide.classList.contains( 'stack' ) === false ) {
+ pastCount++;
+ }
+
+ }
+
+ return pastCount;
+
+ }
+
+ /**
+ * Returns a value ranging from 0-1 that represents
+ * how far into the presentation we have navigated.
+ *
+ * @return {number}
+ */
+ function getProgress() {
+
+ // The number of past and total slides
+ var totalCount = getTotalSlides();
+ var pastCount = getSlidePastCount();
+
+ if( currentSlide ) {
+
+ var allFragments = currentSlide.querySelectorAll( '.fragment' );
+
+ // If there are fragments in the current slide those should be
+ // accounted for in the progress.
+ if( allFragments.length > 0 ) {
+ var visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' );
+
+ // This value represents how big a portion of the slide progress
+ // that is made up by its fragments (0-1)
+ var fragmentWeight = 0.9;
+
+ // Add fragment progress to the past slide count
+ pastCount += ( visibleFragments.length / allFragments.length ) * fragmentWeight;
+ }
+
+ }
+
+ return pastCount / ( totalCount - 1 );
+
+ }
+
+ /**
+ * Checks if this presentation is running inside of the
+ * speaker notes window.
+ *
+ * @return {boolean}
+ */
+ function isSpeakerNotes() {
+
+ return !!window.location.search.match( /receiver/gi );
+
+ }
+
+ /**
+ * Reads the current URL (hash) and navigates accordingly.
+ */
+ function readURL() {
+
+ var hash = window.location.hash;
+
+ // Attempt to parse the hash as either an index or name
+ var bits = hash.slice( 2 ).split( '/' ),
+ name = hash.replace( /#|\//gi, '' );
+
+ // If the first bit is invalid and there is a name we can
+ // assume that this is a named link
+ if( isNaN( parseInt( bits[0], 10 ) ) && name.length ) {
+ var element;
+
+ // Ensure the named link is a valid HTML ID attribute
+ if( /^[a-zA-Z][\w:.-]*$/.test( name ) ) {
+ // Find the slide with the specified ID
+ element = document.getElementById( name );
+ }
+
+ if( element ) {
+ // Find the position of the named slide and navigate to it
+ var indices = Reveal.getIndices( element );
+ slide( indices.h, indices.v );
+ }
+ // If the slide doesn't exist, navigate to the current slide
+ else {
+ slide( indexh || 0, indexv || 0 );
+ }
+ }
+ else {
+ // Read the index components of the hash
+ var h = parseInt( bits[0], 10 ) || 0,
+ v = parseInt( bits[1], 10 ) || 0;
+
+ if( h !== indexh || v !== indexv ) {
+ slide( h, v );
+ }
+ }
+
+ }
+
+ /**
+ * Updates the page URL (hash) to reflect the current
+ * state.
+ *
+ * @param {number} delay The time in ms to wait before
+ * writing the hash
+ */
+ function writeURL( delay ) {
+
+ if( config.history ) {
+
+ // Make sure there's never more than one timeout running
+ clearTimeout( writeURLTimeout );
+
+ // If a delay is specified, timeout this call
+ if( typeof delay === 'number' ) {
+ writeURLTimeout = setTimeout( writeURL, delay );
+ }
+ else if( currentSlide ) {
+ var url = '/';
+
+ // Attempt to create a named link based on the slide's ID
+ var id = currentSlide.getAttribute( 'id' );
+ if( id ) {
+ id = id.replace( /[^a-zA-Z0-9\-\_\:\.]/g, '' );
+ }
+
+ // If the current slide has an ID, use that as a named link
+ if( typeof id === 'string' && id.length ) {
+ url = '/' + id;
+ }
+ // Otherwise use the /h/v index
+ else {
+ if( indexh > 0 || indexv > 0 ) url += indexh;
+ if( indexv > 0 ) url += '/' + indexv;
+ }
+
+ window.location.hash = url;
+ }
+ }
+
+ }
+ /**
+ * Retrieves the h/v location and fragment of the current,
+ * or specified, slide.
+ *
+ * @param {HTMLElement} [slide] If specified, the returned
+ * index will be for this slide rather than the currently
+ * active one
+ *
+ * @return {{h: number, v: number, f: number}}
+ */
+ function getIndices( slide ) {
+
+ // By default, return the current indices
+ var h = indexh,
+ v = indexv,
+ f;
+
+ // If a slide is specified, return the indices of that slide
+ if( slide ) {
+ var isVertical = isVerticalSlide( slide );
+ var slideh = isVertical ? slide.parentNode : slide;
+
+ // Select all horizontal slides
+ var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
+
+ // Now that we know which the horizontal slide is, get its index
+ h = Math.max( horizontalSlides.indexOf( slideh ), 0 );
+
+ // Assume we're not vertical
+ v = undefined;
+
+ // If this is a vertical slide, grab the vertical index
+ if( isVertical ) {
+ v = Math.max( toArray( slide.parentNode.querySelectorAll( 'section' ) ).indexOf( slide ), 0 );
+ }
+ }
+
+ if( !slide && currentSlide ) {
+ var hasFragments = currentSlide.querySelectorAll( '.fragment' ).length > 0;
+ if( hasFragments ) {
+ var currentFragment = currentSlide.querySelector( '.current-fragment' );
+ if( currentFragment && currentFragment.hasAttribute( 'data-fragment-index' ) ) {
+ f = parseInt( currentFragment.getAttribute( 'data-fragment-index' ), 10 );
+ }
+ else {
+ f = currentSlide.querySelectorAll( '.fragment.visible' ).length - 1;
+ }
+ }
+ }
+
+ return { h: h, v: v, f: f };
+
+ }
+
+ /**
+ * Retrieves the total number of slides in this presentation.
+ *
+ * @return {number}
+ */
+ function getTotalSlides() {
+
+ return dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack)' ).length;
+
+ }
+
+ /**
+ * Returns the slide element matching the specified index.
+ *
+ * @return {HTMLElement}
+ */
+ function getSlide( x, y ) {
+
+ var horizontalSlide = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR )[ x ];
+ var verticalSlides = horizontalSlide && horizontalSlide.querySelectorAll( 'section' );
+
+ if( verticalSlides && verticalSlides.length && typeof y === 'number' ) {
+ return verticalSlides ? verticalSlides[ y ] : undefined;
+ }
+
+ return horizontalSlide;
+
+ }
+
+ /**
+ * Returns the background element for the given slide.
+ * All slides, even the ones with no background properties
+ * defined, have a background element so as long as the
+ * index is valid an element will be returned.
+ *
+ * @param {number} x Horizontal background index
+ * @param {number} y Vertical background index
+ * @return {(HTMLElement[]|*)}
+ */
+ function getSlideBackground( x, y ) {
+
+ // When printing to PDF the slide backgrounds are nested
+ // inside of the slides
+ if( isPrintingPDF() ) {
+ var slide = getSlide( x, y );
+ if( slide ) {
+ return slide.slideBackgroundElement;
+ }
+
+ return undefined;
+ }
+
+ var horizontalBackground = dom.wrapper.querySelectorAll( '.backgrounds>.slide-background' )[ x ];
+ var verticalBackgrounds = horizontalBackground && horizontalBackground.querySelectorAll( '.slide-background' );
+
+ if( verticalBackgrounds && verticalBackgrounds.length && typeof y === 'number' ) {
+ return verticalBackgrounds ? verticalBackgrounds[ y ] : undefined;
+ }
+
+ return horizontalBackground;
+
+ }
+
+ /**
+ * Retrieves the speaker notes from a slide. Notes can be
+ * defined in two ways:
+ * 1. As a data-notes attribute on the slide <section>
+ * 2. As an <aside class="notes"> inside of the slide
+ *
+ * @param {HTMLElement} [slide=currentSlide]
+ * @return {(string|null)}
+ */
+ function getSlideNotes( slide ) {
+
+ // Default to the current slide
+ slide = slide || currentSlide;
+
+ // Notes can be specified via the data-notes attribute...
+ if( slide.hasAttribute( 'data-notes' ) ) {
+ return slide.getAttribute( 'data-notes' );
+ }
+
+ // ... or using an <aside class="notes"> element
+ var notesElement = slide.querySelector( 'aside.notes' );
+ if( notesElement ) {
+ return notesElement.innerHTML;
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Retrieves the current state of the presentation as
+ * an object. This state can then be restored at any
+ * time.
+ *
+ * @return {{indexh: number, indexv: number, indexf: number, paused: boolean, overview: boolean}}
+ */
+ function getState() {
+
+ var indices = getIndices();
+
+ return {
+ indexh: indices.h,
+ indexv: indices.v,
+ indexf: indices.f,
+ paused: isPaused(),
+ overview: isOverview()
+ };
+
+ }
+
+ /**
+ * Restores the presentation to the given state.
+ *
+ * @param {object} state As generated by getState()
+ * @see {@link getState} generates the parameter `state`
+ */
+ function setState( state ) {
+
+ if( typeof state === 'object' ) {
+ slide( deserialize( state.indexh ), deserialize( state.indexv ), deserialize( state.indexf ) );
+
+ var pausedFlag = deserialize( state.paused ),
+ overviewFlag = deserialize( state.overview );
+
+ if( typeof pausedFlag === 'boolean' && pausedFlag !== isPaused() ) {
+ togglePause( pausedFlag );
+ }
+
+ if( typeof overviewFlag === 'boolean' && overviewFlag !== isOverview() ) {
+ toggleOverview( overviewFlag );
+ }
+ }
+
+ }
+
+ /**
+ * Return a sorted fragments list, ordered by an increasing
+ * "data-fragment-index" attribute.
+ *
+ * Fragments will be revealed in the order that they are returned by
+ * this function, so you can use the index attributes to control the
+ * order of fragment appearance.
+ *
+ * To maintain a sensible default fragment order, fragments are presumed
+ * to be passed in document order. This function adds a "fragment-index"
+ * attribute to each node if such an attribute is not already present,
+ * and sets that attribute to an integer value which is the position of
+ * the fragment within the fragments list.
+ *
+ * @param {object[]|*} fragments
+ * @return {object[]} sorted Sorted array of fragments
+ */
+ function sortFragments( fragments ) {
+
+ fragments = toArray( fragments );
+
+ var ordered = [],
+ unordered = [],
+ sorted = [];
+
+ // Group ordered and unordered elements
+ fragments.forEach( function( fragment, i ) {
+ if( fragment.hasAttribute( 'data-fragment-index' ) ) {
+ var index = parseInt( fragment.getAttribute( 'data-fragment-index' ), 10 );
+
+ if( !ordered[index] ) {
+ ordered[index] = [];
+ }
+
+ ordered[index].push( fragment );
+ }
+ else {
+ unordered.push( [ fragment ] );
+ }
+ } );
+
+ // Append fragments without explicit indices in their
+ // DOM order
+ ordered = ordered.concat( unordered );
+
+ // Manually count the index up per group to ensure there
+ // are no gaps
+ var index = 0;
+
+ // Push all fragments in their sorted order to an array,
+ // this flattens the groups
+ ordered.forEach( function( group ) {
+ group.forEach( function( fragment ) {
+ sorted.push( fragment );
+ fragment.setAttribute( 'data-fragment-index', index );
+ } );
+
+ index ++;
+ } );
+
+ return sorted;
+
+ }
+
+ /**
+ * Navigate to the specified slide fragment.
+ *
+ * @param {?number} index The index of the fragment that
+ * should be shown, -1 means all are invisible
+ * @param {number} offset Integer offset to apply to the
+ * fragment index
+ *
+ * @return {boolean} true if a change was made in any
+ * fragments visibility as part of this call
+ */
+ function navigateFragment( index, offset ) {
+
+ if( currentSlide && config.fragments ) {
+
+ var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment' ) );
+ if( fragments.length ) {
+
+ // If no index is specified, find the current
+ if( typeof index !== 'number' ) {
+ var lastVisibleFragment = sortFragments( currentSlide.querySelectorAll( '.fragment.visible' ) ).pop();
+
+ if( lastVisibleFragment ) {
+ index = parseInt( lastVisibleFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );
+ }
+ else {
+ index = -1;
+ }
+ }
+
+ // If an offset is specified, apply it to the index
+ if( typeof offset === 'number' ) {
+ index += offset;
+ }
+
+ var fragmentsShown = [],
+ fragmentsHidden = [];
+
+ toArray( fragments ).forEach( function( element, i ) {
+
+ if( element.hasAttribute( 'data-fragment-index' ) ) {
+ i = parseInt( element.getAttribute( 'data-fragment-index' ), 10 );
+ }
+
+ // Visible fragments
+ if( i <= index ) {
+ if( !element.classList.contains( 'visible' ) ) fragmentsShown.push( element );
+ element.classList.add( 'visible' );
+ element.classList.remove( 'current-fragment' );
+
+ // Announce the fragments one by one to the Screen Reader
+ dom.statusDiv.textContent = getStatusText( element );
+
+ if( i === index ) {
+ element.classList.add( 'current-fragment' );
+ startEmbeddedContent( element );
+ }
+ }
+ // Hidden fragments
+ else {
+ if( element.classList.contains( 'visible' ) ) fragmentsHidden.push( element );
+ element.classList.remove( 'visible' );
+ element.classList.remove( 'current-fragment' );
+ }
+
+ } );
+
+ if( fragmentsHidden.length ) {
+ dispatchEvent( 'fragmenthidden', { fragment: fragmentsHidden[0], fragments: fragmentsHidden } );
+ }
+
+ if( fragmentsShown.length ) {
+ dispatchEvent( 'fragmentshown', { fragment: fragmentsShown[0], fragments: fragmentsShown } );
+ }
+
+ updateControls();
+ updateProgress();
+
+ return !!( fragmentsShown.length || fragmentsHidden.length );
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+ /**
+ * Navigate to the next slide fragment.
+ *
+ * @return {boolean} true if there was a next fragment,
+ * false otherwise
+ */
+ function nextFragment() {
+
+ return navigateFragment( null, 1 );
+
+ }
+
+ /**
+ * Navigate to the previous slide fragment.
+ *
+ * @return {boolean} true if there was a previous fragment,
+ * false otherwise
+ */
+ function previousFragment() {
+
+ return navigateFragment( null, -1 );
+
+ }
+
+ /**
+ * Cues a new automated slide if enabled in the config.
+ */
+ function cueAutoSlide() {
+
+ cancelAutoSlide();
+
+ if( currentSlide ) {
+
+ var fragment = currentSlide.querySelector( '.current-fragment' );
+
+ // When the slide first appears there is no "current" fragment so
+ // we look for a data-autoslide timing on the first fragment
+ if( !fragment ) fragment = currentSlide.querySelector( '.fragment' );
+
+ var fragmentAutoSlide = fragment ? fragment.getAttribute( 'data-autoslide' ) : null;
+ var parentAutoSlide = currentSlide.parentNode ? currentSlide.parentNode.getAttribute( 'data-autoslide' ) : null;
+ var slideAutoSlide = currentSlide.getAttribute( 'data-autoslide' );
+
+ // Pick value in the following priority order:
+ // 1. Current fragment's data-autoslide
+ // 2. Current slide's data-autoslide
+ // 3. Parent slide's data-autoslide
+ // 4. Global autoSlide setting
+ if( fragmentAutoSlide ) {
+ autoSlide = parseInt( fragmentAutoSlide, 10 );
+ }
+ else if( slideAutoSlide ) {
+ autoSlide = parseInt( slideAutoSlide, 10 );
+ }
+ else if( parentAutoSlide ) {
+ autoSlide = parseInt( parentAutoSlide, 10 );
+ }
+ else {
+ autoSlide = config.autoSlide;
+ }
+
+ // If there are media elements with data-autoplay,
+ // automatically set the autoSlide duration to the
+ // length of that media. Not applicable if the slide
+ // is divided up into fragments.
+ // playbackRate is accounted for in the duration.
+ if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {
+ toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
+ if( el.hasAttribute( 'data-autoplay' ) ) {
+ if( autoSlide && (el.duration * 1000 / el.playbackRate ) > autoSlide ) {
+ autoSlide = ( el.duration * 1000 / el.playbackRate ) + 1000;
+ }
+ }
+ } );
+ }
+
+ // Cue the next auto-slide if:
+ // - There is an autoSlide value
+ // - Auto-sliding isn't paused by the user
+ // - The presentation isn't paused
+ // - The overview isn't active
+ // - The presentation isn't over
+ if( autoSlide && !autoSlidePaused && !isPaused() && !isOverview() && ( !Reveal.isLastSlide() || availableFragments().next || config.loop === true ) ) {
+ autoSlideTimeout = setTimeout( function() {
+ typeof config.autoSlideMethod === 'function' ? config.autoSlideMethod() : navigateNext();
+ cueAutoSlide();
+ }, autoSlide );
+ autoSlideStartTime = Date.now();
+ }
+
+ if( autoSlidePlayer ) {
+ autoSlidePlayer.setPlaying( autoSlideTimeout !== -1 );
+ }
+
+ }
+
+ }
+
+ /**
+ * Cancels any ongoing request to auto-slide.
+ */
+ function cancelAutoSlide() {
+
+ clearTimeout( autoSlideTimeout );
+ autoSlideTimeout = -1;
+
+ }
+
+ function pauseAutoSlide() {
+
+ if( autoSlide && !autoSlidePaused ) {
+ autoSlidePaused = true;
+ dispatchEvent( 'autoslidepaused' );
+ clearTimeout( autoSlideTimeout );
+
+ if( autoSlidePlayer ) {
+ autoSlidePlayer.setPlaying( false );
+ }
+ }
+
+ }
+
+ function resumeAutoSlide() {
+
+ if( autoSlide && autoSlidePaused ) {
+ autoSlidePaused = false;
+ dispatchEvent( 'autoslideresumed' );
+ cueAutoSlide();
+ }
+
+ }
+
+ function navigateLeft() {
+
+ // Reverse for RTL
+ if( config.rtl ) {
+ if( ( isOverview() || nextFragment() === false ) && availableRoutes().left ) {
+ slide( indexh + 1 );
+ }
+ }
+ // Normal navigation
+ else if( ( isOverview() || previousFragment() === false ) && availableRoutes().left ) {
+ slide( indexh - 1 );
+ }
+
+ }
+
+ function navigateRight() {
+
+ // Reverse for RTL
+ if( config.rtl ) {
+ if( ( isOverview() || previousFragment() === false ) && availableRoutes().right ) {
+ slide( indexh - 1 );
+ }
+ }
+ // Normal navigation
+ else if( ( isOverview() || nextFragment() === false ) && availableRoutes().right ) {
+ slide( indexh + 1 );
+ }
+
+ }
+
+ function navigateUp() {
+
+ // Prioritize hiding fragments
+ if( ( isOverview() || previousFragment() === false ) && availableRoutes().up ) {
+ slide( indexh, indexv - 1 );
+ }
+
+ }
+
+ function navigateDown() {
+
+ // Prioritize revealing fragments
+ if( ( isOverview() || nextFragment() === false ) && availableRoutes().down ) {
+ slide( indexh, indexv + 1 );
+ }
+
+ }
+
+ /**
+ * Navigates backwards, prioritized in the following order:
+ * 1) Previous fragment
+ * 2) Previous vertical slide
+ * 3) Previous horizontal slide
+ */
+ function navigatePrev() {
+
+ // Prioritize revealing fragments
+ if( previousFragment() === false ) {
+ if( availableRoutes().up ) {
+ navigateUp();
+ }
+ else {
+ // Fetch the previous horizontal slide, if there is one
+ var previousSlide;
+
+ if( config.rtl ) {
+ previousSlide = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.future' ) ).pop();
+ }
+ else {
+ previousSlide = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.past' ) ).pop();
+ }
+
+ if( previousSlide ) {
+ var v = ( previousSlide.querySelectorAll( 'section' ).length - 1 ) || undefined;
+ var h = indexh - 1;
+ slide( h, v );
+ }
+ }
+ }
+
+ }
+
+ /**
+ * The reverse of #navigatePrev().
+ */
+ function navigateNext() {
+
+ // Prioritize revealing fragments
+ if( nextFragment() === false ) {
+ if( availableRoutes().down ) {
+ navigateDown();
+ }
+ else if( config.rtl ) {
+ navigateLeft();
+ }
+ else {
+ navigateRight();
+ }
+ }
+
+ }
+
+ /**
+ * Checks if the target element prevents the triggering of
+ * swipe navigation.
+ */
+ function isSwipePrevented( target ) {
+
+ while( target && typeof target.hasAttribute === 'function' ) {
+ if( target.hasAttribute( 'data-prevent-swipe' ) ) return true;
+ target = target.parentNode;
+ }
+
+ return false;
+
+ }
+
+
+ // --------------------------------------------------------------------//
+ // ----------------------------- EVENTS -------------------------------//
+ // --------------------------------------------------------------------//
+
+ /**
+ * Called by all event handlers that are based on user
+ * input.
+ *
+ * @param {object} [event]
+ */
+ function onUserInput( event ) {
+
+ if( config.autoSlideStoppable ) {
+ pauseAutoSlide();
+ }
+
+ }
+
+ /**
+ * Handler for the document level 'keypress' event.
+ *
+ * @param {object} event
+ */
+ function onDocumentKeyPress( event ) {
+
+ // Check if the pressed key is question mark
+ if( event.shiftKey && event.charCode === 63 ) {
+ if( dom.overlay ) {
+ closeOverlay();
+ }
+ else {
+ showHelp( true );
+ }
+ }
+
+ }
+
+ /**
+ * Handler for the document level 'keydown' event.
+ *
+ * @param {object} event
+ */
+ function onDocumentKeyDown( event ) {
+
+ // If there's a condition specified and it returns false,
+ // ignore this event
+ if( typeof config.keyboardCondition === 'function' && config.keyboardCondition() === false ) {
+ return true;
+ }
+
+ // Remember if auto-sliding was paused so we can toggle it
+ var autoSlideWasPaused = autoSlidePaused;
+
+ onUserInput( event );
+
+ // Check if there's a focused element that could be using
+ // the keyboard
+ var activeElementIsCE = document.activeElement && document.activeElement.contentEditable !== 'inherit';
+ var activeElementIsInput = document.activeElement && document.activeElement.tagName && /input|textarea/i.test( document.activeElement.tagName );
+ var activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className);
+
+ // Disregard the event if there's a focused element or a
+ // keyboard modifier key is present
+ if( activeElementIsCE || activeElementIsInput || activeElementIsNotes || (event.shiftKey && event.keyCode !== 32) || event.altKey || event.ctrlKey || event.metaKey ) return;
+
+ // While paused only allow resume keyboard events; 'b', 'v', '.'
+ var resumeKeyCodes = [66,86,190,191];
+ var key;
+
+ // Custom key bindings for togglePause should be able to resume
+ if( typeof config.keyboard === 'object' ) {
+ for( key in config.keyboard ) {
+ if( config.keyboard[key] === 'togglePause' ) {
+ resumeKeyCodes.push( parseInt( key, 10 ) );
+ }
+ }
+ }
+
+ if( isPaused() && resumeKeyCodes.indexOf( event.keyCode ) === -1 ) {
+ return false;
+ }
+
+ var triggered = false;
+
+ // 1. User defined key bindings
+ if( typeof config.keyboard === 'object' ) {
+
+ for( key in config.keyboard ) {
+
+ // Check if this binding matches the pressed key
+ if( parseInt( key, 10 ) === event.keyCode ) {
+
+ var value = config.keyboard[ key ];
+
+ // Callback function
+ if( typeof value === 'function' ) {
+ value.apply( null, [ event ] );
+ }
+ // String shortcuts to reveal.js API
+ else if( typeof value === 'string' && typeof Reveal[ value ] === 'function' ) {
+ Reveal[ value ].call();
+ }
+
+ triggered = true;
+
+ }
+
+ }
+
+ }
+
+ // 2. System defined key bindings
+ if( triggered === false ) {
+
+ // Assume true and try to prove false
+ triggered = true;
+
+ switch( event.keyCode ) {
+ // p, page up
+ case 80: case 33: navigatePrev(); break;
+ // n, page down
+ case 78: case 34: navigateNext(); break;
+ // h, left
+ case 72: case 37: navigateLeft(); break;
+ // l, right
+ case 76: case 39: navigateRight(); break;
+ // k, up
+ case 75: case 38: navigateUp(); break;
+ // j, down
+ case 74: case 40: navigateDown(); break;
+ // home
+ case 36: slide( 0 ); break;
+ // end
+ case 35: slide( Number.MAX_VALUE ); break;
+ // space
+ case 32: isOverview() ? deactivateOverview() : event.shiftKey ? navigatePrev() : navigateNext(); break;
+ // return
+ case 13: isOverview() ? deactivateOverview() : triggered = false; break;
+ // two-spot, semicolon, b, v, period, Logitech presenter tools "black screen" button
+ case 58: case 59: case 66: case 86: case 190: case 191: togglePause(); break;
+ // f
+ case 70: enterFullscreen(); break;
+ // a
+ case 65: if ( config.autoSlideStoppable ) toggleAutoSlide( autoSlideWasPaused ); break;
+ default:
+ triggered = false;
+ }
+
+ }
+
+ // If the input resulted in a triggered action we should prevent
+ // the browsers default behavior
+ if( triggered ) {
+ event.preventDefault && event.preventDefault();
+ }
+ // ESC or O key
+ else if ( ( event.keyCode === 27 || event.keyCode === 79 ) && features.transforms3d ) {
+ if( dom.overlay ) {
+ closeOverlay();
+ }
+ else {
+ toggleOverview();
+ }
+
+ event.preventDefault && event.preventDefault();
+ }
+
+ // If auto-sliding is enabled we need to cue up
+ // another timeout
+ cueAutoSlide();
+
+ }
+
+ /**
+ * Handler for the 'touchstart' event, enables support for
+ * swipe and pinch gestures.
+ *
+ * @param {object} event
+ */
+ function onTouchStart( event ) {
+
+ if( isSwipePrevented( event.target ) ) return true;
+
+ touch.startX = event.touches[0].clientX;
+ touch.startY = event.touches[0].clientY;
+ touch.startCount = event.touches.length;
+
+ // If there's two touches we need to memorize the distance
+ // between those two points to detect pinching
+ if( event.touches.length === 2 && config.overview ) {
+ touch.startSpan = distanceBetween( {
+ x: event.touches[1].clientX,
+ y: event.touches[1].clientY
+ }, {
+ x: touch.startX,
+ y: touch.startY
+ } );
+ }
+
+ }
+
+ /**
+ * Handler for the 'touchmove' event.
+ *
+ * @param {object} event
+ */
+ function onTouchMove( event ) {
+
+ if( isSwipePrevented( event.target ) ) return true;
+
+ // Each touch should only trigger one action
+ if( !touch.captured ) {
+ onUserInput( event );
+
+ var currentX = event.touches[0].clientX;
+ var currentY = event.touches[0].clientY;
+
+ // If the touch started with two points and still has
+ // two active touches; test for the pinch gesture
+ if( event.touches.length === 2 && touch.startCount === 2 && config.overview ) {
+
+ // The current distance in pixels between the two touch points
+ var currentSpan = distanceBetween( {
+ x: event.touches[1].clientX,
+ y: event.touches[1].clientY
+ }, {
+ x: touch.startX,
+ y: touch.startY
+ } );
+
+ // If the span is larger than the desire amount we've got
+ // ourselves a pinch
+ if( Math.abs( touch.startSpan - currentSpan ) > touch.threshold ) {
+ touch.captured = true;
+
+ if( currentSpan < touch.startSpan ) {
+ activateOverview();
+ }
+ else {
+ deactivateOverview();
+ }
+ }
+
+ event.preventDefault();
+
+ }
+ // There was only one touch point, look for a swipe
+ else if( event.touches.length === 1 && touch.startCount !== 2 ) {
+
+ var deltaX = currentX - touch.startX,
+ deltaY = currentY - touch.startY;
+
+ if( deltaX > touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
+ touch.captured = true;
+ navigateLeft();
+ }
+ else if( deltaX < -touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
+ touch.captured = true;
+ navigateRight();
+ }
+ else if( deltaY > touch.threshold ) {
+ touch.captured = true;
+ navigateUp();
+ }
+ else if( deltaY < -touch.threshold ) {
+ touch.captured = true;
+ navigateDown();
+ }
+
+ // If we're embedded, only block touch events if they have
+ // triggered an action
+ if( config.embedded ) {
+ if( touch.captured || isVerticalSlide( currentSlide ) ) {
+ event.preventDefault();
+ }
+ }
+ // Not embedded? Block them all to avoid needless tossing
+ // around of the viewport in iOS
+ else {
+ event.preventDefault();
+ }
+
+ }
+ }
+ // There's a bug with swiping on some Android devices unless
+ // the default action is always prevented
+ else if( UA.match( /android/gi ) ) {
+ event.preventDefault();
+ }
+
+ }
+
+ /**
+ * Handler for the 'touchend' event.
+ *
+ * @param {object} event
+ */
+ function onTouchEnd( event ) {
+
+ touch.captured = false;
+
+ }
+
+ /**
+ * Convert pointer down to touch start.
+ *
+ * @param {object} event
+ */
+ function onPointerDown( event ) {
+
+ if( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === "touch" ) {
+ event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
+ onTouchStart( event );
+ }
+
+ }
+
+ /**
+ * Convert pointer move to touch move.
+ *
+ * @param {object} event
+ */
+ function onPointerMove( event ) {
+
+ if( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === "touch" ) {
+ event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
+ onTouchMove( event );
+ }
+
+ }
+
+ /**
+ * Convert pointer up to touch end.
+ *
+ * @param {object} event
+ */
+ function onPointerUp( event ) {
+
+ if( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === "touch" ) {
+ event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
+ onTouchEnd( event );
+ }
+
+ }
+
+ /**
+ * Handles mouse wheel scrolling, throttled to avoid skipping
+ * multiple slides.
+ *
+ * @param {object} event
+ */
+ function onDocumentMouseScroll( event ) {
+
+ if( Date.now() - lastMouseWheelStep > 600 ) {
+
+ lastMouseWheelStep = Date.now();
+
+ var delta = event.detail || -event.wheelDelta;
+ if( delta > 0 ) {
+ navigateNext();
+ }
+ else if( delta < 0 ) {
+ navigatePrev();
+ }
+
+ }
+
+ }
+
+ /**
+ * Clicking on the progress bar results in a navigation to the
+ * closest approximate horizontal slide using this equation:
+ *
+ * ( clickX / presentationWidth ) * numberOfSlides
+ *
+ * @param {object} event
+ */
+ function onProgressClicked( event ) {
+
+ onUserInput( event );
+
+ event.preventDefault();
+
+ var slidesTotal = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).length;
+ var slideIndex = Math.floor( ( event.clientX / dom.wrapper.offsetWidth ) * slidesTotal );
+
+ if( config.rtl ) {
+ slideIndex = slidesTotal - slideIndex;
+ }
+
+ slide( slideIndex );
+
+ }
+
+ /**
+ * Event handler for navigation control buttons.
+ */
+ function onNavigateLeftClicked( event ) { event.preventDefault(); onUserInput(); navigateLeft(); }
+ function onNavigateRightClicked( event ) { event.preventDefault(); onUserInput(); navigateRight(); }
+ function onNavigateUpClicked( event ) { event.preventDefault(); onUserInput(); navigateUp(); }
+ function onNavigateDownClicked( event ) { event.preventDefault(); onUserInput(); navigateDown(); }
+ function onNavigatePrevClicked( event ) { event.preventDefault(); onUserInput(); navigatePrev(); }
+ function onNavigateNextClicked( event ) { event.preventDefault(); onUserInput(); navigateNext(); }
+
+ /**
+ * Handler for the window level 'hashchange' event.
+ *
+ * @param {object} [event]
+ */
+ function onWindowHashChange( event ) {
+
+ readURL();
+
+ }
+
+ /**
+ * Handler for the window level 'resize' event.
+ *
+ * @param {object} [event]
+ */
+ function onWindowResize( event ) {
+
+ layout();
+
+ }
+
+ /**
+ * Handle for the window level 'visibilitychange' event.
+ *
+ * @param {object} [event]
+ */
+ function onPageVisibilityChange( event ) {
+
+ var isHidden = document.webkitHidden ||
+ document.msHidden ||
+ document.hidden;
+
+ // If, after clicking a link or similar and we're coming back,
+ // focus the document.body to ensure we can use keyboard shortcuts
+ if( isHidden === false && document.activeElement !== document.body ) {
+ // Not all elements support .blur() - SVGs among them.
+ if( typeof document.activeElement.blur === 'function' ) {
+ document.activeElement.blur();
+ }
+ document.body.focus();
+ }
+
+ }
+
+ /**
+ * Invoked when a slide is and we're in the overview.
+ *
+ * @param {object} event
+ */
+ function onOverviewSlideClicked( event ) {
+
+ // TODO There's a bug here where the event listeners are not
+ // removed after deactivating the overview.
+ if( eventsAreBound && isOverview() ) {
+ event.preventDefault();
+
+ var element = event.target;
+
+ while( element && !element.nodeName.match( /section/gi ) ) {
+ element = element.parentNode;
+ }
+
+ if( element && !element.classList.contains( 'disabled' ) ) {
+
+ deactivateOverview();
+
+ if( element.nodeName.match( /section/gi ) ) {
+ var h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),
+ v = parseInt( element.getAttribute( 'data-index-v' ), 10 );
+
+ slide( h, v );
+ }
+
+ }
+ }
+
+ }
+
+ /**
+ * Handles clicks on links that are set to preview in the
+ * iframe overlay.
+ *
+ * @param {object} event
+ */
+ function onPreviewLinkClicked( event ) {
+
+ if( event.currentTarget && event.currentTarget.hasAttribute( 'href' ) ) {
+ var url = event.currentTarget.getAttribute( 'href' );
+ if( url ) {
+ showPreview( url );
+ event.preventDefault();
+ }
+ }
+
+ }
+
+ /**
+ * Handles click on the auto-sliding controls element.
+ *
+ * @param {object} [event]
+ */
+ function onAutoSlidePlayerClick( event ) {
+
+ // Replay
+ if( Reveal.isLastSlide() && config.loop === false ) {
+ slide( 0, 0 );
+ resumeAutoSlide();
+ }
+ // Resume
+ else if( autoSlidePaused ) {
+ resumeAutoSlide();
+ }
+ // Pause
+ else {
+ pauseAutoSlide();
+ }
+
+ }
+
+
+ // --------------------------------------------------------------------//
+ // ------------------------ PLAYBACK COMPONENT ------------------------//
+ // --------------------------------------------------------------------//
+
+
+ /**
+ * Constructor for the playback component, which displays
+ * play/pause/progress controls.
+ *
+ * @param {HTMLElement} container The component will append
+ * itself to this
+ * @param {function} progressCheck A method which will be
+ * called frequently to get the current progress on a range
+ * of 0-1
+ */
+ function Playback( container, progressCheck ) {
+
+ // Cosmetics
+ this.diameter = 100;
+ this.diameter2 = this.diameter/2;
+ this.thickness = 6;
+
+ // Flags if we are currently playing
+ this.playing = false;
+
+ // Current progress on a 0-1 range
+ this.progress = 0;
+
+ // Used to loop the animation smoothly
+ this.progressOffset = 1;
+
+ this.container = container;
+ this.progressCheck = progressCheck;
+
+ this.canvas = document.createElement( 'canvas' );
+ this.canvas.className = 'playback';
+ this.canvas.width = this.diameter;
+ this.canvas.height = this.diameter;
+ this.canvas.style.width = this.diameter2 + 'px';
+ this.canvas.style.height = this.diameter2 + 'px';
+ this.context = this.canvas.getContext( '2d' );
+
+ this.container.appendChild( this.canvas );
+
+ this.render();
+
+ }
+
+ /**
+ * @param value
+ */
+ Playback.prototype.setPlaying = function( value ) {
+
+ var wasPlaying = this.playing;
+
+ this.playing = value;
+
+ // Start repainting if we weren't already
+ if( !wasPlaying && this.playing ) {
+ this.animate();
+ }
+ else {
+ this.render();
+ }
+
+ };
+
+ Playback.prototype.animate = function() {
+
+ var progressBefore = this.progress;
+
+ this.progress = this.progressCheck();
+
+ // When we loop, offset the progress so that it eases
+ // smoothly rather than immediately resetting
+ if( progressBefore > 0.8 && this.progress < 0.2 ) {
+ this.progressOffset = this.progress;
+ }
+
+ this.render();
+
+ if( this.playing ) {
+ features.requestAnimationFrameMethod.call( window, this.animate.bind( this ) );
+ }
+
+ };
+
+ /**
+ * Renders the current progress and playback state.
+ */
+ Playback.prototype.render = function() {
+
+ var progress = this.playing ? this.progress : 0,
+ radius = ( this.diameter2 ) - this.thickness,
+ x = this.diameter2,
+ y = this.diameter2,
+ iconSize = 28;
+
+ // Ease towards 1
+ this.progressOffset += ( 1 - this.progressOffset ) * 0.1;
+
+ var endAngle = ( - Math.PI / 2 ) + ( progress * ( Math.PI * 2 ) );
+ var startAngle = ( - Math.PI / 2 ) + ( this.progressOffset * ( Math.PI * 2 ) );
+
+ this.context.save();
+ this.context.clearRect( 0, 0, this.diameter, this.diameter );
+
+ // Solid background color
+ this.context.beginPath();
+ this.context.arc( x, y, radius + 4, 0, Math.PI * 2, false );
+ this.context.fillStyle = 'rgba( 0, 0, 0, 0.4 )';
+ this.context.fill();
+
+ // Draw progress track
+ this.context.beginPath();
+ this.context.arc( x, y, radius, 0, Math.PI * 2, false );
+ this.context.lineWidth = this.thickness;
+ this.context.strokeStyle = '#666';
+ this.context.stroke();
+
+ if( this.playing ) {
+ // Draw progress on top of track
+ this.context.beginPath();
+ this.context.arc( x, y, radius, startAngle, endAngle, false );
+ this.context.lineWidth = this.thickness;
+ this.context.strokeStyle = '#fff';
+ this.context.stroke();
+ }
+
+ this.context.translate( x - ( iconSize / 2 ), y - ( iconSize / 2 ) );
+
+ // Draw play/pause icons
+ if( this.playing ) {
+ this.context.fillStyle = '#fff';
+ this.context.fillRect( 0, 0, iconSize / 2 - 4, iconSize );
+ this.context.fillRect( iconSize / 2 + 4, 0, iconSize / 2 - 4, iconSize );
+ }
+ else {
+ this.context.beginPath();
+ this.context.translate( 4, 0 );
+ this.context.moveTo( 0, 0 );
+ this.context.lineTo( iconSize - 4, iconSize / 2 );
+ this.context.lineTo( 0, iconSize );
+ this.context.fillStyle = '#fff';
+ this.context.fill();
+ }
+
+ this.context.restore();
+
+ };
+
+ Playback.prototype.on = function( type, listener ) {
+ this.canvas.addEventListener( type, listener, false );
+ };
+
+ Playback.prototype.off = function( type, listener ) {
+ this.canvas.removeEventListener( type, listener, false );
+ };
+
+ Playback.prototype.destroy = function() {
+
+ this.playing = false;
+
+ if( this.canvas.parentNode ) {
+ this.container.removeChild( this.canvas );
+ }
+
+ };
+
+
+ // --------------------------------------------------------------------//
+ // ------------------------------- API --------------------------------//
+ // --------------------------------------------------------------------//
+
+
+ Reveal = {
+ VERSION: VERSION,
+
+ initialize: initialize,
+ configure: configure,
+ sync: sync,
+
+ // Navigation methods
+ slide: slide,
+ left: navigateLeft,
+ right: navigateRight,
+ up: navigateUp,
+ down: navigateDown,
+ prev: navigatePrev,
+ next: navigateNext,
+
+ // Fragment methods
+ navigateFragment: navigateFragment,
+ prevFragment: previousFragment,
+ nextFragment: nextFragment,
+
+ // Deprecated aliases
+ navigateTo: slide,
+ navigateLeft: navigateLeft,
+ navigateRight: navigateRight,
+ navigateUp: navigateUp,
+ navigateDown: navigateDown,
+ navigatePrev: navigatePrev,
+ navigateNext: navigateNext,
+
+ // Shows a help overlay with keyboard shortcuts
+ showHelp: showHelp,
+
+ // Forces an update in slide layout
+ layout: layout,
+
+ // Randomizes the order of slides
+ shuffle: shuffle,
+
+ // Returns an object with the available routes as booleans (left/right/top/bottom)
+ availableRoutes: availableRoutes,
+
+ // Returns an object with the available fragments as booleans (prev/next)
+ availableFragments: availableFragments,
+
+ // Toggles the overview mode on/off
+ toggleOverview: toggleOverview,
+
+ // Toggles the "black screen" mode on/off
+ togglePause: togglePause,
+
+ // Toggles the auto slide mode on/off
+ toggleAutoSlide: toggleAutoSlide,
+
+ // State checks
+ isOverview: isOverview,
+ isPaused: isPaused,
+ isAutoSliding: isAutoSliding,
+
+ // Adds or removes all internal event listeners (such as keyboard)
+ addEventListeners: addEventListeners,
+ removeEventListeners: removeEventListeners,
+
+ // Facility for persisting and restoring the presentation state
+ getState: getState,
+ setState: setState,
+
+ // Presentation progress on range of 0-1
+ getProgress: getProgress,
+
+ // Returns the indices of the current, or specified, slide
+ getIndices: getIndices,
+
+ getTotalSlides: getTotalSlides,
+
+ // Returns the slide element at the specified index
+ getSlide: getSlide,
+
+ // Returns the slide background element at the specified index
+ getSlideBackground: getSlideBackground,
+
+ // Returns the speaker notes string for a slide, or null
+ getSlideNotes: getSlideNotes,
+
+ // Returns the previous slide element, may be null
+ getPreviousSlide: function() {
+ return previousSlide;
+ },
+
+ // Returns the current slide element
+ getCurrentSlide: function() {
+ return currentSlide;
+ },
+
+ // Returns the current scale of the presentation content
+ getScale: function() {
+ return scale;
+ },
+
+ // Returns the current configuration object
+ getConfig: function() {
+ return config;
+ },
+
+ // Helper method, retrieves query string as a key/value hash
+ getQueryHash: function() {
+ var query = {};
+
+ location.search.replace( /[A-Z0-9]+?=([\w\.%-]*)/gi, function(a) {
+ query[ a.split( '=' ).shift() ] = a.split( '=' ).pop();
+ } );
+
+ // Basic deserialization
+ for( var i in query ) {
+ var value = query[ i ];
+
+ query[ i ] = deserialize( unescape( value ) );
+ }
+
+ return query;
+ },
+
+ // Returns true if we're currently on the first slide
+ isFirstSlide: function() {
+ return ( indexh === 0 && indexv === 0 );
+ },
+
+ // Returns true if we're currently on the last slide
+ isLastSlide: function() {
+ if( currentSlide ) {
+ // Does this slide has next a sibling?
+ if( currentSlide.nextElementSibling ) return false;
+
+ // If it's vertical, does its parent have a next sibling?
+ if( isVerticalSlide( currentSlide ) && currentSlide.parentNode.nextElementSibling ) return false;
+
+ return true;
+ }
+
+ return false;
+ },
+
+ // Checks if reveal.js has been loaded and is ready for use
+ isReady: function() {
+ return loaded;
+ },
+
+ // Forward event binding to the reveal DOM element
+ addEventListener: function( type, listener, useCapture ) {
+ if( 'addEventListener' in window ) {
+ ( dom.wrapper || document.querySelector( '.reveal' ) ).addEventListener( type, listener, useCapture );
+ }
+ },
+ removeEventListener: function( type, listener, useCapture ) {
+ if( 'addEventListener' in window ) {
+ ( dom.wrapper || document.querySelector( '.reveal' ) ).removeEventListener( type, listener, useCapture );
+ }
+ },
+
+ // Programatically triggers a keyboard event
+ triggerKey: function( keyCode ) {
+ onDocumentKeyDown( { keyCode: keyCode } );
+ },
+
+ // Registers a new shortcut to include in the help overlay
+ registerKeyboardShortcut: function( key, value ) {
+ keyboardShortcuts[key] = value;
+ }
+ };
+
+ return Reveal;
+
+}));
diff --git a/slides/reveal.js/theme/blood.css b/slides/reveal.js/theme/blood.css
new file mode 100644
index 0000000..1e0fbaf
--- /dev/null
+++ b/slides/reveal.js/theme/blood.css
@@ -0,0 +1,315 @@
+/**
+ * Blood theme for reveal.js
+ * Author: Walther http://github.com/Walther
+ *
+ * Designed to be used with highlight.js theme
+ * "monokai_sublime.css" available from
+ * https://github.com/isagalaev/highlight.js/
+ *
+ * For other themes, change $codeBackground accordingly.
+ *
+ */
+@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic);
+/*********************************************
+ * GLOBAL STYLES
+ *********************************************/
+body {
+ background: #222;
+ background-color: #222; }
+
+.reveal {
+ font-family: Ubuntu, "sans-serif";
+ font-size: 40px;
+ font-weight: normal;
+ color: #eee; }
+
+::selection {
+ color: #fff;
+ background: #a23;
+ text-shadow: none; }
+
+::-moz-selection {
+ color: #fff;
+ background: #a23;
+ text-shadow: none; }
+
+.reveal .slides > section,
+.reveal .slides > section > section {
+ line-height: 1.3;
+ font-weight: inherit; }
+
+/*********************************************
+ * HEADERS
+ *********************************************/
+.reveal h1,
+.reveal h2,
+.reveal h3,
+.reveal h4,
+.reveal h5,
+.reveal h6 {
+ margin: 0 0 20px 0;
+ color: #eee;
+ font-family: Ubuntu, "sans-serif";
+ font-weight: normal;
+ line-height: 1.2;
+ letter-spacing: normal;
+ text-transform: uppercase;
+ text-shadow: 2px 2px 2px #222;
+ word-wrap: break-word; }
+
+.reveal h1 {
+ font-size: 3.77em; }
+
+.reveal h2 {
+ font-size: 2.11em; }
+
+.reveal h3 {
+ font-size: 1.55em; }
+
+.reveal h4 {
+ font-size: 1em; }
+
+.reveal h1 {
+ text-shadow: 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, 0.1), 0 0 5px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2), 0 5px 10px rgba(0, 0, 0, 0.25), 0 20px 20px rgba(0, 0, 0, 0.15); }
+
+/*********************************************
+ * OTHER
+ *********************************************/
+.reveal p {
+ margin: 20px 0;
+ line-height: 1.3; }
+
+/* Ensure certain elements are never larger than the slide itself */
+.reveal img,
+.reveal video,
+.reveal iframe {
+ max-width: 95%;
+ max-height: 95%; }
+
+.reveal strong,
+.reveal b {
+ font-weight: bold; }
+
+.reveal em {
+ font-style: italic; }
+
+.reveal ol,
+.reveal dl,
+.reveal ul {
+ display: inline-block;
+ text-align: left;
+ margin: 0 0 0 1em; }
+
+.reveal ol {
+ list-style-type: decimal; }
+
+.reveal ul {
+ list-style-type: disc; }
+
+.reveal ul ul {
+ list-style-type: square; }
+
+.reveal ul ul ul {
+ list-style-type: circle; }
+
+.reveal ul ul,
+.reveal ul ol,
+.reveal ol ol,
+.reveal ol ul {
+ display: block;
+ margin-left: 40px; }
+
+.reveal dt {
+ font-weight: bold; }
+
+.reveal dd {
+ margin-left: 40px; }
+
+.reveal q,
+.reveal blockquote {
+ quotes: none; }
+
+.reveal blockquote {
+ display: block;
+ position: relative;
+ width: 70%;
+ margin: 20px auto;
+ padding: 5px;
+ font-style: italic;
+ background: rgba(255, 255, 255, 0.05);
+ box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); }
+
+.reveal blockquote p:first-child,
+.reveal blockquote p:last-child {
+ display: inline-block; }
+
+.reveal q {
+ font-style: italic; }
+
+.reveal pre {
+ display: block;
+ position: relative;
+ width: 90%;
+ margin: 20px auto;
+ text-align: left;
+ font-size: 0.55em;
+ font-family: monospace;
+ line-height: 1.2em;
+ word-wrap: break-word;
+ box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); }
+
+.reveal code {
+ font-family: monospace; }
+
+.reveal pre code {
+ display: block;
+ padding: 5px;
+ overflow: auto;
+ max-height: 400px;
+ word-wrap: normal; }
+
+.reveal table {
+ margin: auto;
+ border-collapse: collapse;
+ border-spacing: 0; }
+
+.reveal table th {
+ font-weight: bold; }
+
+.reveal table th,
+.reveal table td {
+ text-align: left;
+ padding: 0.2em 0.5em 0.2em 0.5em;
+ border-bottom: 1px solid; }
+
+.reveal table th[align="center"],
+.reveal table td[align="center"] {
+ text-align: center; }
+
+.reveal table th[align="right"],
+.reveal table td[align="right"] {
+ text-align: right; }
+
+.reveal table tbody tr:last-child th,
+.reveal table tbody tr:last-child td {
+ border-bottom: none; }
+
+.reveal sup {
+ vertical-align: super; }
+
+.reveal sub {
+ vertical-align: sub; }
+
+.reveal small {
+ display: inline-block;
+ font-size: 0.6em;
+ line-height: 1.2em;
+ vertical-align: top; }
+
+.reveal small * {
+ vertical-align: top; }
+
+/*********************************************
+ * LINKS
+ *********************************************/
+.reveal a {
+ color: #a23;
+ text-decoration: none;
+ -webkit-transition: color .15s ease;
+ -moz-transition: color .15s ease;
+ transition: color .15s ease; }
+
+.reveal a:hover {
+ color: #dd5566;
+ text-shadow: none;
+ border: none; }
+
+.reveal .roll span:after {
+ color: #fff;
+ background: #6a1520; }
+
+/*********************************************
+ * IMAGES
+ *********************************************/
+.reveal section img {
+ margin: 15px 0px;
+ background: rgba(255, 255, 255, 0.12);
+ border: 4px solid #eee;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); }
+
+.reveal section img.plain {
+ border: 0;
+ box-shadow: none; }
+
+.reveal a img {
+ -webkit-transition: all .15s linear;
+ -moz-transition: all .15s linear;
+ transition: all .15s linear; }
+
+.reveal a:hover img {
+ background: rgba(255, 255, 255, 0.2);
+ border-color: #a23;
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
+
+/*********************************************
+ * NAVIGATION CONTROLS
+ *********************************************/
+.reveal .controls .navigate-left,
+.reveal .controls .navigate-left.enabled {
+ border-right-color: #a23; }
+
+.reveal .controls .navigate-right,
+.reveal .controls .navigate-right.enabled {
+ border-left-color: #a23; }
+
+.reveal .controls .navigate-up,
+.reveal .controls .navigate-up.enabled {
+ border-bottom-color: #a23; }
+
+.reveal .controls .navigate-down,
+.reveal .controls .navigate-down.enabled {
+ border-top-color: #a23; }
+
+.reveal .controls .navigate-left.enabled:hover {
+ border-right-color: #dd5566; }
+
+.reveal .controls .navigate-right.enabled:hover {
+ border-left-color: #dd5566; }
+
+.reveal .controls .navigate-up.enabled:hover {
+ border-bottom-color: #dd5566; }
+
+.reveal .controls .navigate-down.enabled:hover {
+ border-top-color: #dd5566; }
+
+/*********************************************
+ * PROGRESS BAR
+ *********************************************/
+.reveal .progress {
+ background: rgba(0, 0, 0, 0.2); }
+
+.reveal .progress span {
+ background: #a23;
+ -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+ -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+ transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
+
+.reveal p {
+ font-weight: 300;
+ text-shadow: 1px 1px #222; }
+
+.reveal h1,
+.reveal h2,
+.reveal h3,
+.reveal h4,
+.reveal h5,
+.reveal h6 {
+ font-weight: 700; }
+
+.reveal p code {
+ background-color: #23241f;
+ display: inline-block;
+ border-radius: 7px; }
+
+.reveal small code {
+ vertical-align: baseline; }
diff --git a/slides/reveal.js/zenburn.css b/slides/reveal.js/zenburn.css
new file mode 100644
index 0000000..07be502
--- /dev/null
+++ b/slides/reveal.js/zenburn.css
@@ -0,0 +1,80 @@
+/*
+
+Zenburn style from voldmar.ru (c) Vladimir Epifanov <voldmar@voldmar.ru>
+based on dark.css by Ivan Sagalaev
+
+*/
+
+.hljs {
+ display: block;
+ overflow-x: auto;
+ padding: 0.5em;
+ background: #3f3f3f;
+ color: #dcdcdc;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-tag {
+ color: #e3ceab;
+}
+
+.hljs-template-tag {
+ color: #dcdcdc;
+}
+
+.hljs-number {
+ color: #8cd0d3;
+}
+
+.hljs-variable,
+.hljs-template-variable,
+.hljs-attribute {
+ color: #efdcbc;
+}
+
+.hljs-literal {
+ color: #efefaf;
+}
+
+.hljs-subst {
+ color: #8f8f8f;
+}
+
+.hljs-title,
+.hljs-name,
+.hljs-selector-id,
+.hljs-selector-class,
+.hljs-section,
+.hljs-type {
+ color: #efef8f;
+}
+
+.hljs-symbol,
+.hljs-bullet,
+.hljs-link {
+ color: #dca3a3;
+}
+
+.hljs-deletion,
+.hljs-string,
+.hljs-built_in,
+.hljs-builtin-name {
+ color: #cc9393;
+}
+
+.hljs-addition,
+.hljs-comment,
+.hljs-quote,
+.hljs-meta {
+ color: #7f9f7f;
+}
+
+
+.hljs-emphasis {
+ font-style: italic;
+}
+
+.hljs-strong {
+ font-weight: bold;
+}
diff --git a/slides/security/6char-words.txt b/slides/security/6char-words.txt
new file mode 100644
index 0000000..fd9b0b6
--- /dev/null
+++ b/slides/security/6char-words.txt
@@ -0,0 +1,1494 @@
+search
+online
+people
+health
+should
+system
+policy
+number
+please
+rights
+public
+school
+review
+united
+center
+travel
+report
+member
+before
+hotels
+office
+design
+posted
+within
+states
+family
+prices
+sports
+county
+access
+change
+rating
+during
+return
+events
+little
+movies
+source
+author
+around
+course
+canada
+credit
+estate
+select
+photos
+thread
+market
+really
+action
+series
+second
+forums
+better
+friend
+server
+issues
+street
+things
+person
+mobile
+offers
+recent
+stores
+memory
+social
+august
+create
+single
+latest
+status
+browse
+seller
+always
+result
+groups
+making
+future
+london
+become
+garden
+listed
+energy
+images
+notice
+others
+format
+months
+safety
+having
+common
+living
+called
+period
+window
+france
+region
+island
+record
+direct
+update
+either
+centre
+europe
+topics
+videos
+global
+player
+lyrics
+submit
+amount
+though
+thanks
+weight
+choose
+points
+camera
+domain
+beauty
+models
+simple
+friday
+annual
+google
+church
+method
+active
+figure
+enough
+higher
+yellow
+french
+nature
+orders
+africa
+growth
+agency
+monday
+income
+engine
+double
+screen
+across
+needed
+season
+effect
+sunday
+casino
+volume
+anyone
+silver
+inside
+mature
+rather
+supply
+robert
+skills
+advice
+career
+rental
+middle
+taking
+values
+coming
+object
+length
+client
+follow
+sample
+george
+choice
+artist
+levels
+letter
+phones
+summer
+degree
+button
+matter
+custom
+almost
+editor
+female
+thomas
+cancer
+reason
+spring
+answer
+police
+wanted
+unique
+survey
+animal
+mexico
+secure
+simply
+paypal
+option
+master
+valley
+larger
+impact
+strong
+ground
+owners
+cities
+ensure
+budget
+guides
+amazon
+retail
+useful
+trying
+mother
+joined
+modern
+senior
+charge
+normal
+entire
+output
+likely
+indian
+dating
+filter
+longer
+behind
+german
+buying
+allows
+boards
+string
+unless
+target
+except
+moving
+brands
+places
+pretty
+winter
+boston
+medium
+itself
+papers
+awards
+studio
+reader
+device
+remote
+theory
+remove
+visual
+martin
+manual
+agents
+repair
+sector
+jersey
+father
+quotes
+driver
+campus
+beyond
+museum
+former
+parent
+bottom
+detail
+switch
+titles
+basket
+weekly
+demand
+square
+nation
+module
+resort
+random
+motion
+forest
+couple
+giving
+chance
+vision
+ending
+listen
+accept
+lowest
+highly
+appear
+actual
+coffee
+easily
+poster
+closed
+league
+minute
+effort
+fields
+breast
+kansas
+doctor
+reduce
+enable
+leader
+israel
+flight
+pocket
+factor
+stream
+signed
+errors
+worked
+sorted
+myself
+expert
+became
+orange
+marine
+guitar
+saying
+spirit
+claims
+branch
+manage
+corner
+oregon
+tables
+define
+racing
+column
+plants
+avenue
+mental
+viewed
+moment
+attack
+damage
+placed
+dollar
+bridge
+native
+played
+shirts
+profit
+expect
+russia
+golden
+senate
+forces
+turned
+delete
+signal
+issued
+sexual
+flower
+passed
+stated
+hawaii
+covers
+adults
+script
+served
+dining
+dakota
+handle
+pubmed
+looked
+logged
+laptop
+nearly
+forgot
+origin
+gaming
+faster
+dallas
+bought
+broken
+alaska
+battle
+equity
+speech
+shared
+sounds
+forced
+height
+obtain
+remain
+failed
+secret
+austin
+andrew
+assets
+injury
+joseph
+lawyer
+portal
+gratis
+toward
+assist
+comics
+houses
+postal
+finish
+daniel
+brazil
+static
+hunter
+famous
+writer
+gender
+colour
+vendor
+junior
+ladies
+ticket
+agreed
+soccer
+import
+christ
+scheme
+manner
+matrix
+turkey
+proper
+inches
+shares
+colors
+appeal
+cruise
+disney
+drives
+dealer
+nearby
+happen
+miller
+caused
+luxury
+frames
+indeed
+easier
+adding
+mostly
+taylor
+prints
+suites
+hidden
+serial
+relief
+planet
+copies
+recipe
+permit
+seeing
+tennis
+bureau
+pieces
+dinner
+sydney
+stress
+trends
+fourth
+wilson
+charts
+census
+poetry
+lights
+forget
+sister
+newest
+extent
+export
+sweden
+backup
+spread
+expand
+jordan
+affect
+virgin
+raised
+blonde
+albums
+cheats
+guests
+hosted
+nevada
+agenda
+anyway
+tracks
+prince
+circle
+grants
+edward
+launch
+symbol
+crafts
+fiscal
+styles
+denver
+filled
+notify
+cables
+cotton
+dental
+killed
+border
+debate
+starts
+causes
+opened
+scores
+comedy
+weblog
+linear
+edited
+jewish
+linked
+wonder
+begins
+reform
+alerts
+assume
+howard
+leaves
+checks
+safari
+tested
+formal
+hockey
+showed
+cancel
+limits
+outlet
+winner
+potter
+modify
+oxford
+patent
+eating
+mirror
+kernel
+stocks
+buyers
+taiwan
+chosen
+greece
+labour
+nights
+behalf
+liquid
+salary
+saving
+empire
+resume
+twenty
+avatar
+helped
+decide
+guinea
+muscle
+attend
+shower
+holdem
+seemed
+finder
+unable
+insert
+alumni
+themes
+powers
+heaven
+norway
+asking
+blocks
+bodies
+paying
+carbon
+crisis
+bright
+header
+formed
+sheets
+puerto
+plasma
+banner
+dreams
+stands
+latina
+wheels
+sexcam
+router
+poland
+folder
+womens
+upload
+voting
+courts
+regard
+exists
+smooth
+strike
+narrow
+threat
+castle
+missed
+labels
+acting
+stored
+stable
+lesson
+cinema
+severe
+deluxe
+fabric
+visits
+flying
+berlin
+pounds
+desire
+caught
+marked
+driven
+bottle
+rubber
+legend
+python
+entity
+holder
+duties
+ethics
+dragon
+brings
+stereo
+commit
+jacket
+oracle
+excess
+stamps
+mining
+garage
+thongs
+morgan
+prayer
+cheese
+fetish
+apache
+fellow
+lounge
+hilton
+horror
+debian
+mainly
+ethnic
+occurs
+layout
+horses
+donate
+taught
+worker
+temple
+breaks
+waters
+prefer
+harris
+toyota
+vector
+shaved
+buffer
+purple
+mutual
+syntax
+prison
+chairs
+sierra
+desert
+oldest
+steven
+summit
+spaces
+escape
+cialis
+glance
+arcade
+filing
+foster
+trials
+tissue
+aspect
+counts
+priced
+closer
+shadow
+riding
+clinic
+korean
+packet
+funded
+extend
+dublin
+nelson
+murder
+grades
+digest
+rescue
+losses
+combat
+abroad
+arthur
+walker
+gordon
+serves
+palace
+verify
+copper
+nobody
+cloudy
+plenty
+throat
+ignore
+wealth
+vacuum
+writes
+plates
+essays
+fairly
+config
+stupid
+harbor
+puzzle
+rising
+latter
+repeat
+pupils
+casual
+polish
+lovely
+extras
+clause
+troops
+indoor
+broker
+trucks
+partly
+donald
+sensor
+angels
+deputy
+sealed
+loaded
+scenes
+finger
+locate
+wooden
+motors
+shorts
+johnny
+facing
+refund
+trembl
+emails
+cyprus
+makers
+hearts
+carter
+legacy
+danger
+widely
+phrase
+hybrid
+bigger
+diesel
+versus
+exceed
+babies
+albert
+graham
+compaq
+slowly
+infant
+samuel
+unlike
+wright
+proven
+cached
+warren
+comply
+cherry
+webcam
+nutten
+quebec
+dennis
+socket
+silent
+humans
+analog
+facial
+talent
+seeker
+wisdom
+offset
+payday
+philip
+stages
+powder
+assess
+stones
+losing
+gospel
+knight
+earned
+parker
+triple
+cooper
+titans
+sought
+median
+herein
+basics
+carpet
+struct
+lenses
+binary
+walter
+warner
+inkjet
+wizard
+actors
+liable
+morris
+eminem
+recall
+picked
+belief
+bikini
+lookup
+ottawa
+refine
+bidder
+singer
+herald
+plugin
+diving
+invite
+terror
+thirty
+refers
+victim
+arrive
+sunset
+framed
+inform
+murray
+intent
+oxygen
+cookie
+canyon
+meters
+merely
+passes
+durham
+muslim
+sleeve
+stroke
+sharon
+gloves
+skiing
+flickr
+timing
+denied
+deaths
+rivers
+thumbs
+twelve
+decade
+titten
+drinks
+voices
+honest
+albany
+coding
+hiking
+pierre
+arabia
+panama
+athens
+judges
+walked
+nissan
+afraid
+norton
+locked
+fusion
+canvas
+parish
+coupon
+nurses
+tagged
+killer
+bishop
+pulled
+shaped
+farmer
+heroes
+floral
+fisher
+spears
+worlds
+guilty
+tablet
+crimes
+moscow
+thesis
+pixels
+totals
+afford
+turner
+spoken
+stayed
+redeem
+rogers
+regime
+wishes
+depend
+differ
+monica
+breath
+candle
+herbal
+loving
+deemed
+hacker
+madrid
+margin
+solely
+norman
+headed
+voters
+murphy
+thinks
+justin
+tricks
+panels
+tongue
+danish
+monkey
+invest
+lovers
+atomic
+approx
+arabic
+rachel
+chains
+engage
+quoted
+bronze
+sender
+spouse
+exotic
+viewer
+signup
+proved
+salmon
+butter
+pepper
+weapon
+burden
+finest
+realty
+autumn
+toilet
+ranked
+routes
+packed
+timely
+talked
+villas
+peeing
+brooks
+newton
+whilst
+prompt
+ebooks
+victor
+attach
+spider
+ranges
+trails
+hudson
+divine
+dialog
+venues
+shield
+prague
+pickup
+nascar
+sacred
+chrome
+oliver
+delays
+scored
+lambda
+belong
+barnes
+rabbit
+unions
+frozen
+scales
+strain
+yamaha
+hebrew
+gained
+adjust
+soviet
+treaty
+vienna
+chapel
+layers
+guided
+powell
+radius
+harder
+stuart
+monroe
+tender
+clouds
+easter
+praise
+jeremy
+venice
+hardly
+absent
+hoping
+bubble
+vessel
+lauren
+ashley
+scroll
+relate
+suffer
+retain
+tunnel
+genres
+beaver
+kijiji
+eagles
+anchor
+parade
+hiring
+clocks
+surely
+stylus
+arnold
+chicks
+cattle
+reload
+kuwait
+struck
+bridal
+tribal
+rebate
+meetup
+cycles
+detect
+butler
+twinks
+techno
+immune
+latvia
+rarely
+martha
+trains
+metals
+celtic
+advise
+boxing
+hughes
+reveal
+watson
+strict
+saddam
+inline
+timber
+ruling
+steady
+hourly
+geneva
+handed
+intake
+tucson
+assure
+sodium
+thehun
+decent
+dayton
+carlos
+valium
+uganda
+trivia
+adidas
+harvey
+hazard
+fruits
+ribbon
+suzuki
+exempt
+dishes
+refuse
+trades
+superb
+floors
+speaks
+burton
+copied
+scotia
+gibson
+roller
+nicole
+latino
+mixing
+fitted
+asthma
+reward
+zambia
+sprint
+inputs
+genome
+knives
+honors
+fallen
+sussex
+gather
+backed
+alfred
+motels
+slight
+msgstr
+arrest
+adipex
+deeply
+marina
+prizes
+bosnia
+optics
+pursue
+plains
+lonely
+hereby
+collar
+racial
+amanda
+kelkoo
+novels
+safely
+finite
+kidney
+allied
+throws
+roster
+nasdaq
+tuning
+gotten
+rocket
+bullet
+towers
+duncan
+priest
+ronald
+trance
+locale
+bundle
+hammer
+runner
+notion
+mailed
+arctic
+defend
+stolen
+agrees
+cheers
+zoning
+mighty
+holmes
+galaxy
+caring
+itunes
+buried
+newbie
+darwin
+milton
+marker
+sandra
+monaco
+belize
+robust
+porter
+jungle
+alpine
+andale
+cooler
+shapes
+andrea
+breeds
+rapids
+bailey
+eugene
+metric
+joshua
+varied
+grande
+assign
+tigers
+aurora
+slides
+lender
+chorus
+rhythm
+argued
+clarke
+sudden
+claire
+speeds
+vocals
+chubby
+burner
+gentle
+deeper
+worthy
+saints
+helena
+marion
+cowboy
+queens
+tribes
+defeat
+clicks
+harper
+tenant
+tattoo
+freely
+marcus
+nudist
+remedy
+genius
+barely
+pamela
+marble
+surrey
+belkin
+giants
+solved
+magnet
+cayman
+jaguar
+posing
+urgent
+gothic
+graphs
+patrol
+divide
+mailto
+boring
+schema
+prefix
+barrel
+typing
+harold
+floppy
+namely
+aerial
+makeup
+nathan
+tobago
+wicked
+pushed
+reggae
+saturn
+enzyme
+zshops
+planes
+tackle
+ambien
+vernon
+builds
+leslie
+favors
+potato
+sticks
+excuse
+strand
+cheque
+reject
+italic
+valued
+batman
+luther
+settle
+palmer
+scenic
+sewing
+munich
+celebs
+trusts
+pillow
+harley
+finals
+parcel
+rolled
+flavor
+hungry
+malawi
+curtis
+lesser
+charms
+trader
+denial
+thrown
+raises
+ballot
+angola
+squirt
+helmet
+nickel
+wallet
+coated
+intend
+louise
+beings
+habits
+accent
+eleven
+auburn
+unlock
+pledge
+angela
+merger
+nextel
+rwanda
+riders
+remark
+dozens
+varies
+guards
+kruger
+granny
+fleece
+pierce
+breach
+wiring
+pastor
+calvin
+phases
+ballet
+bumper
+garlic
+banned
+briefs
+mumbai
+radios
+tariff
+nvidia
+hostel
+employ
+yearly
+marvel
+petite
+strips
+gossip
+rotary
+kinase
+skirts
+serbia
+guyana
+deadly
+rounds
+dosage
+baking
+needle
+brakes
+sticky
+heated
+jackie
+adrian
+brutal
+yields
+suited
+blacks
+curves
+vertex
+tomato
+waiver
+garcia
+valves
+donors
+bufing
+julian
+velvet
+wesley
+lately
+brunei
+banana
+slovak
+remind
+affair
+washer
+beside
+mentor
+fought
+metres
+pencil
+freeze
+titled
+sphere
+ratios
+walnut
+ladder
+italia
+hansen
+condos
+gently
+fridge
+fraser
+blades
+trauma
+advert
+subaru
+picnic
+hollow
+groove
+sleeps
+travis
+heater
+colony
+cannon
+circus
+forbes
+cooked
+gerald
+hunger
+mariah
+cement
+closes
+violin
+naples
+modems
+prozac
+newark
+turtle
+warned
+neural
+fossil
+apollo
+greene
+robots
+nested
+movers
+verbal
+bryant
+voyuer
+garmin
+render
+carmen
+impose
+enters
+savage
+willow
+barbie
+favour
+roland
+mounts
+michel
+subtle
+cradle
+virtue
+corpus
+shades
+adware
+zoloft
+ultram
+cursor
+maiden
+viking
+myrtle
+bother
+bhutan
+mating
+unwrap
+resist
+wagner
+ranger
+newman
+scared
+asylum
+robbie
+poison
diff --git a/slides/security/8char-words.txt b/slides/security/8char-words.txt
new file mode 100644
index 0000000..393d1c7
--- /dev/null
+++ b/slides/security/8char-words.txt
@@ -0,0 +1,1162 @@
+business
+services
+products
+software
+research
+comments
+national
+internet
+shipping
+reserved
+security
+american
+computer
+download
+pictures
+personal
+location
+children
+students
+shopping
+previous
+property
+customer
+december
+training
+advanced
+category
+register
+november
+features
+industry
+provided
+required
+articles
+feedback
+complete
+standard
+programs
+language
+password
+question
+building
+february
+analysis
+possible
+problems
+interest
+learning
+delivery
+original
+includes
+messages
+provides
+specific
+director
+planning
+database
+official
+district
+calendar
+resource
+document
+material
+together
+function
+economic
+projects
+included
+received
+archives
+magazine
+policies
+position
+listings
+wireless
+purchase
+response
+practice
+hardware
+designed
+discount
+remember
+increase
+european
+activity
+although
+contents
+regional
+supplies
+exchange
+continue
+benefits
+anything
+mortgage
+solution
+addition
+clothing
+homepage
+military
+decision
+division
+actually
+saturday
+starting
+thursday
+consumer
+contract
+releases
+virginia
+multiple
+featured
+friendly
+schedule
+everyone
+approach
+physical
+medicine
+evidence
+favorite
+recently
+probably
+networks
+transfer
+carolina
+hospital
+overview
+distance
+involved
+partners
+existing
+selected
+patients
+directly
+searches
+strategy
+teaching
+canadian
+positive
+football
+abstract
+contains
+republic
+vacation
+academic
+graphics
+expected
+mountain
+consider
+northern
+proposed
+reported
+politics
+modified
+released
+internal
+detailed
+japanese
+approved
+southern
+yourself
+pressure
+keywords
+purposes
+external
+teachers
+subjects
+capacity
+requires
+electric
+creative
+progress
+families
+accepted
+agencies
+michigan
+columbia
+critical
+employee
+packages
+colorado
+relevant
+illinois
+elements
+facility
+minister
+visitors
+coverage
+clinical
+sciences
+currency
+commerce
+accounts
+settings
+cultural
+holidays
+graduate
+thinking
+provider
+optional
+sections
+websites
+religion
+measures
+chemical
+exercise
+meetings
+congress
+username
+produced
+argument
+creating
+attorney
+auctions
+informed
+thoughts
+quantity
+platform
+machines
+recovery
+merchant
+vehicles
+campaign
+examples
+motorola
+intended
+election
+requests
+separate
+identify
+domestic
+extended
+sequence
+williams
+movement
+printing
+baseball
+approval
+contacts
+matching
+offering
+variable
+compared
+workshop
+lighting
+portable
+returned
+warranty
+assembly
+criminal
+powerful
+obtained
+supplied
+opinions
+maintain
+priority
+payments
+straight
+prepared
+criteria
+behavior
+changing
+festival
+whatever
+maryland
+eligible
+checkout
+handling
+scotland
+followed
+protocol
+designer
+marriage
+negative
+missouri
+ministry
+proposal
+birthday
+slightly
+lingerie
+profiles
+controls
+breaking
+combined
+ultimate
+reviewed
+forecast
+accuracy
+pharmacy
+creation
+chairman
+violence
+oklahoma
+speakers
+cleaning
+concerns
+officers
+referred
+supports
+presence
+majority
+strength
+daughter
+standing
+ordering
+bookmark
+specials
+improved
+exposure
+gambling
+outdoors
+printers
+kentucky
+interior
+relative
+identity
+victoria
+revision
+instance
+licensed
+recorded
+finished
+discover
+patterns
+stations
+greatest
+operator
+tracking
+accurate
+managing
+happened
+lesbians
+managers
+aircraft
+conflict
+versions
+employer
+describe
+citizens
+heritage
+audience
+assigned
+directed
+sporting
+affected
+expenses
+indicate
+anderson
+diseases
+thailand
+advisory
+template
+anywhere
+atlantic
+investor
+wildlife
+speaking
+sponsors
+checking
+guidance
+observed
+glossary
+channels
+ericsson
+appendix
+supplier
+arkansas
+notebook
+explorer
+historic
+attached
+disabled
+upcoming
+constant
+portland
+concepts
+relating
+alliance
+engineer
+becoming
+relation
+colleges
+brothers
+presents
+estimate
+bulletin
+epinions
+painting
+universe
+watching
+sterling
+sessions
+journals
+jennifer
+terminal
+nebraska
+properly
+hundreds
+tomorrow
+visiting
+downtown
+keyboard
+suitable
+millions
+findings
+clicking
+province
+catholic
+governor
+swimming
+pakistan
+reliable
+symptoms
+memorial
+fighting
+pregnant
+cellular
+normally
+diabetes
+flexible
+numerous
+superior
+spending
+magnetic
+registry
+employed
+displays
+allowing
+earnings
+delaware
+counties
+occurred
+concrete
+accident
+resident
+possibly
+flashing
+malaysia
+antiques
+parallel
+bathroom
+drinking
+reaction
+enhanced
+entitled
+generate
+monitors
+duration
+pursuant
+contrast
+adoption
+measured
+marshall
+thousand
+hamilton
+tutorial
+portugal
+lawrence
+valuable
+airlines
+aviation
+disaster
+commands
+achieved
+injuries
+nintendo
+appeared
+franklin
+exciting
+ringtone
+pleasure
+oriented
+desktops
+columbus
+producer
+semester
+strongly
+proteins
+familiar
+carrying
+editions
+vertical
+absolute
+consists
+soldiers
+guardian
+classics
+bringing
+evaluate
+tropical
+pipeline
+everyday
+ethernet
+handbook
+navigate
+somewhat
+receiver
+scottish
+richmond
+covering
+platinum
+judgment
+bedrooms
+modeling
+spectrum
+emphasis
+princess
+entering
+thompson
+memories
+adequate
+cartoons
+entirely
+replaced
+reducing
+shooting
+launched
+suggests
+operated
+overseas
+surprise
+shoppers
+supposed
+ordinary
+applying
+reporter
+champion
+sentence
+outcomes
+survival
+jonathan
+whenever
+lifetime
+athletic
+campbell
+traveler
+aluminum
+wishlist
+trailers
+syndrome
+expanded
+bulgaria
+believed
+spanking
+catering
+incident
+dynamics
+decrease
+cumshots
+revenues
+emerging
+churches
+reserves
+minority
+recorder
+seminars
+paradise
+compiled
+romantic
+revealed
+margaret
+portions
+equation
+reviewer
+involves
+earrings
+chapters
+literary
+choosing
+boundary
+believes
+deadline
+equipped
+broadway
+acquired
+entrance
+attempts
+answered
+disorder
+firewall
+animated
+judicial
+bachelor
+attitude
+montreal
+genetics
+attended
+mitchell
+embedded
+brochure
+petition
+shoulder
+diameter
+literacy
+moderate
+opposite
+dealtime
+mercedes
+tramadol
+receives
+veterans
+occasion
+sleeping
+moreover
+michelle
+dialogue
+declared
+handheld
+disposal
+florists
+switches
+blogging
+midnight
+commonly
+pleasant
+announce
+sampling
+inspired
+weddings
+suddenly
+netscape
+township
+rankings
+robinson
+remained
+entities
+roulette
+medicare
+explains
+feelings
+freeware
+donation
+targeted
+realized
+gamecube
+climbing
+somebody
+colombia
+archived
+courtesy
+detected
+bracelet
+juvenile
+acoustic
+cassette
+steering
+cemetery
+contests
+berkeley
+adjusted
+seasonal
+counters
+cultures
+coaching
+examined
+encoding
+cosmetic
+resulted
+portrait
+carriers
+mobility
+builders
+struggle
+crossing
+resolved
+branches
+holdings
+zimbabwe
+browsing
+bargains
+frequent
+ensuring
+hispanic
+diamonds
+untitled
+marriott
+starring
+referral
+distinct
+verified
+formerly
+situated
+strictly
+retailer
+vitamins
+brooklyn
+phillips
+interval
+expansys
+repeated
+filename
+florence
+analyses
+drawings
+scenario
+junction
+weekends
+produces
+kingston
+adapters
+adjacent
+reaching
+receptor
+surgical
+citation
+premises
+imperial
+benjamin
+studying
+upgrades
+offshore
+harrison
+emission
+apparent
+outreach
+mounting
+balanced
+upskirts
+explicit
+precious
+annually
+scanners
+delivers
+necklace
+arranged
+theaters
+advocacy
+threaded
+footwear
+licenses
+removing
+isolated
+assisted
+compound
+abortion
+wellness
+membrane
+previews
+exterior
+greeting
+botswana
+velocity
+composed
+baseline
+honolulu
+electron
+passport
+treasury
+occupied
+observer
+sunshine
+ceremony
+arrested
+homework
+assessed
+enabling
+stronger
+advances
+darkness
+stanford
+rejected
+gamespot
+railroad
+lectures
+cheapest
+travesti
+salvador
+tanzania
+preserve
+unsigned
+theories
+executed
+showcase
+integral
+synopsis
+composer
+accessed
+imported
+contrary
+focusing
+admitted
+equality
+stickers
+concerts
+cambodia
+updating
+readings
+confused
+compiler
+airports
+brunette
+gathered
+slovenia
+notified
+dramatic
+surfaces
+terrible
+reflects
+taxation
+treasure
+assuming
+monetary
+floating
+plymouth
+warnings
+stunning
+actively
+cookbook
+uploaded
+collapse
+americas
+unlikely
+beverage
+forestry
+barriers
+infected
+particle
+minerals
+humidity
+operates
+brisbane
+manitoba
+missions
+costumes
+nickname
+staffing
+playlist
+statutes
+enrolled
+publicly
+reseller
+suffered
+informal
+swingers
+mistakes
+defining
+counting
+medieval
+captured
+innocent
+scanning
+cordless
+patricia
+disagree
+episodes
+circular
+mainland
+interact
+auckland
+olympics
+worldsex
+trinidad
+geometry
+slovakia
+gorgeous
+barbados
+chrysler
+mcdonald
+plumbing
+brussels
+shanghai
+davidson
+organize
+triangle
+oriental
+hydrogen
+webshots
+advocate
+artistic
+detector
+colonial
+proceeds
+indirect
+browsers
+overcome
+brighton
+reminder
+searched
+insights
+sullivan
+exhibits
+bacteria
+moisture
+symantec
+launches
+latitude
+deposits
+mistress
+trustees
+reprints
+midlands
+analysts
+nicholas
+invasion
+spelling
+medicaid
+infrared
+quarters
+naturals
+fixtures
+bloggers
+flooring
+ethiopia
+athletes
+humanity
+scholars
+snapshot
+segments
+dominant
+minimize
+fraction
+adelaide
+emirates
+promised
+bookings
+fabulous
+maritime
+periodic
+overhead
+prospect
+shipment
+breeding
+envelope
+homeland
+excluded
+emotions
+incoming
+cleaners
+cashiers
+rotation
+premiere
+villages
+symphony
+rational
+fighters
+chambers
+fountain
+regarded
+egyptian
+outlined
+headline
+treating
+enormous
+shemales
+honduras
+cabinets
+hartford
+wrapping
+timeline
+infinite
+civilian
+realtors
+wherever
+democrat
+retained
+logitech
+briefing
+highland
+hawaiian
+consoles
+cylinder
+surround
+finances
+enjoying
+italiano
+carnival
+promises
+combines
+bradford
+reynolds
+speeches
+catalogs
+savannah
+pointing
+metadata
+circuits
+handbags
+somerset
+incurred
+roommate
+failures
+theology
+edmonton
+retrieve
+worldcat
+titanium
+deutsche
+postings
+cornwall
+basement
+sandwich
+hearings
+textbook
+frontier
+stopping
+refugees
+peaceful
+doctrine
+trainers
+conclude
+advisors
+pavilion
+talented
+paraguay
+boutique
+peterson
+homeless
+horrible
+metallic
+warriors
+cadillac
+parental
+marathon
+pressing
+gasoline
+warcraft
+catalyst
+analyzed
+remedies
+validity
+handjobs
+weighted
+performs
+plastics
+salaries
+postcard
+elephant
+drainage
+clearing
+routines
+reliance
+striking
+podcasts
+ensemble
+biblical
+prostate
+nitrogen
+softball
+firewire
+musician
+blocking
+limiting
+dispatch
+restored
+chargers
+rendered
+openings
+councils
+cottages
+develops
+dressing
+drilling
+tomatoes
+clusters
+antibody
+momentum
+grateful
+laughing
+opponent
+propecia
+mongolia
+manually
+centered
+writings
+charging
+discrete
+beginner
+sapphire
+crawford
+declined
+neighbor
+highways
+thinkpad
+intimate
+dentists
+variance
+cameroon
+adaptive
+computed
+invision
+generous
+learners
+aberdeen
+educated
+inserted
+basename
+suburban
+survivor
+cingular
+impaired
+ventures
+stranger
+tribunal
+pensions
+mattress
+likewise
+charming
+annoying
+disclose
+restrict
+springer
+endorsed
+maximize
+senators
+bleeding
+optimize
+caroline
+engaging
+deferred
+polished
+simpsons
+flashers
+arrivals
+securely
+fioricet
+promoted
+enclosed
+thriller
+transmit
+planners
+disputes
+textiles
+intranet
+aquarium
+promptly
+sexually
+dividend
+playback
+hometown
+handmade
+workflow
+switched
+richards
+hardwood
+temporal
+airplane
+istanbul
+asbestos
+throwing
+potatoes
+thorough
+creature
+syracuse
+maldives
+firmware
+shepherd
+canberra
+sympathy
+avoiding
+surgeons
+promotes
+johnston
+prisoner
+earliest
+morrison
+examines
+budapest
+knitting
+attacked
+smallest
+monsters
+lightbox
+cocktail
diff --git a/slides/security/index.html b/slides/security/index.html
new file mode 100644
index 0000000..23066dc
--- /dev/null
+++ b/slides/security/index.html
@@ -0,0 +1,24 @@
+---
+layout: slides
+title: Security
+scripts: [ ./script.js ]
+styles: [ ../reveal.js/theme/blood.css, ./style.css ]
+---
+<div class="reveal">
+ <div class="slides">
+ <section>
+ <h1>Security</h1>
+ <div class="profile">
+ <img src="/assets/face.jpg" alt="Noah Loomans">
+ <div class="info">
+ <div class="name">Noah Loomans</div>
+ <div class="pgp-key">67B0 295A C271 345D 0706 4B9B 8B23 75F3 B367 DF6D</div>
+ </div>
+ </div>
+ </section>
+ <section>
+ <h4>Your password sucks</h4>
+ <h1 id="changing-passwd">Password!1</h1>
+ </section>
+ </div>
+</div>
diff --git a/slides/security/more-then-6char-words.txt b/slides/security/more-then-6char-words.txt
new file mode 100644
index 0000000..1772511
--- /dev/null
+++ b/slides/security/more-then-6char-words.txt
@@ -0,0 +1,6359 @@
+search
+information
+contact
+business
+online
+services
+service
+people
+health
+products
+should
+product
+system
+policy
+number
+please
+available
+copyright
+support
+message
+software
+rights
+public
+school
+through
+review
+privacy
+company
+general
+research
+university
+january
+reviews
+program
+management
+united
+international
+center
+travel
+comments
+development
+report
+member
+details
+before
+hotels
+because
+results
+office
+education
+national
+design
+posted
+internet
+address
+community
+within
+states
+shipping
+reserved
+subject
+between
+family
+special
+prices
+website
+technology
+project
+version
+section
+sports
+related
+security
+county
+american
+members
+network
+computer
+systems
+following
+download
+without
+access
+resources
+current
+control
+history
+pictures
+personal
+including
+directory
+location
+change
+rating
+government
+children
+during
+return
+students
+shopping
+account
+digital
+profile
+previous
+events
+department
+description
+insurance
+another
+property
+quality
+listing
+content
+country
+private
+little
+customer
+december
+compare
+movies
+include
+college
+article
+provide
+source
+author
+different
+around
+course
+canada
+process
+training
+credit
+science
+categories
+advanced
+english
+estate
+conditions
+select
+windows
+photos
+thread
+category
+gallery
+register
+however
+october
+november
+market
+library
+really
+action
+series
+features
+industry
+provided
+required
+second
+accessories
+forums
+september
+better
+questions
+medical
+friend
+server
+application
+articles
+feedback
+looking
+issues
+complete
+street
+comment
+financial
+things
+working
+against
+standard
+person
+mobile
+payment
+equipment
+student
+programs
+offers
+recent
+stores
+problem
+memory
+performance
+social
+august
+language
+options
+experience
+create
+america
+important
+single
+activities
+example
+additional
+password
+latest
+something
+question
+changes
+status
+browse
+building
+seller
+february
+always
+result
+groups
+release
+analysis
+request
+making
+picture
+possible
+professional
+future
+committee
+problems
+london
+washington
+meeting
+become
+interest
+california
+similar
+garden
+schools
+million
+reference
+companies
+listed
+learning
+energy
+delivery
+popular
+stories
+computers
+journal
+reports
+welcome
+central
+images
+president
+notice
+original
+council
+includes
+australia
+discussion
+archive
+others
+entertainment
+agreement
+format
+society
+months
+safety
+friends
+edition
+messages
+marketing
+further
+updated
+association
+having
+provides
+already
+studies
+common
+specific
+several
+living
+collection
+called
+display
+limited
+powered
+solutions
+director
+natural
+whether
+electronics
+period
+planning
+database
+official
+weather
+average
+technical
+window
+france
+region
+island
+record
+direct
+microsoft
+conference
+environment
+records
+district
+calendar
+statement
+update
+downloads
+resource
+present
+applications
+either
+document
+material
+written
+federal
+hosting
+tickets
+centre
+requirements
+finance
+minutes
+europe
+reading
+topics
+individual
+usually
+together
+videos
+percent
+function
+getting
+global
+economic
+player
+projects
+lyrics
+subscribe
+submit
+germany
+amount
+included
+though
+thanks
+everything
+various
+production
+commercial
+weight
+advertising
+received
+choose
+treatment
+newsletter
+archives
+points
+knowledge
+magazine
+camera
+currently
+construction
+registered
+receive
+domain
+methods
+chapter
+protection
+policies
+beauty
+manager
+position
+listings
+models
+michael
+engineering
+florida
+simple
+wireless
+license
+friday
+annual
+published
+corporate
+google
+church
+method
+purchase
+customers
+active
+response
+practice
+hardware
+figure
+materials
+holiday
+enough
+designed
+writing
+countries
+discount
+higher
+effects
+created
+remember
+standards
+yellow
+political
+increase
+advertise
+kingdom
+environmental
+thought
+french
+storage
+nature
+orders
+availability
+africa
+summary
+growth
+agency
+monday
+european
+activity
+although
+western
+income
+employment
+overall
+commission
+package
+contents
+players
+engine
+regional
+supplies
+started
+administration
+institute
+double
+screen
+exchange
+sponsored
+electronic
+continue
+across
+benefits
+needed
+season
+someone
+anything
+printer
+condition
+effective
+believe
+organization
+effect
+sunday
+selection
+casino
+volume
+anyone
+mortgage
+silver
+corporation
+inside
+solution
+mature
+rather
+addition
+supply
+nothing
+certain
+executive
+running
+necessary
+jewelry
+according
+clothing
+particular
+robert
+homepage
+skills
+islands
+advice
+career
+military
+rental
+decision
+british
+facilities
+sellers
+middle
+opportunities
+taking
+values
+division
+coming
+tuesday
+object
+lesbian
+appropriate
+machine
+length
+actually
+statistics
+client
+returns
+capital
+follow
+sample
+investment
+saturday
+christmas
+england
+culture
+george
+choice
+starting
+registration
+thursday
+courses
+consumer
+airport
+foreign
+artist
+outside
+furniture
+levels
+channel
+letter
+phones
+wednesday
+structure
+summer
+degree
+contract
+button
+releases
+matter
+custom
+virginia
+almost
+located
+multiple
+distribution
+editor
+industrial
+potential
+featured
+female
+responsible
+communications
+associated
+thomas
+primary
+cancer
+numbers
+reason
+browser
+spring
+foundation
+answer
+friendly
+schedule
+documents
+communication
+purpose
+feature
+police
+everyone
+independent
+approach
+cameras
+physical
+operating
+medicine
+ratings
+chicago
+wanted
+developed
+unique
+survey
+telephone
+animal
+sources
+mexico
+population
+regular
+secure
+navigation
+operations
+therefore
+simply
+evidence
+station
+christian
+paypal
+favorite
+understand
+option
+master
+valley
+recently
+probably
+rentals
+publications
+worldwide
+improve
+connection
+publisher
+larger
+networks
+parents
+impact
+transfer
+introduction
+kitchen
+strong
+carolina
+wedding
+properties
+hospital
+ground
+overview
+accommodation
+owners
+disease
+excellent
+perfect
+opportunity
+classic
+command
+cities
+william
+express
+distance
+assessment
+ensure
+involved
+especially
+interface
+partners
+budget
+guides
+success
+maximum
+operation
+existing
+selected
+amazon
+patients
+restaurants
+beautiful
+warning
+locations
+forward
+flowers
+significant
+technologies
+retail
+animals
+useful
+directly
+manufacturer
+providing
+housing
+catalog
+searches
+trying
+mother
+authority
+considered
+traffic
+programme
+joined
+strategy
+modern
+senior
+ireland
+teaching
+testing
+charge
+instead
+canadian
+normal
+enterprise
+entire
+educational
+leading
+positive
+fitness
+chinese
+opinion
+football
+abstract
+output
+greater
+likely
+develop
+employees
+artists
+alternative
+processing
+responsibility
+resolution
+publication
+relations
+contains
+session
+photography
+republic
+components
+vacation
+century
+academic
+assistance
+completed
+graphics
+indian
+expected
+dating
+pacific
+mountain
+organizations
+filter
+mailing
+vehicle
+longer
+consider
+northern
+behind
+german
+buying
+proposed
+default
+require
+outdoor
+morning
+otherwise
+allows
+protein
+reported
+transportation
+politics
+partner
+disclaimer
+authors
+boards
+faculty
+parties
+membership
+mission
+string
+modified
+released
+internal
+recommended
+unless
+richard
+detailed
+japanese
+approved
+background
+target
+except
+character
+maintenance
+ability
+functions
+moving
+brands
+places
+pretty
+trademarks
+phentermine
+southern
+yourself
+winter
+battery
+pressure
+submitted
+boston
+keywords
+medium
+television
+interested
+purposes
+throughout
+itself
+defined
+papers
+playing
+awards
+studio
+reader
+virtual
+device
+established
+answers
+remote
+programming
+external
+regarding
+instructions
+offered
+theory
+remove
+surface
+minimum
+visual
+variety
+teachers
+martin
+manual
+subjects
+agents
+increased
+repair
+understanding
+beginning
+associates
+finally
+updates
+desktop
+classes
+sector
+capacity
+requires
+jersey
+father
+electric
+instruments
+quotes
+officer
+driver
+businesses
+respect
+unknown
+specified
+restaurant
+procedures
+teacher
+relationship
+workers
+georgia
+traditional
+campus
+showing
+creative
+benefit
+progress
+funding
+devices
+fiction
+sometimes
+watches
+careers
+beyond
+families
+museum
+themselves
+transport
+interesting
+evaluation
+accepted
+former
+implementation
+complex
+galleries
+references
+presented
+agencies
+literature
+respective
+parent
+spanish
+michigan
+columbia
+setting
+economy
+highest
+helpful
+monthly
+critical
+musical
+definition
+secretary
+angeles
+networking
+australian
+employee
+bottom
+magazines
+packages
+detail
+francisco
+changed
+individuals
+colorado
+switch
+russian
+largest
+african
+titles
+relevant
+guidelines
+justice
+connect
+basket
+applied
+weekly
+installation
+described
+demand
+square
+attention
+advance
+auction
+difference
+allowed
+correct
+charles
+nation
+selling
+illinois
+regulations
+elements
+species
+module
+resort
+facility
+random
+pricing
+certificate
+minister
+motion
+fashion
+directions
+visitors
+documentation
+monitor
+trading
+forest
+coverage
+couple
+giving
+chance
+vision
+ending
+clients
+actions
+listen
+discuss
+accept
+automotive
+successful
+communities
+clinical
+situation
+sciences
+markets
+lowest
+highly
+publishing
+appear
+emergency
+developing
+currency
+leather
+determine
+temperature
+announcements
+patient
+actual
+historical
+commerce
+ringtones
+perhaps
+persons
+difficult
+scientific
+satellite
+village
+accounts
+amateur
+particularly
+factors
+coffee
+settings
+cultural
+easily
+poster
+functional
+closed
+holidays
+zealand
+balance
+monitoring
+graduate
+replies
+architecture
+initial
+thinking
+recommend
+league
+minute
+provider
+optional
+dictionary
+accounting
+manufacturing
+sections
+fishing
+effort
+fields
+fantasy
+letters
+professor
+context
+install
+apparel
+generally
+continued
+breast
+techniques
+johnson
+quickly
+dollars
+websites
+religion
+driving
+permission
+surgery
+measures
+generation
+kansas
+chemical
+doctor
+reduce
+brought
+himself
+component
+enable
+exercise
+guarantee
+leader
+diamond
+israel
+processes
+servers
+meetings
+seconds
+arizona
+keyword
+interests
+flight
+congress
+username
+produced
+italian
+paperback
+classifieds
+supported
+pocket
+freedom
+argument
+competition
+creating
+premium
+providers
+characters
+attorney
+upgrade
+factor
+growing
+thousands
+stream
+apartments
+hearing
+eastern
+auctions
+therapy
+entries
+generated
+signed
+administrative
+serious
+samsung
+errors
+efforts
+informed
+thoughts
+worked
+quantity
+practices
+sorted
+reporting
+essential
+myself
+platform
+affiliate
+immediately
+nursing
+defense
+machines
+designated
+covered
+recovery
+integrated
+configuration
+merchant
+comprehensive
+expert
+universal
+protect
+presentation
+languages
+became
+orange
+compliance
+vehicles
+prevent
+campaign
+marine
+improvement
+guitar
+finding
+pennsylvania
+examples
+saying
+spirit
+claims
+challenge
+motorola
+acceptance
+strategies
+affairs
+intended
+towards
+election
+suggest
+branch
+charges
+affiliates
+reasons
+talking
+multimedia
+certified
+manage
+corner
+computing
+oregon
+element
+interactive
+requests
+separate
+quarter
+procedure
+leadership
+tables
+define
+racing
+religious
+breakfast
+column
+plants
+developer
+identify
+avenue
+missing
+approximately
+domestic
+sitemap
+recommendations
+houston
+comparison
+mental
+viewed
+moment
+extended
+sequence
+attack
+centers
+opening
+damage
+reserve
+recipes
+plastic
+produce
+placed
+counter
+failure
+follows
+weekend
+dollar
+ontario
+automatically
+minnesota
+bridge
+native
+williams
+movement
+printing
+baseball
+approval
+played
+contacts
+readers
+jackson
+adventure
+matching
+offering
+shirts
+profit
+leaders
+posters
+institutions
+assistant
+variable
+advertisement
+expect
+parking
+headlines
+yesterday
+compared
+determined
+wholesale
+workshop
+russia
+extension
+seattle
+statements
+golden
+completely
+lighting
+senate
+forces
+brother
+turned
+portable
+electrical
+applicable
+returned
+pattern
+theatre
+earlier
+manufacturers
+sponsor
+classical
+warranty
+dedicated
+indiana
+direction
+basketball
+objects
+delete
+evening
+assembly
+nuclear
+signal
+criminal
+issued
+sexual
+wisconsin
+powerful
+obtained
+flower
+personnel
+passed
+supplied
+identified
+opinions
+promote
+stated
+hawaii
+professionals
+appears
+decided
+covers
+advantage
+designs
+maintain
+tourism
+priority
+newsletters
+adults
+savings
+graphic
+payments
+estimated
+binding
+winning
+anonymous
+straight
+script
+served
+miscellaneous
+prepared
+dining
+integration
+atlanta
+dakota
+interview
+framework
+installed
+credits
+clearly
+handle
+criteria
+pubmed
+massachusetts
+associate
+behavior
+enlarge
+frequently
+revenue
+measure
+changing
+looked
+discussions
+festival
+laboratory
+flights
+experts
+whatever
+logged
+laptop
+vintage
+exactly
+explore
+maryland
+concept
+nearly
+eligible
+checkout
+reality
+forgot
+handling
+origin
+gaming
+billion
+destination
+scotland
+faster
+intelligence
+dallas
+bought
+nations
+followed
+specifications
+broken
+tripadvisor
+alaska
+battle
+residential
+decisions
+industries
+protocol
+partnership
+editorial
+expression
+equity
+provisions
+speech
+principles
+suggestions
+shared
+sounds
+replacement
+strategic
+economics
+forced
+compatible
+apartment
+height
+speaker
+netherlands
+obtain
+consulting
+recreation
+offices
+designer
+remain
+managed
+failed
+marriage
+participants
+secret
+negative
+austin
+favorites
+toronto
+theater
+springs
+missouri
+andrew
+perform
+healthy
+translation
+estimates
+assets
+injury
+joseph
+ministry
+drivers
+lawyer
+figures
+married
+protected
+proposal
+sharing
+philadelphia
+portal
+waiting
+birthday
+gratis
+banking
+officials
+toward
+slightly
+assist
+conduct
+contained
+lingerie
+legislation
+calling
+parameters
+serving
+profiles
+comics
+matters
+houses
+postal
+relationships
+tennessee
+controls
+breaking
+combined
+ultimate
+representative
+frequency
+introduced
+finish
+departments
+residents
+displayed
+reduced
+physics
+performed
+extreme
+samples
+daniel
+reviewed
+forecast
+removed
+singles
+administrator
+amounts
+contain
+accuracy
+pharmacy
+brazil
+creation
+static
+hunter
+addresses
+crystal
+famous
+writer
+chairman
+violence
+oklahoma
+speakers
+academy
+dynamic
+gender
+permanent
+agriculture
+cleaning
+constitutes
+portfolio
+practical
+delivered
+collectibles
+infrastructure
+exclusive
+concerns
+colour
+vendor
+originally
+utilities
+philosophy
+regulation
+officers
+reduction
+referred
+supports
+nutrition
+recording
+regions
+junior
+meaning
+secondary
+wonderful
+ladies
+ticket
+announced
+agreed
+prevention
+soccer
+import
+posting
+presence
+instant
+mentioned
+automatic
+healthcare
+viewing
+maintained
+increasing
+majority
+connected
+christ
+directors
+aspects
+austria
+participation
+scheme
+utility
+preview
+manner
+matrix
+containing
+combination
+amendment
+despite
+strength
+guaranteed
+turkey
+libraries
+proper
+distributed
+degrees
+singapore
+enterprises
+seeking
+inches
+phoenix
+convention
+shares
+principal
+daughter
+standing
+comfort
+colors
+ordering
+appeal
+cruise
+certification
+previously
+bookmark
+buildings
+specials
+disney
+household
+batteries
+smoking
+becomes
+drives
+alabama
+improved
+achieve
+positions
+subscription
+dealer
+contemporary
+nearby
+carried
+happen
+exposure
+panasonic
+permalink
+signature
+gambling
+miller
+provision
+outdoors
+clothes
+caused
+luxury
+frames
+certainly
+indeed
+newspaper
+circuit
+printed
+removal
+easier
+liability
+trademark
+printers
+adding
+kentucky
+mostly
+taylor
+trackback
+prints
+factory
+interior
+revised
+americans
+optical
+promotion
+relative
+amazing
+identity
+suites
+conversion
+feeling
+hidden
+reasonable
+victoria
+serial
+relief
+revision
+broadband
+influence
+importance
+planet
+webmaster
+copies
+recipe
+permit
+seeing
+tennis
+prescription
+bedroom
+instance
+licensed
+orlando
+specifically
+bureau
+represent
+conservation
+recorded
+pieces
+finished
+dinner
+lawyers
+sydney
+stress
+trends
+discover
+patterns
+louisiana
+javascript
+fourth
+advisor
+marketplace
+wilson
+evolution
+certificates
+objectives
+stations
+suggested
+remains
+greatest
+concerned
+operator
+structures
+generic
+encyclopedia
+charts
+continuing
+census
+interracial
+competitive
+transit
+suppliers
+compact
+poetry
+lights
+tracking
+keeping
+preparation
+attempt
+receiving
+matches
+accordance
+engines
+forget
+discussed
+accurate
+stephen
+elizabeth
+climate
+reservations
+playstation
+alcohol
+instruction
+managing
+annotation
+sister
+differences
+walking
+explain
+smaller
+newest
+establish
+happened
+expressed
+extent
+lesbians
+paragraph
+mathematics
+compensation
+export
+managers
+aircraft
+modules
+sweden
+conflict
+conducted
+versions
+employer
+percentage
+mississippi
+describe
+concern
+backup
+requested
+citizens
+connecticut
+heritage
+personals
+immediate
+holding
+trouble
+spread
+agricultural
+expand
+supporting
+audience
+assigned
+jordan
+collections
+participate
+specialist
+affect
+virgin
+experienced
+investigation
+raised
+institution
+directed
+dealers
+searching
+sporting
+helping
+affected
+totally
+expenses
+indicate
+blonde
+proceedings
+favourite
+transmission
+anderson
+characteristics
+organic
+experiences
+albums
+cheats
+extremely
+verzeichnis
+contracts
+guests
+hosted
+diseases
+concerning
+developers
+equivalent
+chemistry
+neighborhood
+nevada
+thailand
+variables
+agenda
+anyway
+continues
+tracks
+advisory
+curriculum
+template
+prince
+circle
+grants
+anywhere
+psychology
+responses
+atlantic
+circumstances
+edward
+investor
+identification
+leaving
+wildlife
+appliances
+elementary
+cooking
+speaking
+sponsors
+unlimited
+respond
+entered
+launch
+checking
+belgium
+printable
+guidance
+enforcement
+symbol
+crafts
+highway
+hardcover
+observed
+booking
+glossary
+fiscal
+celebrity
+styles
+denver
+filled
+channels
+ericsson
+appendix
+notify
+chocolate
+portion
+hampshire
+supplier
+cables
+cotton
+bluetooth
+controlled
+requirement
+authorities
+biology
+dental
+killed
+border
+ancient
+debate
+representatives
+starts
+pregnancy
+causes
+arkansas
+biography
+leisure
+attractions
+learned
+transactions
+notebook
+explorer
+historic
+attached
+opened
+husband
+disabled
+authorized
+upcoming
+britain
+concert
+retirement
+scores
+financing
+efficiency
+comedy
+adopted
+efficient
+weblog
+linear
+commitment
+specialty
+carrier
+edited
+constant
+jewish
+linked
+portland
+interviews
+concepts
+reflect
+deliver
+wonder
+lessons
+begins
+qualified
+reform
+alerts
+treated
+discovery
+classified
+relating
+assume
+confidence
+alliance
+confirm
+neither
+howard
+offline
+leaves
+engineer
+lifestyle
+consistent
+replace
+clearance
+connections
+inventory
+converter
+organisation
+checks
+reached
+becoming
+safari
+objective
+indicated
+securities
+relation
+enabled
+montana
+volunteer
+tested
+democratic
+enhance
+switzerland
+parameter
+adapter
+processor
+formal
+dimensions
+contribute
+hockey
+colleges
+laptops
+showed
+challenges
+editors
+threads
+supreme
+brothers
+recognition
+presents
+submission
+estimate
+encourage
+regulatory
+inspection
+consumers
+cancel
+limits
+territory
+transaction
+manchester
+weapons
+outlet
+contributions
+continuous
+resulting
+cambridge
+initiative
+execution
+disability
+increases
+winner
+contractor
+episode
+examination
+potter
+bulletin
+indicates
+modify
+oxford
+epinions
+painting
+committed
+extensive
+affordable
+universe
+candidate
+databases
+patent
+outstanding
+eating
+perspective
+planned
+watching
+messenger
+mirror
+tournament
+consideration
+discounts
+sterling
+sessions
+kernel
+stocks
+buyers
+journals
+catalogue
+jennifer
+antonio
+charged
+taiwan
+chosen
+greece
+labour
+terminal
+publishers
+nights
+behalf
+caribbean
+liquid
+nebraska
+salary
+reservation
+gourmet
+properly
+orleans
+saving
+remaining
+empire
+resume
+twenty
+prepare
+avatar
+depending
+illegal
+expansion
+hundreds
+lincoln
+helped
+premier
+tomorrow
+purchased
+decide
+consent
+visiting
+performing
+downtown
+keyboard
+contest
+collected
+suitable
+absolutely
+millions
+chamber
+guinea
+findings
+muscle
+featuring
+implement
+clicking
+scheduled
+typical
+calculator
+significantly
+chicken
+temporary
+attend
+shower
+sending
+tonight
+sufficient
+holdem
+province
+catholic
+awareness
+vancouver
+governor
+seemed
+contribution
+measurement
+swimming
+spyware
+formula
+constitution
+packaging
+pakistan
+reliable
+consultation
+northwest
+finder
+unable
+periods
+classroom
+democracy
+attacks
+wallpaper
+merchandise
+resistance
+symptoms
+resorts
+biggest
+memorial
+visitor
+insert
+baltimore
+gateway
+alumni
+drawing
+candidates
+charlotte
+ordered
+biological
+fighting
+transition
+happens
+preferences
+romance
+instrument
+themes
+powers
+heaven
+pregnant
+classification
+focused
+physician
+hollywood
+bargain
+wikipedia
+cellular
+norway
+vermont
+asking
+blocks
+normally
+spiritual
+hunting
+diabetes
+bodies
+photographs
+cutting
+writers
+flexible
+favourites
+mapping
+numerous
+relatively
+satisfaction
+represents
+indexed
+pittsburgh
+superior
+preferred
+paying
+cartoon
+intellectual
+granted
+choices
+carbon
+spending
+comfortable
+magnetic
+interaction
+listening
+effectively
+registry
+crisis
+outlook
+massive
+denmark
+employed
+bright
+header
+poverty
+formed
+sheets
+patrick
+experimental
+puerto
+revolution
+consolidation
+displays
+plasma
+allowing
+earnings
+mystery
+landscape
+dependent
+mechanical
+journey
+delaware
+bidding
+consultants
+banner
+applicant
+charter
+barbara
+cooperation
+counties
+acquisition
+implemented
+directories
+recognized
+dreams
+blogger
+notification
+licensing
+stands
+occurred
+textbooks
+diversity
+cleveland
+reverse
+deposit
+seminar
+investments
+latina
+wheels
+sexcam
+specify
+accessibility
+sensitive
+templates
+formats
+depends
+router
+concrete
+editing
+poland
+folder
+womens
+completion
+upload
+universities
+technique
+contractors
+milfhunter
+voting
+courts
+notices
+subscriptions
+calculate
+detroit
+alexander
+broadcast
+converted
+toshiba
+anniversary
+improvements
+specification
+accident
+accessible
+accessory
+resident
+possibly
+airline
+typically
+representation
+regard
+exists
+arrangements
+smooth
+conferences
+uniprotkb
+strike
+consumption
+birmingham
+flashing
+narrow
+afternoon
+threat
+surveys
+sitting
+putting
+consultant
+controller
+ownership
+committees
+legislative
+researchers
+vietnam
+trailer
+castle
+gardens
+missed
+malaysia
+unsubscribe
+antique
+labels
+willing
+molecular
+acting
+stored
+residence
+attorneys
+antiques
+density
+hundred
+operators
+strange
+sustainable
+philippines
+statistical
+mention
+innovation
+employers
+parallel
+amended
+operate
+bathroom
+stable
+definitions
+doctors
+lesson
+cinema
+elections
+drinking
+reaction
+enhanced
+entitled
+severe
+generate
+stainless
+newspapers
+hospitals
+deluxe
+monitors
+exception
+duration
+successfully
+indonesia
+pursuant
+fabric
+visits
+primarily
+domains
+capabilities
+contrast
+recommendation
+flying
+recruitment
+berlin
+organized
+siemens
+adoption
+improving
+expensive
+capture
+pounds
+buffalo
+organisations
+explained
+programmes
+desire
+expertise
+mechanism
+camping
+jewellery
+welfare
+caught
+eventually
+marked
+driven
+measured
+medline
+bottle
+agreements
+considering
+innovative
+marshall
+massage
+rubber
+conclusion
+closing
+thousand
+legend
+python
+monster
+columns
+disorders
+collaboration
+hamilton
+detection
+cookies
+formation
+tutorial
+engineers
+entity
+cruises
+holder
+proposals
+moderator
+tutorials
+settlement
+portugal
+lawrence
+duties
+valuable
+collectables
+ethics
+forever
+dragon
+captain
+fantastic
+imagine
+brings
+heating
+governments
+purchasing
+scripts
+stereo
+appointed
+dealing
+commit
+operational
+airlines
+liberal
+livecam
+corresponding
+descriptions
+jacket
+determination
+animation
+oracle
+matthew
+productions
+aviation
+hobbies
+excess
+disaster
+console
+commands
+telecommunications
+instructor
+achieved
+injuries
+shipped
+approaches
+voltage
+anthony
+nintendo
+loading
+stamps
+appeared
+franklin
+highlights
+mining
+designers
+melbourne
+ongoing
+imaging
+betting
+scientists
+liberty
+wyoming
+blackjack
+argentina
+convert
+possibility
+analyst
+commissioner
+dangerous
+garage
+exciting
+reliability
+thongs
+unfortunately
+respectively
+volunteers
+attachment
+ringtone
+finland
+morgan
+derived
+pleasure
+oriented
+desktops
+columbus
+prayer
+appointment
+workshops
+hurricane
+postage
+producer
+represented
+mortgages
+responsibilities
+cheese
+carefully
+productivity
+investors
+underground
+diagnosis
+principle
+vacations
+semester
+calculated
+fetish
+applies
+casinos
+appearance
+apache
+filters
+incorporated
+notebooks
+fellow
+lounge
+algorithm
+strongly
+valentine
+hilton
+proteins
+horror
+familiar
+capable
+douglas
+debian
+involving
+investing
+christopher
+admission
+elected
+carrying
+victory
+madison
+terrorism
+editions
+mainly
+ethnic
+parliament
+situations
+allocated
+citizen
+vertical
+corrections
+structural
+municipal
+describes
+occurs
+absolute
+disabilities
+consists
+anytime
+substance
+prohibited
+addressed
+soldiers
+guardian
+lecture
+simulation
+layout
+initiatives
+concentration
+classics
+interpretation
+horses
+donate
+taught
+bankruptcy
+worker
+optimization
+temple
+substances
+discovered
+breaks
+genetic
+restrictions
+participating
+waters
+promise
+exhibition
+prefer
+cabinet
+harris
+bringing
+evaluate
+tiffany
+tropical
+collect
+composition
+toyota
+streets
+nationwide
+vector
+definitely
+shaved
+turning
+buffer
+purple
+existence
+commentary
+limousines
+developments
+immigration
+destinations
+mutual
+pipeline
+necessarily
+syntax
+attribute
+prison
+chairs
+everyday
+apparently
+surrounding
+mountains
+popularity
+inquiry
+ethernet
+checked
+exhibit
+sierra
+visible
+desert
+postposted
+oldest
+coordinator
+obviously
+mercury
+steven
+handbook
+navigate
+summit
+victims
+spaces
+fundamental
+burning
+escape
+coupons
+somewhat
+receiver
+substantial
+progressive
+cialis
+glance
+scottish
+championship
+arcade
+richmond
+sacramento
+impossible
+russell
+obvious
+depression
+covering
+platinum
+judgment
+bedrooms
+filing
+foster
+modeling
+passing
+awarded
+testimonials
+trials
+tissue
+memorabilia
+clinton
+masters
+cartridge
+alberta
+explanation
+commons
+cincinnati
+subsection
+electricity
+permitted
+spectrum
+arrival
+pottery
+emphasis
+aspect
+workplace
+awesome
+mexican
+confirmed
+counts
+priced
+wallpapers
+desired
+closer
+assumes
+heights
+shadow
+riding
+infection
+firefox
+expense
+eligibility
+venture
+clinic
+korean
+healing
+princess
+entering
+packet
+studios
+involvement
+buttons
+placement
+observations
+vbulletin
+funded
+thompson
+winners
+extend
+subsequent
+dublin
+rolling
+motorcycle
+disclosure
+establishment
+memories
+nelson
+arrived
+creates
+tourist
+murder
+adequate
+senator
+presentations
+grades
+cartoons
+digest
+lodging
+entirely
+replaced
+rescue
+undergraduate
+losses
+combat
+reducing
+stopped
+occupation
+donations
+associations
+citysearch
+closely
+radiation
+seriously
+shooting
+launched
+elsewhere
+pollution
+conservative
+guestbook
+effectiveness
+abroad
+arthur
+visited
+walker
+demonstrate
+atmosphere
+suggests
+operated
+experiment
+targets
+overseas
+purchases
+counsel
+federation
+invited
+assignment
+chemicals
+gordon
+farmers
+queries
+ukraine
+absence
+nearest
+cluster
+vendors
+whereas
+serves
+surprise
+partial
+shoppers
+everybody
+couples
+nashville
+ranking
+simpson
+sublime
+counseling
+palace
+acceptable
+satisfied
+measurements
+verify
+trusted
+copper
+milwaukee
+medication
+warehouse
+shareware
+receipt
+supposed
+ordinary
+nobody
+violation
+configure
+stability
+applying
+southwest
+institutional
+expectations
+independence
+knowing
+reporter
+metabolism
+champion
+cloudy
+personally
+plenty
+sentence
+throat
+ignore
+uniform
+excellence
+wealth
+somewhere
+vacuum
+dancing
+attributes
+recognize
+writes
+outcomes
+survival
+publish
+screening
+thumbnail
+jonathan
+whenever
+lifetime
+pioneer
+forgotten
+acrobat
+plates
+athletic
+thermal
+essays
+behaviour
+telling
+fairly
+coastal
+config
+charity
+intelligent
+edinburgh
+obligation
+campbell
+stupid
+harbor
+hungary
+traveler
+segment
+realize
+regardless
+puzzle
+rising
+aluminum
+wishlist
+insight
+restricted
+republican
+secrets
+latter
+merchants
+trailers
+repeat
+syndrome
+philips
+attendance
+penalty
+glasses
+enables
+builder
+jessica
+arguments
+amsterdam
+adventures
+pupils
+stewart
+announcement
+outcome
+appreciate
+expanded
+casual
+polish
+lovely
+extras
+centres
+clause
+troops
+indoor
+bulgaria
+broker
+charger
+regularly
+believed
+cooling
+trucks
+mechanisms
+divorce
+shopper
+partly
+customize
+tradition
+donald
+sensor
+exposed
+telecom
+angels
+deputy
+indicators
+sealed
+emissions
+physicians
+loaded
+complaint
+scenes
+experiments
+afghanistan
+spanking
+scholarship
+governance
+founded
+supplements
+chronic
+catering
+finger
+locate
+camcorder
+trained
+implementing
+ourselves
+tobacco
+wooden
+motors
+roberts
+incident
+dynamics
+conversation
+decrease
+cumshots
+pension
+revenues
+emerging
+worship
+capability
+herself
+producing
+churches
+precision
+damages
+reserves
+contributed
+shorts
+reproduction
+minority
+diverse
+ingredients
+johnny
+franchise
+recorder
+complaints
+facing
+promotions
+passion
+rehabilitation
+maintaining
+defence
+patches
+refund
+environments
+trembl
+divided
+reception
+emails
+cyprus
+correctly
+insider
+seminars
+consequences
+makers
+hearts
+geography
+appearing
+integrity
+discrimination
+carter
+legacy
+pleased
+danger
+vitamin
+widely
+processed
+phrase
+genuine
+raising
+implications
+functionality
+paradise
+hybrid
+intermediate
+emotional
+platforms
+bigger
+billing
+diesel
+versus
+combine
+overnight
+geographic
+exceed
+preliminary
+districts
+introduce
+promotional
+chevrolet
+babies
+compiled
+romantic
+revealed
+specialists
+generator
+albert
+examine
+graham
+suspension
+bristol
+margaret
+compaq
+correction
+slowly
+authentication
+communicate
+supplement
+showtimes
+portions
+infant
+promoting
+sectors
+samuel
+grounds
+regards
+machinery
+bandwidth
+unlike
+equation
+baskets
+probability
+dimension
+wright
+proven
+schedules
+admissions
+cached
+warren
+studied
+reviewer
+involves
+quarterly
+profits
+comply
+florist
+illustrated
+cherry
+continental
+alternate
+deutsch
+achievement
+limitations
+webcam
+funeral
+nutten
+earrings
+enjoyed
+automated
+chapters
+charlie
+quebec
+passenger
+convenient
+dennis
+francis
+noticed
+socket
+silent
+literary
+signals
+orientation
+childhood
+symbols
+humans
+analog
+facial
+choosing
+talent
+flexibility
+seeker
+wisdom
+boundary
+packard
+offset
+payday
+philip
+holders
+believes
+swedish
+deadline
+jurisdiction
+displaying
+witness
+collins
+equipped
+stages
+encouraged
+powder
+broadway
+acquired
+assess
+cartridges
+stones
+entrance
+declaration
+losing
+attempts
+gadgets
+glasgow
+automation
+impacts
+gospel
+advantages
+induced
+knight
+preparing
+recipient
+linking
+extensions
+appeals
+earned
+illness
+islamic
+athletics
+southeast
+alternatives
+pending
+parker
+determining
+lebanon
+personalized
+kennedy
+conditioning
+teenage
+triple
+cooper
+vincent
+secured
+unusual
+answered
+partnerships
+destruction
+increasingly
+migration
+disorder
+routine
+toolbar
+basically
+conventional
+titans
+applicants
+wearing
+sought
+mounted
+habitat
+firewall
+median
+scanner
+herein
+occupational
+animated
+judicial
+adjustment
+integer
+treatments
+bachelor
+attitude
+camcorders
+engaged
+falling
+basics
+montreal
+carpet
+struct
+lenses
+binary
+genetics
+attended
+difficulty
+collective
+coalition
+dropped
+enrollment
+walter
+besides
+producers
+collector
+interfaces
+advertisers
+moments
+strings
+representing
+observation
+torture
+deleted
+mitchell
+restoration
+convenience
+returning
+opposition
+container
+defendant
+warner
+confirmation
+embedded
+inkjet
+supervisor
+wizard
+actors
+peripherals
+liable
+brochure
+morris
+bestsellers
+petition
+eminem
+recall
+antenna
+picked
+assumed
+departure
+minneapolis
+belief
+killing
+bikini
+memphis
+shoulder
+lookup
+harvard
+brokers
+diameter
+ottawa
+podcast
+seasons
+interactions
+refine
+bidder
+singer
+herald
+literacy
+intervention
+plugin
+attraction
+diving
+invite
+modification
+latinas
+suppose
+customized
+involve
+moderate
+terror
+younger
+thirty
+opposite
+understood
+rapidly
+dealtime
+mercedes
+assurance
+happening
+outline
+amendments
+tramadol
+holland
+receives
+metropolitan
+compilation
+verification
+refers
+veterans
+attractive
+occasion
+recordings
+jefferson
+victim
+demands
+sleeping
+careful
+gardening
+obligations
+arrive
+orchestra
+sunset
+tracked
+moreover
+minimal
+polyphonic
+lottery
+framed
+outsourcing
+licence
+adjustable
+allocation
+michelle
+discipline
+demonstrated
+dialogue
+identifying
+alphabetical
+declared
+dispatched
+handheld
+disposal
+florists
+installing
+switches
+romania
+voluntary
+consult
+greatly
+blogging
+cycling
+midnight
+commonly
+photographer
+inform
+turkish
+messaging
+pentium
+quantum
+murray
+intent
+largely
+pleasant
+announce
+constructed
+additions
+requiring
+engagement
+sampling
+refinance
+inspired
+weddings
+suddenly
+oxygen
+cookie
+canyon
+meters
+merely
+calendars
+arrangement
+conclusions
+passes
+bibliography
+pointer
+compatibility
+stretch
+durham
+furthermore
+permits
+cooperative
+muslim
+sleeve
+netscape
+cleaner
+cricket
+feeding
+stroke
+township
+rankings
+measuring
+robinson
+jacksonville
+headquarters
+sharon
+transfers
+olympic
+transformation
+remained
+attachments
+entities
+customs
+administrators
+personality
+rainbow
+roulette
+decline
+gloves
+israeli
+medicare
+skiing
+facilitate
+subscriber
+hewlett
+explains
+proceed
+flickr
+feelings
+jamaica
+priorities
+bookstore
+timing
+parenting
+denied
+incredible
+britney
+freeware
+donation
+deaths
+rivers
+commonwealth
+pharmaceutical
+manhattan
+katrina
+workforce
+thumbs
+targeted
+organizational
+realized
+twelve
+founder
+decade
+gamecube
+dispute
+portuguese
+titten
+adverse
+everywhere
+excerpt
+discharge
+drinks
+voices
+halloween
+climbing
+perfume
+honest
+albany
+hazardous
+restore
+methodology
+somebody
+housewares
+reputation
+resistant
+democrats
+recycling
+creator
+qualifications
+museums
+coding
+slideshow
+tracker
+variation
+passage
+transferred
+hiking
+pierre
+jelsoft
+headset
+photograph
+oakland
+colombia
+distributor
+underlying
+wrestling
+suicide
+archived
+photoshop
+arabia
+gathering
+projection
+mathematical
+logical
+extract
+specialized
+diagnostic
+panama
+indianapolis
+payable
+corporations
+courtesy
+criticism
+automobile
+confidential
+statutory
+accommodations
+athens
+northeast
+downloaded
+judges
+retired
+remarks
+detected
+decades
+paintings
+walked
+arising
+nissan
+bracelet
+juvenile
+injection
+yorkshire
+populations
+protective
+afraid
+acoustic
+railway
+cassette
+initially
+indicator
+pointed
+causing
+mistake
+norton
+locked
+eliminate
+fusion
+mineral
+sunglasses
+steering
+fortune
+preference
+canvas
+threshold
+parish
+claimed
+screens
+cemetery
+planner
+croatia
+stadium
+venezuela
+exploration
+sequences
+coupon
+nurses
+astronomy
+edwards
+contests
+translate
+announces
+costume
+tagged
+berkeley
+killer
+adjusted
+bishop
+pulled
+shaped
+compression
+seasonal
+establishing
+farmer
+counters
+constitutional
+perfectly
+instantly
+cultures
+norfolk
+coaching
+examined
+encoding
+litigation
+submissions
+heroes
+painted
+broadcasting
+horizontal
+artwork
+cosmetic
+resulted
+portrait
+terrorist
+informational
+ethical
+carriers
+ecommerce
+mobility
+floral
+builders
+struggle
+schemes
+suffering
+neutral
+fisher
+spears
+prospective
+bedding
+ultimately
+joining
+heading
+equally
+artificial
+bearing
+spectacular
+coordination
+connector
+seniors
+worlds
+guilty
+affiliated
+activation
+naturally
+tablet
+subscribers
+violent
+mitsubishi
+underwear
+potentially
+constraints
+crossing
+inclusive
+dimensional
+cottage
+considerable
+crimes
+resolved
+mozilla
+branches
+anymore
+holdings
+locator
+selecting
+processors
+pantyhose
+zimbabwe
+difficulties
+complexity
+constantly
+browsing
+resolve
+barcelona
+presidential
+documentary
+territories
+melissa
+moscow
+thesis
+palestinian
+bargains
+frequent
+nigeria
+ceiling
+pixels
+ensuring
+hispanic
+legislature
+hospitality
+anybody
+procurement
+diamonds
+untitled
+totals
+marriott
+singing
+theoretical
+afford
+exercises
+starring
+referral
+surveillance
+optimal
+distinct
+protocols
+highlight
+substitute
+inclusion
+hopefully
+brilliant
+turner
+sucking
+reuters
+spoken
+evaluated
+stayed
+assignments
+manuals
+termination
+watched
+thereof
+households
+redeem
+rogers
+authentic
+regime
+wishes
+montgomery
+architectural
+louisville
+depend
+differ
+macintosh
+movements
+ranging
+monica
+repairs
+breath
+amenities
+virtually
+candle
+hanging
+colored
+authorization
+verified
+formerly
+projector
+situated
+comparative
+herbal
+loving
+strictly
+routing
+stanley
+psychological
+surprised
+retailer
+vitamins
+elegant
+renewal
+genealogy
+opposed
+deemed
+scoring
+expenditure
+brooklyn
+liverpool
+sisters
+critics
+connectivity
+algorithms
+hacker
+madrid
+similarly
+margin
+solely
+collaborative
+norman
+excluding
+headed
+voters
+madonna
+commander
+murphy
+thinks
+suggestion
+soldier
+phillips
+justin
+interval
+mirrors
+spotlight
+tricks
+investigate
+expansys
+panels
+repeated
+assault
+connecting
+logistics
+tongue
+bowling
+danish
+monkey
+proportion
+filename
+florence
+invest
+analyses
+drawings
+significance
+scenario
+lovers
+atomic
+approx
+symposium
+arabic
+essentials
+junction
+protecting
+rachel
+solving
+transmitted
+weekends
+screenshots
+produces
+intensive
+chains
+kingston
+engage
+deviant
+switching
+quoted
+adapters
+correspondence
+imports
+supervision
+bronze
+expenditures
+separation
+testimony
+suspect
+celebrities
+sender
+mandatory
+boundaries
+crucial
+syndication
+celebration
+adjacent
+filtering
+tuition
+spouse
+exotic
+viewer
+signup
+threats
+luxembourg
+puzzles
+reaching
+damaged
+receptor
+surgical
+destroy
+citation
+premises
+proved
+offensive
+imperial
+benjamin
+deployment
+studying
+colleagues
+salmon
+olympus
+separated
+directive
+starter
+upgrades
+butter
+pepper
+weapon
+luggage
+burden
+stylish
+grocery
+offshore
+governing
+retailers
+kenneth
+harrison
+occasionally
+attending
+emission
+finest
+realty
+recruiting
+apparent
+instructional
+autumn
+traveling
+permissions
+biotechnology
+toilet
+ranked
+jackets
+routes
+packed
+excited
+outreach
+mounting
+recover
+balanced
+prescribed
+catherine
+timely
+talked
+upskirts
+delayed
+reproduced
+explicit
+calculation
+villas
+consolidated
+exclude
+peeing
+occasions
+brooks
+equations
+newton
+exceptional
+anxiety
+whilst
+spatial
+respondents
+ceramic
+prompt
+precious
+annually
+considerations
+scanners
+fingers
+ebooks
+delivers
+queensland
+necklace
+musicians
+composite
+unavailable
+arranged
+theaters
+advocacy
+raleigh
+essentially
+designing
+threaded
+qualify
+assessments
+diagram
+footwear
+beijing
+peoples
+victor
+attach
+licenses
+removing
+advised
+brunswick
+spider
+ranges
+sensitivity
+trails
+preservation
+hudson
+isolated
+calgary
+interim
+assisted
+divine
+streaming
+approve
+compound
+intensity
+technological
+syndicate
+abortion
+dialog
+venues
+wellness
+calcium
+newport
+antivirus
+addressing
+discounted
+indians
+shield
+harvest
+membrane
+prague
+previews
+bangladesh
+constitute
+locally
+concluded
+pickup
+desperate
+mothers
+nascar
+iceland
+demonstration
+governmental
+manufactured
+candles
+graduation
+sailing
+variations
+sacred
+addiction
+morocco
+chrome
+springfield
+refused
+exterior
+greeting
+ecology
+oliver
+botswana
+delays
+synthesis
+undefined
+unemployment
+verizon
+scored
+enhancement
+newcastle
+velocity
+lambda
+composed
+performances
+baseline
+societies
+silicon
+brazilian
+identical
+petroleum
+compete
+norwegian
+belong
+honolulu
+beatles
+retention
+exchanges
+thomson
+barnes
+soundtrack
+wondering
+rabbit
+profession
+seating
+separately
+physiology
+collecting
+exports
+participant
+scholarships
+recreational
+dominican
+electron
+friendship
+heather
+passport
+unions
+treasury
+warrant
+solaris
+frozen
+occupied
+royalty
+scales
+observer
+sunshine
+strain
+ceremony
+somehow
+arrested
+expanding
+provincial
+investigations
+yamaha
+medications
+hebrew
+gained
+rochester
+laundry
+solomon
+placing
+homework
+adjust
+assessed
+advertiser
+enabling
+encryption
+filling
+downloadable
+sophisticated
+imposed
+silence
+focuses
+soviet
+possession
+laboratories
+treaty
+trainer
+stronger
+volumes
+advances
+vegetables
+thumbnails
+darkness
+bizrate
+vienna
+implied
+stanford
+stockings
+respondent
+packing
+statute
+rejected
+satisfy
+destroyed
+shelter
+chapel
+gamespot
+manufacture
+layers
+wordpress
+guided
+vulnerability
+accountability
+celebrate
+accredited
+appliance
+compressed
+bahamas
+powell
+mixture
+scheduling
+radius
+perspectives
+mortality
+logging
+hampton
+christians
+borders
+therapeutic
+impressive
+accordingly
+architect
+railroad
+lectures
+challenging
+nursery
+harder
+microwave
+cheapest
+accidents
+travesti
+relocation
+stuart
+contributors
+salvador
+monroe
+tender
+violations
+temperatures
+clouds
+competitions
+discretion
+tanzania
+preserve
+unsigned
+staying
+cosmetics
+easter
+theories
+repository
+praise
+jeremy
+venice
+concentrations
+vibrators
+estonia
+christianity
+veteran
+streams
+landing
+signing
+executed
+negotiations
+realistic
+showcase
+integral
+namibia
+generating
+christina
+congressional
+synopsis
+hardly
+prairie
+reunion
+composer
+absent
+photographic
+ecuador
+hoping
+accessed
+spirits
+modifications
+imported
+bubble
+acquire
+contrary
+millennium
+tribune
+vessel
+focusing
+viruses
+cheaper
+admitted
+equality
+achieving
+stickers
+fisheries
+exceptions
+reactions
+leasing
+lauren
+beliefs
+macromedia
+companion
+analyze
+ashley
+scroll
+relate
+divisions
+additionally
+suffer
+forests
+fellowship
+invalid
+concerts
+martial
+victorian
+retain
+colours
+execute
+tunnel
+genres
+cambodia
+patents
+copyrights
+lithuania
+mastercard
+chronicles
+obtaining
+beaver
+updating
+distribute
+readings
+decorative
+kijiji
+confused
+compiler
+enlargement
+eagles
+accused
+campaigns
+conjunction
+defines
+airports
+instances
+indigenous
+brunette
+packets
+anchor
+validation
+parade
+corruption
+trigger
+incentives
+cholesterol
+gathered
+slovenia
+notified
+differential
+beaches
+folders
+dramatic
+surfaces
+terrible
+routers
+pendant
+dresses
+baptist
+scientist
+starsmerchant
+hiring
+clocks
+arthritis
+females
+wallace
+nevertheless
+reflects
+taxation
+cuisine
+surely
+practitioners
+transcript
+myspace
+theorem
+inflation
+stylus
+compounds
+contracting
+arnold
+structured
+reasonably
+chicks
+cattle
+radical
+graduates
+recommends
+controlling
+treasure
+reload
+distributors
+levitra
+assuming
+monetary
+elderly
+arlington
+particles
+floating
+extraordinary
+indicating
+bolivia
+hottest
+stevens
+coordinate
+kuwait
+exclusively
+alleged
+limitation
+widescreen
+compile
+squirting
+webster
+struck
+illustration
+plymouth
+warnings
+construct
+inquiries
+bridal
+inspiration
+tribal
+curious
+affecting
+freight
+rebate
+meetup
+eclipse
+downloading
+shuttle
+aggregate
+stunning
+cycles
+affects
+forecasts
+detect
+actively
+ampland
+complicated
+fastest
+butler
+shopzilla
+injured
+decorating
+payroll
+cookbook
+expressions
+courier
+uploaded
+shakespeare
+collapse
+americas
+connectors
+twinks
+unlikely
+conflicts
+techno
+beverage
+tribute
+immune
+latvia
+travelers
+forestry
+barriers
+rarely
+infected
+offerings
+martha
+genesis
+barrier
+incorrect
+trains
+metals
+bicycle
+furnishings
+letting
+guatemala
+celtic
+thereby
+particle
+perception
+minerals
+advise
+humidity
+bottles
+boxing
+bangkok
+renaissance
+pathology
+ordinance
+hughes
+photographers
+infections
+jeffrey
+operates
+brisbane
+configured
+survive
+festivals
+possibilities
+reveal
+contributing
+clinics
+manitoba
+analytical
+missions
+watson
+costumes
+strict
+saddam
+circulation
+offense
+protest
+assumption
+jerusalem
+transexuales
+invention
+nickname
+technician
+inline
+executives
+enquiries
+washing
+staffing
+cognitive
+exploring
+enquiry
+closure
+timber
+intense
+playlist
+registrar
+showers
+supporters
+ruling
+steady
+statutes
+withdrawal
+predicted
+saskatchewan
+cancellation
+plugins
+enrolled
+sensors
+ministers
+publicly
+hourly
+geneva
+freebsd
+veterinary
+prostores
+reseller
+handed
+suffered
+intake
+informal
+relevance
+incentive
+butterfly
+tucson
+mechanics
+heavily
+swingers
+headers
+mistakes
+numerical
+defining
+counting
+reflection
+accompanied
+assure
+invitation
+devoted
+princeton
+sodium
+spirituality
+hormone
+meanwhile
+proprietary
+timothy
+childrens
+thumbzilla
+medieval
+porcelain
+bridges
+pichunter
+captured
+thehun
+decent
+casting
+dayton
+translated
+shortly
+cameron
+columnists
+carlos
+andreas
+warrior
+diploma
+innocent
+scanning
+consensus
+valium
+copying
+delivering
+cordless
+patricia
+uganda
+journalism
+trivia
+adidas
+grammar
+intention
+disagree
+harvey
+undertaken
+hazard
+livesex
+statewide
+semiconductor
+gregory
+episodes
+boolean
+circular
+mainland
+illustrations
+chances
+interact
+happiness
+substantially
+bizarre
+auckland
+olympics
+fruits
+identifier
+worldsex
+ribbon
+calculations
+conducting
+startup
+suzuki
+trinidad
+kissing
+exempt
+reduces
+accomplished
+calculators
+geometry
+impression
+slovakia
+correlation
+gorgeous
+capitol
+dishes
+barbados
+chrysler
+nervous
+refuse
+extends
+fragrance
+mcdonald
+replica
+plumbing
+brussels
+neighbors
+trades
+superb
+transparent
+trinity
+charleston
+handled
+legends
+champions
+floors
+selections
+projectors
+inappropriate
+exhaust
+comparing
+shanghai
+speaks
+burton
+vocational
+davidson
+copied
+scotia
+farming
+gibson
+pharmacies
+roller
+introducing
+organize
+appreciated
+nicole
+latino
+mixing
+handles
+skilled
+fitted
+albuquerque
+harmony
+distinguished
+asthma
+projected
+assumptions
+shareholders
+developmental
+regulated
+triangle
+anticipated
+oriental
+reward
+windsor
+zambia
+completing
+hydrogen
+webshots
+sprint
+comparable
+advocate
+confusion
+copyrighted
+inputs
+warranties
+genome
+escorts
+documented
+paperbacks
+coaches
+vessels
+harbour
+keyboards
+knives
+vulnerable
+arrange
+artistic
+honors
+reflected
+unified
+detector
+ignored
+fallen
+precise
+sussex
+respiratory
+notifications
+transexual
+mainstream
+invoice
+evaluating
+subcommittee
+gather
+maternity
+backed
+alfred
+colonial
+motels
+forming
+embassy
+journalists
+rebecca
+slight
+proceeds
+indirect
+amongst
+foundations
+msgstr
+arrest
+volleyball
+adipex
+horizon
+deeply
+toolbox
+marina
+liabilities
+prizes
+bosnia
+browsers
+decreased
+tolerance
+surfing
+creativity
+describing
+optics
+pursue
+lightning
+overcome
+quotations
+inspector
+attract
+brighton
+bookmarks
+disable
+succeed
+leonard
+lending
+reminder
+searched
+behavioral
+riverside
+bathrooms
+plains
+raymond
+insights
+abilities
+initiated
+sullivan
+midwest
+karaoke
+lonely
+nonprofit
+lancaster
+suspended
+hereby
+observe
+containers
+attitudes
+collar
+simultaneously
+racial
+integrate
+bermuda
+amanda
+sociology
+mobiles
+screenshot
+exhibitions
+kelkoo
+confident
+retrieved
+exhibits
+officially
+consortium
+terrace
+bacteria
+replied
+seafood
+novels
+recipients
+delicious
+traditions
+safely
+finite
+kidney
+periodically
+durable
+allied
+throws
+moisture
+hungarian
+roster
+referring
+symantec
+spencer
+wichita
+nasdaq
+uruguay
+transform
+tablets
+tuning
+gotten
+educators
+futures
+vegetable
+humanities
+independently
+wanting
+custody
+scratch
+launches
+alignment
+masturbating
+henderson
+britannica
+competitors
+rocket
+bullet
+towers
+visibility
+latitude
+consciousness
+deposits
+beverly
+mistress
+encounter
+trustees
+duncan
+reprints
+bernard
+resolutions
+accessing
+attempted
+midlands
+priest
+ronald
+analysts
+trance
+locale
+nicholas
+bundle
+hammer
+invasion
+witnesses
+runner
+administered
+notion
+mailed
+fujitsu
+spelling
+arctic
+rewards
+beneath
+strengthen
+defend
+frederick
+medicaid
+infrared
+seventh
+aggressive
+advertisements
+quarters
+stolen
+sublimedirectory
+soonest
+disturbed
+determines
+sculpture
+naturals
+motivation
+lenders
+pharmacology
+fitting
+fixtures
+bloggers
+agrees
+passengers
+quantities
+petersburg
+consistently
+powerpoint
+surplus
+obituaries
+cheers
+punishment
+appreciation
+subsequently
+belarus
+zoning
+gravity
+providence
+restriction
+incorporate
+backgrounds
+treasurer
+guitars
+essence
+flooring
+lightweight
+ethiopia
+mighty
+athletes
+humanity
+transcription
+holmes
+complications
+scholars
+scripting
+remembered
+galaxy
+chester
+snapshot
+caring
+synthetic
+segments
+testament
+dominant
+specifics
+itunes
+stomach
+partially
+buried
+newbie
+minimize
+darwin
+wilderness
+generations
+tournaments
+bradley
+anatomy
+sponsorship
+headphones
+fraction
+proceeding
+defects
+volkswagen
+uncertainty
+breakdown
+milton
+marker
+reconstruction
+subsidiary
+strengths
+clarity
+sandra
+adelaide
+encouraging
+furnished
+monaco
+settled
+folding
+emirates
+terrorists
+airfare
+comparisons
+beneficial
+distributions
+vaccine
+belize
+viewpicture
+promised
+robust
+bookings
+threatened
+minolta
+republicans
+discusses
+porter
+jungle
+responded
+abstracts
+alpine
+prediction
+pharmaceuticals
+andale
+fabulous
+thesaurus
+individually
+battlefield
+literally
+ecological
+implies
+cooler
+appraisal
+consisting
+maritime
+periodic
+submitting
+overhead
+prospect
+shipment
+breeding
+citations
+geographical
+mozambique
+tension
+shapes
+envelope
+homeland
+disclaimers
+championships
+excluded
+andrea
+breeds
+rapids
+sheffield
+bailey
+finishing
+emotions
+wellington
+incoming
+prospects
+lexmark
+cleaners
+bulgarian
+eternal
+cashiers
+aboriginal
+remarkable
+rotation
+preventing
+productive
+boulevard
+eugene
+metric
+compliant
+penalties
+bennett
+imagination
+hotmail
+refurbished
+joshua
+armenia
+varied
+grande
+closest
+activated
+actress
+conferencing
+assign
+armstrong
+politicians
+trackbacks
+accommodate
+tigers
+aurora
+slides
+premiere
+lender
+villages
+chorus
+christine
+rhythm
+argued
+dietary
+symphony
+clarke
+sudden
+accepting
+precipitation
+marilyn
+findlaw
+claire
+isolation
+speeds
+sustained
+matched
+approximate
+carroll
+rational
+programmer
+fighters
+chambers
+greetings
+inherited
+warming
+incomplete
+vocals
+chronicle
+fountain
+chubby
+legitimate
+biographies
+burner
+investigator
+plaintiff
+finnish
+gentle
+prisoners
+deeper
+muslims
+mediterranean
+nightlife
+footage
+worthy
+reveals
+architects
+saints
+entrepreneur
+carries
+freelance
+excessive
+screensaver
+helena
+regarded
+valuation
+unexpected
+cigarette
+characteristic
+marion
+egyptian
+tunisia
+metallica
+outlined
+consequently
+headline
+treating
+appointments
+cowboy
+narrative
+bahrain
+enormous
+consist
+queens
+academics
+quantitative
+shemales
+screensavers
+subdivision
+tribes
+defeat
+clicks
+distinction
+honduras
+naughty
+hazards
+insured
+harper
+livestock
+exemption
+tenant
+sustainability
+cabinets
+tattoo
+algebra
+shadows
+formatting
+nutritional
+hartford
+freely
+marcus
+sunrise
+wrapping
+nicaragua
+weblogs
+timeline
+belongs
+readily
+affiliation
+nudist
+infinite
+ensures
+relatives
+lindsay
+legally
+satisfactory
+revolutionary
+bracelets
+civilian
+telephony
+remedy
+realtors
+breathing
+briefly
+thickness
+adjustments
+graphical
+genius
+discussing
+aerospace
+fighter
+meaningful
+retreat
+adapted
+barely
+wherever
+estates
+democrat
+borough
+maintains
+failing
+shortcuts
+retained
+voyeurweb
+pamela
+andrews
+marble
+extending
+specifies
+logitech
+surrey
+briefing
+belkin
+accreditation
+blackberry
+highland
+meditation
+modular
+microphone
+macedonia
+combining
+brandon
+instrumental
+giants
+organizing
+balloon
+moderators
+winston
+solved
+kazakhstan
+hawaiian
+standings
+partition
+invisible
+gratuit
+consoles
+magnet
+translations
+porsche
+cayman
+jaguar
+commodity
+posing
+kilometers
+thanksgiving
+hopkins
+urgent
+guarantees
+infants
+gothic
+cylinder
+indication
+congratulations
+graphs
+surround
+cigarettes
+revenge
+expires
+enemies
+controllers
+consultancy
+finances
+accepts
+enjoying
+conventions
+patrol
+italiano
+coordinates
+carnival
+roughly
+sticker
+promises
+responding
+physically
+divide
+stakeholders
+hydrocodone
+consecutive
+cornell
+deserve
+attempting
+mailto
+representations
+worried
+garbage
+competing
+combines
+bradford
+phrases
+peninsula
+chelsea
+boring
+reynolds
+accurately
+speeches
+reaches
+schema
+considers
+catalogs
+ministries
+vacancies
+quizzes
+parliamentary
+prefix
+savannah
+barrel
+typing
+planets
+deficit
+boulder
+pointing
+coupled
+myanmar
+metadata
+harold
+circuits
+floppy
+texture
+handbags
+somerset
+incurred
+acknowledge
+thoroughly
+antigua
+nottingham
+thunder
+caution
+identifies
+questionnaire
+qualification
+modelling
+namely
+miniature
+interstate
+pirates
+aerial
+consequence
+systematic
+perceived
+origins
+makeup
+textile
+madagascar
+nathan
+tobago
+presenting
+troubleshooting
+uzbekistan
+indexes
+centuries
+magnitude
+richardson
+fragrances
+vocabulary
+licking
+earthquake
+fundraising
+markers
+weights
+albania
+geological
+assessing
+lasting
+wicked
+introduces
+roommate
+webcams
+pushed
+webmasters
+computational
+acdbentity
+participated
+handhelds
+answering
+impressed
+reggae
+failures
+conspiracy
+surname
+theology
+evident
+saturn
+organizer
+allergy
+twisted
+combinations
+preceding
+enzyme
+cumulative
+zshops
+planes
+edmonton
+tackle
+pokemon
+amplifier
+ambien
+arbitrary
+prominent
+retrieve
+lexington
+vernon
+worldcat
+titanium
+builds
+contacted
+recorders
+occasional
+leslie
+deutsche
+postings
+innovations
+postcards
+algeria
+blessed
+reviewing
+cardiff
+cornwall
+favors
+potato
+explicitly
+sticks
+transsexual
+citizenship
+excuse
+reforms
+basement
+strand
+sandwich
+lawsuit
+informative
+girlfriend
+bloomberg
+cheque
+hierarchy
+influenced
+banners
+reject
+abandoned
+circles
+italic
+complement
+passive
+mauritius
+valued
+checklist
+bangbus
+requesting
+courage
+lauderdale
+scenarios
+gazette
+hitachi
+extraction
+batman
+elevation
+hearings
+coleman
+utilization
+beverages
+calibration
+efficiently
+anaheim
+textbook
+entertaining
+prerequisite
+luther
+frontier
+settle
+stopping
+refugees
+knights
+hypothesis
+palmer
+medicines
+peaceful
+altered
+pontiac
+regression
+doctrine
+scenic
+trainers
+enhancements
+renewable
+intersection
+passwords
+sewing
+consistency
+collectors
+conclude
+recognised
+munich
+celebs
+propose
+azerbaijan
+lighter
+astrology
+advisors
+pavilion
+tactics
+trusts
+occurring
+supplemental
+travelling
+talented
+pillow
+induction
+precisely
+shorter
+harley
+spreading
+provinces
+relying
+finals
+paraguay
+parcel
+refined
+fifteen
+widespread
+incidence
+predict
+boutique
+acrylic
+rolled
+incidents
+peterson
+shannon
+toddler
+enhancing
+flavor
+homeless
+horrible
+hungry
+metallic
+blocked
+interference
+warriors
+palestine
+listprice
+cadillac
+atmospheric
+malawi
+knowledgestorm
+curtis
+parental
+referenced
+strikes
+lesser
+publicity
+marathon
+proposition
+pressing
+gasoline
+dressed
+belfast
+niagara
+warcraft
+charms
+catalyst
+trader
+allowance
+denial
+designation
+thrown
+prepaid
+raises
+duplicate
+electro
+criterion
+civilization
+analyzed
+vietnamese
+tremendous
+ballot
+varying
+remedies
+validity
+trustee
+handjobs
+weighted
+angola
+squirt
+performs
+plastics
+corrected
+helmet
+salaries
+postcard
+elephant
+encountered
+tsunami
+scholar
+nickel
+internationally
+surrounded
+expedia
+geology
+creatures
+coating
+commented
+wallet
+cleared
+smilies
+accomplish
+boating
+drainage
+shakira
+corners
+broader
+vegetarian
+newfoundland
+clearing
+investigated
+ambassador
+coated
+intend
+stephanie
+contacting
+vegetation
+findarticles
+louise
+specially
+routines
+hitting
+beings
+aquatic
+reliance
+habits
+striking
+infectious
+podcasts
+gilbert
+ferrari
+continuity
+outputs
+phenomenon
+ensemble
+insulin
+assured
+biblical
+conscious
+accent
+mysimon
+eleven
+ambient
+utilize
+mileage
+prostate
+adaptor
+auburn
+unlock
+hyundai
+pledge
+vampire
+angela
+relates
+nitrogen
+merger
+softball
+referrals
+differently
+firewire
+nextel
+framing
+organised
+musician
+blocking
+rwanda
+integrating
+limiting
+dispatch
+revisions
+restored
+riders
+chargers
+remark
+dozens
+varies
+reasoning
+rendered
+picking
+charitable
+guards
+annotated
+convinced
+openings
+burlington
+replacing
+researcher
+watershed
+councils
+occupations
+acknowledged
+kruger
+pockets
+granny
+equilibrium
+inquire
+characterized
+cottages
+realtor
+privilege
+develops
+qualifying
+chassis
+estimation
+pushing
+fleece
+pediatric
+pierce
+dressing
+techrepublic
+institutes
+prefers
+drilling
+brochures
+breach
+traveller
+appropriations
+suspected
+tomatoes
+benchmark
+beginners
+instructors
+highlighted
+bedford
+stationery
+mustang
+unauthorized
+clusters
+antibody
+competent
+momentum
+wiring
+pastor
+calvin
+contributor
+demonstrates
+phases
+grateful
+emerald
+gradually
+laughing
+desirable
+ballet
+journalist
+abraham
+bumper
+afterwards
+webpage
+religions
+garlic
+hostels
+senegal
+explosion
+banned
+briefs
+signatures
+mumbai
+disciplines
+daughters
+conversations
+radios
+tariff
+nvidia
+opponent
+simplified
+muscles
+wrapped
+motherboard
+runtime
+bibliographic
+distant
+champagne
+decimal
+deviation
+superintendent
+propecia
+hostel
+housewives
+employ
+mongolia
+penguin
+magical
+influences
+inspections
+irrigation
+miracle
+manually
+reprint
+hydraulic
+centered
+robertson
+yearly
+penetration
+conviction
+omissions
+writings
+hamburg
+retrieval
+qualities
+fathers
+charging
+marvel
+prototype
+importantly
+petite
+apparatus
+terrain
+explaining
+strips
+gossip
+rangers
+nomination
+empirical
+rotary
+dependence
+discrete
+beginner
+sexuality
+polyester
+commitments
+suggesting
+sapphire
+kinase
+skirts
+remainder
+crawford
+labeled
+privileges
+televisions
+specializing
+marking
+commodities
+serbia
+sheriff
+griffin
+declined
+guyana
+neighbor
+motorcycles
+highways
+thinkpad
+concentrate
+intimate
+reproductive
+preston
+deadly
+molecules
+rounds
+longest
+refrigerator
+intervals
+sentences
+dentists
+exclusion
+workstation
+holocaust
+dosage
+receivers
+customise
+disposition
+variance
+navigator
+investigators
+cameroon
+baking
+marijuana
+adaptive
+computed
+needle
+cathedral
+brakes
+nirvana
+fairfield
+invision
+sticky
+destiny
+generous
+madness
+blowing
+fascinating
+landscapes
+heated
+lafayette
+jackie
+computation
+cardiovascular
+cardiac
+salvation
+adrian
+predictions
+accompanying
+vatican
+brutal
+learners
+selective
+arbitration
+configuring
+editorials
+sacrifice
+seekers
+removable
+convergence
+yields
+gibraltar
+suited
+numeric
+anthropology
+skating
+aberdeen
+emperor
+malpractice
+blacks
+educated
+rebates
+reporters
+proudly
+necessity
+rendering
+inserted
+pulling
+basename
+obesity
+curves
+suburban
+touring
+vertex
+hepatitis
+nationally
+tomato
+andorra
+waterproof
+expired
+travels
+waiver
+specialties
+humanitarian
+invitations
+functioning
+delight
+survivor
+garcia
+cingular
+economies
+alexandria
+bacterial
+counted
+undertake
+declare
+continuously
+valves
+impaired
+achievements
+donors
+convertible
+teaches
+ventures
+bufing
+stranger
+tragedy
+julian
+painful
+velvet
+tribunal
+pensions
+prayers
+secretariat
+nowhere
+paragraphs
+adolescent
+nominations
+wesley
+lately
+cancelled
+mattress
+brunei
+likewise
+banana
+introductory
+slovak
+reservoir
+occurrence
+remind
+worcester
+demographic
+charming
+disciplinary
+annoying
+respected
+disclose
+affair
+washer
+restrict
+springer
+beside
+portraits
+rebound
+mentor
+interpreted
+evaluations
+fought
+baghdad
+elimination
+metres
+hypothetical
+immigrants
+complimentary
+helicopter
+pencil
+freeze
+performer
+titled
+commissions
+sphere
+powerseller
+ratios
+concord
+graduated
+endorsed
+surprising
+walnut
+ladder
+italia
+unnecessary
+dramatically
+liberia
+sherman
+maximize
+hansen
+senators
+workout
+yugoslavia
+bleeding
+characterization
+likelihood
+fundamentals
+contamination
+endangered
+compromise
+masturbation
+optimize
+stating
+caroline
+expiration
+namespace
+peripheral
+engaging
+negotiation
+opponents
+triumph
+nominated
+confidentiality
+electoral
+changelog
+welding
+deferred
+alternatively
+condos
+polished
+gently
+greensboro
+locking
+controversial
+fridge
+blanket
+simpsons
+elliott
+recovered
+fraser
+justify
+upgrading
+blades
+frontpage
+trauma
+advert
+possess
+demanding
+defensive
+flashers
+subaru
+forbidden
+vanilla
+programmers
+monitored
+installations
+deutschland
+picnic
+arrivals
+practitioner
+motivated
+smithsonian
+hollow
+securely
+examining
+fioricet
+groove
+revelation
+pursuit
+delegation
+dictionaries
+backing
+greenhouse
+sleeps
+transparency
+travis
+endless
+figured
+currencies
+survivors
+positioning
+heater
+colony
+cannon
+circus
+promoted
+forbes
+moldova
+descending
+enclosed
+temporarily
+cooked
+thriller
+transmit
+gerald
+pressed
+frequencies
+scanned
+reflections
+hunger
+mariah
+municipality
+detective
+surgeon
+cement
+experiencing
+fireplace
+endorsement
+planners
+disputes
+textiles
+missile
+intranet
+closes
+psychiatry
+persistent
+deborah
+assists
+summaries
+gabriel
+auditor
+aquarium
+violin
+prophet
+bracket
+looksmart
+magnificent
+colleague
+naples
+promptly
+modems
+adaptation
+harmful
+paintball
+prozac
+sexually
+enclosure
+dividend
+newark
+glucose
+phantom
+playback
+supervisors
+westminster
+turtle
+distances
+absorption
+treasures
+warned
+neural
+fossil
+hometown
+transcripts
+apollo
+disappointed
+persian
+continually
+communist
+collectible
+handmade
+greene
+entrepreneurs
+robots
+grenada
+creations
+acquisitions
+earning
+mailman
+nested
+biodiversity
+excitement
+somalia
+movers
+verbal
+presently
+workflow
+mysterious
+novelty
+bryant
+voyuer
+librarian
+subsidiaries
+switched
+stockholm
+garmin
+indonesian
+therapist
+richards
+budgets
+toolkit
+promising
+relaxation
+render
+carmen
+thereafter
+hardwood
+erotica
+temporal
+commissioners
+forwarding
+nightmare
+airplane
+reductions
+southampton
+istanbul
+impose
+organisms
+telescope
+viewers
+asbestos
+portsmouth
+enters
+savage
+advancement
+harassment
+willow
+resumes
+throwing
+existed
+generators
+barbie
+favour
+generates
+potatoes
+thorough
+replication
+inexpensive
+receptors
+roland
+optimum
+interventions
+huntington
+creature
+mounts
+syracuse
+internship
+refresh
+aluminium
+snowboard
+beastality
+webcast
+michel
+evanescence
+subtle
+coordinated
+shipments
+maldives
+stripes
+firmware
+antarctica
+shepherd
+canberra
+cradle
+chancellor
+controversy
+legendary
+sympathy
+avoiding
+beautifully
+expects
+jumping
+fabrics
+antibodies
+polymer
+hygiene
+poultry
+virtue
+examinations
+surgeons
+bouquet
+immunology
+promotes
+mandate
+departmental
+corpus
+johnston
+terminology
+gentleman
+reproduce
+convicted
+shades
+indices
+roommates
+adware
+threatening
+spokesman
+zoloft
+activists
+frankfurt
+prisoner
+halifax
+encourages
+ultram
+cursor
+assembled
+earliest
+donated
+stuffed
+restructuring
+insects
+terminals
+morrison
+maiden
+simulations
+sufficiently
+examines
+viking
+myrtle
+cleanup
+conditional
+crossword
+bother
+budapest
+conceptual
+knitting
+attacked
+bhutan
+liechtenstein
+mating
+compute
+redhead
+arrives
+translator
+automobiles
+tractor
+continent
+unwrap
+longitude
+resist
+challenged
+telecharger
+insertion
+instrumentation
+wagner
+constraint
+groundwater
+touched
+strengthening
+cologne
+wishing
+ranger
+smallest
+insulation
+newman
+scared
+infringement
+subjective
+monsters
+asylum
+lightbox
+robbie
+cocktail
+outlets
+swaziland
+varieties
+mediawiki
+configurations
+poison
diff --git a/slides/security/script.js b/slides/security/script.js
new file mode 100644
index 0000000..4fd6533
--- /dev/null
+++ b/slides/security/script.js
@@ -0,0 +1,22 @@
+/* global Reveal */
+
+Reveal.initialize({
+ history: true
+})
+
+function getRandomInt (min, max) {
+ return Math.floor(Math.random() * (max - min + 1)) + min
+}
+
+window.fetch('./8char-words.txt').then(r => r.text()).then(res => {
+ const words = res.split('\n')
+ const specialChars = ['.', '-', '_', '!', '@', '#', '$', '%']
+
+ window.setInterval(function () {
+ const randomWord = words[getRandomInt(0, words.length - 1)]
+ const randomSpecialChar = specialChars[getRandomInt(0, specialChars.length - 1)]
+ const randomNumber = getRandomInt(1, 9)
+ const randomPassword = randomWord + randomSpecialChar + randomNumber
+ document.querySelector('#changing-passwd').textContent = randomPassword
+ }, 500)
+})
diff --git a/slides/security/style.css b/slides/security/style.css
new file mode 100644
index 0000000..7d58e78
--- /dev/null
+++ b/slides/security/style.css
@@ -0,0 +1,31 @@
+.profile {
+ background-color: rgba(255, 255, 255, 0.05);;
+ display: flex;
+ align-items: center;
+ border-radius: 8px;
+ max-width: 650px;
+ margin: 0 auto !important;
+}
+
+.profile img {
+ width: 120px;
+ height: 120px;
+ border-radius: 50%;
+ margin: 16px !important;
+}
+
+.profile .info {
+ margin: 16px;
+ text-align: left;
+}
+
+.profile .pgp-key {
+ font-family: "Roboto Mono";
+ font-size: 15px;
+ color: gray;
+}
+
+#changing-passwd {
+ text-transform: capitalize;
+ white-space: nowrap;
+}
diff --git a/slides/xss/index.html b/slides/xss/index.html
new file mode 100644
index 0000000..2e43568
--- /dev/null
+++ b/slides/xss/index.html
@@ -0,0 +1,79 @@
+---
+layout: slides
+title: Security
+scripts: [ ./script.js ]
+styles: [ ../reveal.js/theme/blood.css, ../reveal.js/zenburn.css, ./style.css ]
+---
+<div class="reveal">
+ <div class="slides">
+ <section>
+ <h1>XSS Injections</h1>
+ <div class="profile">
+ <img src="/assets/face.jpg" alt="Noah Loomans">
+ <div class="info">
+ <div class="name">Noah Loomans</div>
+ <div class="pgp-key">67B0 295A C271 345D 0706 4B9B 8B23 75F3 B367 DF6D</div>
+ </div>
+ </div>
+ </section>
+ <section>
+ <h2>Cross Site Scripting</h2>
+ </section>
+ <section>
+ <h2>Sample Code</h2>
+ <pre><code class="hljs" data-trim contenteditable>
+&lt;?php
+
+$sql = "SELECT comment FROM comments";
+$result = $conn->query($sql);
+
+// output data of each row
+while($row = $result->fetch_assoc()) {
+ echo $row["comment"] . "&lt;br&gt;";
+}
+
+?&gt;
+ </code></pre>
+ </section>
+ <section>
+ <h2>What if I enter <code>&lt;b&gt;hello&lt;/b&gt;</code>?</h2>
+ </section>
+ <section>
+ <pre><code class="hljs html" data-trim data-noescape contenteditable>
+&lt;p class="comments"&gt;
+<span class="fragment">This sucks&lt;br&gt;</span>
+<span class="fragment">First!&lt;br&gt;</span>
+<span class="fragment"><mark>&lt;b&gt;hello.&lt;/b&gt;&lt;br&gt;</mark></span>
+&lt;/p&gt;̿
+ </code></pre>
+ </section>
+ <section data-background-image="https://keybase.io/images/blog/zcash/evil.png">
+ <h1><code>&lt;script&gt;</code></h1>
+ </section>
+ <section>
+ <h2>Sample Code</h2>
+ <pre><code class="hljs" data-trim data-noescape contenteditable>
+&lt;?php
+
+$sql = "SELECT comment FROM comments";
+$result = $conn->query($sql);
+
+// output data of each row
+while($row = $result->fetch_assoc()) {
+ echo <span class="fragment" data-fragment-index="2"><mark>htmlspecialchars(</mark></span>$row["comment"]<span class="fragment" data-fragment-index="2"><mark>);</mark></span> . "&lt;br&gt;";
+}
+
+?&gt;
+ </code></pre>
+ <p class="fragment" data-fragment-index="1">
+ Source: <a href="https://www.w3schools.com/php/php_mysql_select.asp">w3schools</a>
+ </p>
+ </section>
+ <section>
+ <h1><code class="hljs">&lt;</code> -> <code class="hljs">&amp;lt;</code></h1>
+ </section>
+ <section>
+ https://hack-challange-nloomans.c9users.io/
+ </section>
+ </div>
+</div>
diff --git a/slides/xss/script.js b/slides/xss/script.js
new file mode 100644
index 0000000..d617911
--- /dev/null
+++ b/slides/xss/script.js
@@ -0,0 +1,6 @@
+/* global Reveal */
+
+Reveal.initialize({
+ history: true,
+ backgroundTransition: 'zoom'
+})
diff --git a/slides/xss/style.css b/slides/xss/style.css
new file mode 100644
index 0000000..d7e92e0
--- /dev/null
+++ b/slides/xss/style.css
@@ -0,0 +1,26 @@
+.profile {
+ background-color: rgba(255, 255, 255, 0.05);;
+ display: flex;
+ align-items: center;
+ border-radius: 8px;
+ max-width: 650px;
+ margin: 0 auto !important;
+}
+
+.profile img {
+ width: 120px;
+ height: 120px;
+ border-radius: 50%;
+ margin: 16px !important;
+}
+
+.profile .info {
+ margin: 16px;
+ text-align: left;
+}
+
+.profile .pgp-key {
+ font-family: "Roboto Mono";
+ font-size: 15px;
+ color: gray;
+}