1
0
mirror of https://github.com/hakimel/reveal.js.git synced 2025-09-23 13:01:32 +02:00

Compare commits

...

28 Commits
0.3.0 ... 1.1.0

Author SHA1 Message Date
Hakim El Hattab
2313dfef6d readme history update 2011-12-26 00:04:11 -08:00
Hakim El Hattab
c7c7735e7a added new transitions (box/page) and a ui theme (neon) 2011-12-26 00:00:38 -08:00
Hakim El Hattab
1ac6386eef fix padding and duplicate background on vertical slides in overview 2011-12-23 21:52:35 -08:00
Hakim El Hattab
b162a54c2d fix clicks on vertical slides in overview 2011-12-23 21:33:28 -08:00
Hakim El Hattab
91ff92e211 skip fragments when in overview 2011-12-23 21:22:13 -08:00
Hakim El Hattab
c6a75117f6 added experimental overview mode (press SPACE) 2011-12-23 02:47:38 -08:00
Hakim El Hattab
adc9ad19ce fallback on 2d transform transitions via feature detect 2011-12-23 00:36:37 -08:00
Hakim El Hattab
f6dc531298 slides three or more steps away from current are now hidden 2011-12-22 22:41:19 -08:00
Hakim El Hattab
01000e1478 only apply background gradient to <html> 2011-12-22 22:01:10 -08:00
Hakim El Hattab
0c231fec38 added '-ms' prefixed properties 2011-12-22 21:30:10 -08:00
Hakim El Hattab
9065114ef0 progress bar is now a div and uses the same transition + easing as slides (fixes #6) 2011-12-22 21:25:15 -08:00
Hakim El Hattab
91c3056a62 Added examples 2011-12-22 20:36:42 -08:00
Hakim El Hattab
abbd027124 updated readme 2011-12-22 00:11:57 -08:00
Hakim El Hattab
4a4ffd518e hide progress by default 2011-12-22 00:03:52 -08:00
Hakim El Hattab
bdff009c74 added optional presentation progress bar 2011-12-22 00:00:29 -08:00
Hakim El Hattab
2026c9645c replaced google logo with a unicorn 2011-12-21 23:03:30 -08:00
Hakim El Hattab
833e298617 comments & typo correction 2011-12-21 20:22:49 -08:00
Hakim El Hattab
11ee006f9d slide with code is now editable, escaped unicode arrows 2011-12-21 20:21:52 -08:00
Hakim El Hattab
60bf197890 Merge pull request #5 from matthewlein/master
contenteditable and arrow keys
2011-12-21 18:19:36 -08:00
Matthew Lein
853efe5043 for contenteditable elements, don't let arrow keys work 2011-12-21 15:11:10 -05:00
Hakim El Hattab
59c9b3c596 fragments now work in vertical slides (fixes #4) 2011-12-17 12:55:25 -08:00
Hakim El Hattab
e6f444a307 disabled overflow on body (fixes #2) 2011-12-05 01:00:52 -08:00
Hakim El Hattab
d2faad4730 fix broken link 2011-12-04 20:53:35 -08:00
Hakim El Hattab
f9527d31b4 fix vertical slide transition and hit areas of rolling links 2011-12-04 19:24:08 -08:00
Hakim El Hattab
233160ff23 cleanup & comments 2011-12-04 18:55:48 -08:00
Hakim El Hattab
b36e8d5c4e readme update 2011-12-04 18:51:09 -08:00
Hakim El Hattab
9edb5f6da0 Updated readme 2011-12-04 18:21:15 -08:00
Hakim El Hattab
a6453a0fb0 renamed to reveal.js, many new features, and upgraded to v1.0 2011-12-04 18:07:33 -08:00
8 changed files with 1700 additions and 414 deletions

View File

@@ -1,8 +1,50 @@
# CSS 3D Slideshow
# reveal.js
Requires a browser with support for CSS 3D transforms, such as Chrome or Safari.
A CSS 3D slideshow tool for quickly creating good looking HTML presentations. Requires a browser with support for CSS 3D transforms, querySelector and classList. Does not _rely_ on any external libraries but [highlight.js](http://softwaremaniacs.org/soft/highlight/en/description/) is included by default for code highlighting.
Curious about how this looks in action? [Check out the demo page.](http://hakim.se/experiments/css/slideshow/).
Curious about how this looks in action? [Check out the demo page](http://lab.hakim.se/reveal-js/).
# Examples
* http://lab.hakim.se/reveal-js/ (original)
* http://www.ideapolisagency.com/ from [@achrafkassioui](http://twitter.com/achrafkassioui)
* http://lucienfrelin.com/ from [@lucienfrelin](http://twitter.com/lucienfrelin)
[Send me a link](http://hakim.se/about/contact) if you used reveal.js for a project or presentation.
# History
### 1.1 (master)
- Added an optional presentation progress bar
- Images wrapped in anchors no longer unexpectedly flip in 3D
- Slides that contain other slides are given the 'stack' class
- Added 'transition' option for specifying transition styles
- Added 'theme' option for specifying UI styles
- New transitions: 'box' & 'page'
- New theme: 'neon'
### 1.0
- New and improved style
- Added controls in bottom right which indicate where you can navigate
- Reveal views in iteratively by giving them the .fragment class
- Code sample syntax highlighting thanks to [highlight.js](http://softwaremaniacs.org/soft/highlight/en/description/)
- Initialization options (toggling controls, toggling rolling links, transition theme)
### 0.3
- Added licensing terms
- Fixed broken links on touch devices
### 0.2
- Refactored code and added inline documentation
- Slides now have unique URL's
- A basic API to invoke navigation was added
### 0.1
- First release
# License

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -1,4 +1,6 @@
/**
* Main styles for reveal.js
*
* @author Hakim El Hattab
*/
@@ -20,35 +22,33 @@
*********************************************/
html, body {
position: relative;
padding: 0;
margin: 0;
overflow: hidden;
font-family: 'Crimson Text', Times, 'Times New Roman', serif;
font-family: 'Lato', Times, 'Times New Roman', serif;
font-size: 36px;
font-weight: 200;
letter-spacing: -0.02em;
background: #fff;
color: #222;
color: #eee;
width: 100%;
height: 100%;
background-image: -webkit-gradient(
radial,
50% 50%, 0,
50% 50%, 1000,
from(rgba(245,245,245,1.0)),
to(rgba(100,100,100,1.0))
);
background-image: -moz-radial-gradient(
50% 50% 90deg,
rgba(245,245,245,1.0) 0%,
rgba(100,100,100,1.0) 100%
);
min-height: 600px;
}
html {
background: #555a5f;
background: -moz-radial-gradient(center, ellipse cover, #555a5f 0%, #1c1e20 100%);
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#555a5f), color-stop(100%,#1c1e20));
background: -webkit-radial-gradient(center, ellipse cover, #555a5f 0%,#1c1e20 100%);
background: -o-radial-gradient(center, ellipse cover, #555a5f 0%,#1c1e20 100%);
background: -ms-radial-gradient(center, ellipse cover, #555a5f 0%,#1c1e20 100%);
background: radial-gradient(center, ellipse cover, #555a5f 0%,#1c1e20 100%);
}
/*********************************************
* HEADERS
@@ -56,16 +56,14 @@ html, body {
h1, h2, h3, h4 {
margin: 0 0 20px 0;
color: #222;
color: #eee;
font-family: 'League Gothic', Arial, Helvetica, sans-serif;
font-family: 'League Gothic', sans-serif;
line-height: 0.9em;
letter-spacing: 0.02em;
text-transform: uppercase;
text-shadow: 0px 1px 0px #eee,
0px 0px 4px #bbb;
text-shadow: 0px 0px 6px rgba(0,0,0,0.2);
}
h1 { font-size: 136px; }
@@ -78,86 +76,40 @@ h2.inverted,
h3.inverted,
h4.inverted {
color: #fff;
text-shadow: 0px 0px 1px #fff,
0px 0px 1px #888;
text-shadow: 0px 0px 2px rgba(0,0,0,0.2);
}
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,.1),
0 0 5px rgba(0,0,0,.1),
0 1px 3px rgba(0,0,0,.3),
0 3px 5px rgba(0,0,0,.2),
0 5px 10px rgba(0,0,0,.25),
0 20px 20px rgba(0,0,0,.15);
}
/*********************************************
* SLIDES
* VIEW FRAGMENTS
*********************************************/
#main {
position: absolute;
width: 800px;
height: 600px;
left: 50%;
top: 50%;
margin-left: -400px;
margin-top: -320px;
text-align: center;
-webkit-perspective: 600px;
-webkit-perspective-origin: 50% 25%;
}
#main>section,
#main>section>section {
display: none;
position: absolute;
width: 100%;
min-height: 600px;
-webkit-transform-style: preserve-3d;
-webkit-transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
-moz-transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
-o-transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
}
#main section.past {
display: block;
#main section .fragment {
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0)
rotateY(-90deg)
translate3d(-100%, 0, 0);
}
#main section.present {
display: block;
position: relative;
z-index: 10;
}
#main section.future {
display: block;
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0)
rotateY(90deg)
translate3d(100%, 0, 0);
}
#main section>section.past {
display: block;
opacity: 0;
-webkit-transform: translate3d(0, -50%, 0)
rotateX(70deg)
translate3d(0, -50%, 0);
}
#main section>section.future {
display: block;
opacity: 0;
-webkit-transform: translate3d(0, 50%, 0)
rotateX(-70deg)
translate3d(0, 50%, 0);
-webkit-transition: all .2s ease;
-moz-transition: all .2s ease;
-ms-transition: all .2s ease;
-o-transition: all .2s ease;
transition: all .2s ease;
}
#main section .fragment.visible {
opacity: 1;
}
/*********************************************
@@ -166,8 +118,22 @@ h4.inverted {
#main>section {
line-height: 1.2em;
text-shadow: 0px 0px 2px #fff, 0px 0px 4px #bbb;
font-weight: 600;
font-weight: normal;
}
strong, b {
font-weight: bold;
}
em, i {
font-style: italic;
}
ol, ul {
display: inline-block;
text-align: left;
margin: 0 auto;
}
ol {
@@ -175,53 +141,715 @@ ol {
list-style-position: inside;
}
li, p {
ul {
list-style: disc;
}
p {
margin-bottom: 10px;
}
blockquote {
display: block;
position: relative;
width: 70%;
margin: 5px auto;
padding: 5px;
font-style: italic;
background: rgba(255, 255, 255, 0.05);
box-shadow: 0px 0px 2px rgba(0,0,0,0.2);
}
blockquote:before {
content: '“';
}
blockquote:after {
content: '”';
}
pre {
display: block;
position: relative;
width: 90%;
margin: 10px auto;
text-align: left;
font-size: 14px;
font-family: monospace;
line-height: 1.1em;
word-wrap: break-word;
box-shadow: 0px 0px 6px rgba(0,0,0,0.3);
}
code {
font-family: monospace;
}
small {
font-size: 60%;
line-height: 1em;
vertical-align: top;
}
q {
font-style: italic;
}
q:before {
content: '“';
}
q:after {
content: '”';
}
a:not(.image) {
color: #1b6263;
color: hsl(185, 85%, 50%);
text-decoration: none;
border-bottom: 1px dashed rgba(0,0,0,0.3);
padding: 1px 3px;
-webkit-transition: all .2s ease;
-moz-transition: all .2s ease;
-ms-transition: all .2s ease;
-o-transition: all .2s ease;
transition: all .2s ease;
}
a:not(.image):hover {
color: #fff;
background: #2fa794;
color: hsl(185, 85%, 70%);
background: hsla(185, 25%, 20%, 0.4);
text-shadow: none;
border: none;
border-radius: 2px;
}
img {
section img {
margin: 30px 0 0 0;
background: rgba(255,255,255,0.12);
border: 4px solid #eee;
-webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
-moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
-o-box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
-webkit-transition: all .11s linear;
-moz-transition: all .11s linear;
-o-transition: all .11s linear;
transition: all .11s linear;
-webkit-transition: all .2s linear;
-moz-transition: all .2s linear;
-ms-transition: all .2s linear;
-o-transition: all .2s linear;
transition: all .2s linear;
}
a.image:hover img {
background: rgba(255,255,255,0.2);
border-color: #13DAEC;
-webkit-box-shadow: 0 0 20px rgba(0, 0, 0, 0.25);
-moz-box-shadow: 0 0 20px rgba(0, 0, 0, 0.25);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.25);
-webkit-box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
-moz-box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
-o-box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
}
/*********************************************
* CONTROLS
*********************************************/
.controls {
display: none;
position: fixed;
width: 100px;
height: 100px;
right: 0;
bottom: 0;
}
.controls a {
font-size: 30px;
position: absolute;
opacity: 0.1;
color: #fff;
}
.controls a.enabled {
opacity: 0.6;
color: hsl(185, 85%, 70%);
text-shadow: 0px 0px 2px hsla(185, 45%, 70%, 0.3);
}
.controls a.enabled:active {
margin-top: 1px;
}
.controls .left {
top: 30px;
}
.controls .right {
left: 60px;
top: 30px;
}
.controls .up {
left: 30px;
}
.controls .down {
left: 30px;
top: 60px;
}
/*********************************************
* PROGRESS BAR
*********************************************/
.progress {
position: fixed;
display: none;
height: 4px;
width: 100%;
bottom: 0;
left: 0;
background: rgba(0,0,0,0.2);
}
.progress span {
display: block;
background: hsl(185, 85%, 50%);
height: 100%;
width: 0px;
-webkit-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
-moz-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
-ms-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
-o-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
}
/*********************************************
* ROLLING LINKS
*********************************************/
.roll {
display: inline-block;
overflow: hidden;
vertical-align: top;
-webkit-perspective: 400px;
-moz-perspective: 400px;
-ms-perspective: 400px;
perspective: 400px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}
.roll:hover {
background: none;
text-shadow: none;
}
.roll span {
display: block;
position: relative;
padding: 0 2px;
pointer-events: none;
-webkit-transition: all 400ms ease;
-moz-transition: all 400ms ease;
-ms-transition: all 400ms ease;
transition: all 400ms ease;
-webkit-transform-origin: 50% 0%;
-moz-transform-origin: 50% 0%;
-ms-transform-origin: 50% 0%;
transform-origin: 50% 0%;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.roll:hover span {
background: rgba(0,0,0,0.5);
-webkit-transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
-moz-transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
-ms-transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
}
.roll span:after {
content: attr(data-title);
display: block;
position: absolute;
left: 0;
top: 0;
padding: 0 2px;
color: #fff;
background: hsl(185, 60%, 35%);
-webkit-transform-origin: 50% 0%;
-moz-transform-origin: 50% 0%;
-ms-transform-origin: 50% 0%;
transform-origin: 50% 0%;
-webkit-transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
-moz-transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
-ms-transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
}
/*********************************************
* SLIDES
*********************************************/
#main {
position: absolute;
width: 900px;
height: 600px;
left: 50%;
top: 50%;
margin-left: -450px;
margin-top: -320px;
padding: 20px 0px;
text-align: center;
-webkit-perspective: 600px;
-moz-perspective: 600px;
-ms-perspective: 600px;
perspective: 600px;
-webkit-perspective-origin: 50% 25%;
-moz-perspective-origin: 50% 25%;
-ms-perspective-origin: 50% 25%;
perspective-origin: 50% 25%;
}
#main>section,
#main>section>section {
display: none;
position: absolute;
width: 100%;
min-height: 600px;
z-index: 10;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
-moz-transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
-ms-transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
-o-transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
}
#main section.present {
display: block;
z-index: 11;
opacity: 1;
}
/*********************************************
* DEFAULT TRANSITION
*********************************************/
#main section.past {
display: block;
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
-moz-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
-ms-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
}
#main section.future {
display: block;
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
-moz-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
-ms-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
}
#main section>section.past {
display: block;
opacity: 0;
-webkit-transform: translate3d(0, -50%, 0) rotateX(70deg) translate3d(0, -50%, 0);
-moz-transform: translate3d(0, -50%, 0) rotateX(70deg) translate3d(0, -50%, 0);
-ms-transform: translate3d(0, -50%, 0) rotateX(70deg) translate3d(0, -50%, 0);
transform: translate3d(0, -50%, 0) rotateX(70deg) translate3d(0, -50%, 0);
}
#main section>section.future {
display: block;
opacity: 0;
-webkit-transform: translate3d(0, 50%, 0) rotateX(-70deg) translate3d(0, 50%, 0);
-moz-transform: translate3d(0, 50%, 0) rotateX(-70deg) translate3d(0, 50%, 0);
-ms-transform: translate3d(0, 50%, 0) rotateX(-70deg) translate3d(0, 50%, 0);
transform: translate3d(0, 50%, 0) rotateX(-70deg) translate3d(0, 50%, 0);
}
/*********************************************
* CONCAVE TRANSITION
*********************************************/
.concave #main>section.past {
-webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0);
-moz-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0);
-ms-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0);
}
.concave #main>section.future {
-webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0);
-moz-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0);
-ms-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0);
}
.concave #main section>section.past {
-webkit-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0);
-moz-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0);
-ms-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0);
transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0);
}
.concave #main section>section.future {
-webkit-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0);
-moz-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0);
-ms-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0);
transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0);
}
/*********************************************
* LINEAR TRANSITION
*********************************************/
.linear #main>section.past {
-webkit-transform: translate(-150%, 0);
-moz-transform: translate(-150%, 0);
-ms-transform: translate(-150%, 0);
-o-transform: translate(-150%, 0);
transform: translate(-150%, 0);
}
.linear #main>section.future {
-webkit-transform: translate(150%, 0);
-moz-transform: translate(150%, 0);
-ms-transform: translate(150%, 0);
-o-transform: translate(150%, 0);
transform: translate(150%, 0);
}
.linear #main section>section.past {
-webkit-transform: translate(0, -150%);
-moz-transform: translate(0, -150%);
-ms-transform: translate(0, -150%);
-o-transform: translate(0, -150%);
transform: translate(0, -150%);
}
.linear #main section>section.future {
-webkit-transform: translate(0, 150%);
-moz-transform: translate(0, 150%);
-ms-transform: translate(0, 150%);
-o-transform: translate(0, 150%);
transform: translate(0, 150%);
}
/*********************************************
* BOX TRANSITION
*********************************************/
.box #main {
margin-top: -350px;
-webkit-perspective-origin: 50% 25%;
-moz-perspective-origin: 50% 25%;
-ms-perspective-origin: 50% 25%;
perspective-origin: 50% 25%;
-webkit-perspective: 1300px;
-moz-perspective: 1300px;
-ms-perspective: 1300px;
perspective: 1300px;
}
.box #main section {
padding: 30px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.box #main section:not(.stack):before {
content: '';
position: absolute;
display: block;
width: 100%;
height: 100%;
left: 0;
top: 0;
background: #292929;
border-radius: 4px;
-webkit-transform: translateZ( -20px );
-moz-transform: translateZ( -20px );
-ms-transform: translateZ( -20px );
-o-transform: translateZ( -20px );
transform: translateZ( -20px );
}
.box #main 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 );
-moz-transform: translateZ(-90px) rotateX( 65deg );
-ms-transform: translateZ(-90px) rotateX( 65deg );
-o-transform: translateZ(-90px) rotateX( 65deg );
transform: translateZ(-90px) rotateX( 65deg );
}
.box #main section.stack {
padding: 0;
background: none;
}
.box #main>section.past {
-webkit-transform-origin: 100% 0%;
-moz-transform-origin: 100% 0%;
-ms-transform-origin: 100% 0%;
transform-origin: 100% 0%;
-webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg);
-moz-transform: translate3d(-100%, 0, 0) rotateY(-90deg);
-ms-transform: translate3d(-100%, 0, 0) rotateY(-90deg);
transform: translate3d(-100%, 0, 0) rotateY(-90deg);
}
.box #main>section.future {
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
-ms-transform-origin: 0% 0%;
transform-origin: 0% 0%;
-webkit-transform: translate3d(100%, 0, 0) rotateY(90deg);
-moz-transform: translate3d(100%, 0, 0) rotateY(90deg);
-ms-transform: translate3d(100%, 0, 0) rotateY(90deg);
transform: translate3d(100%, 0, 0) rotateY(90deg);
}
.box #main section>section.past {
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
-ms-transform-origin: 0% 100%;
transform-origin: 0% 100%;
-webkit-transform: translate3d(0, -100%, 0) rotateX(90deg);
-moz-transform: translate3d(0, -100%, 0) rotateX(90deg);
-ms-transform: translate3d(0, -100%, 0) rotateX(90deg);
transform: translate3d(0, -100%, 0) rotateX(90deg);
}
.box #main section>section.future {
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
-ms-transform-origin: 0% 0%;
transform-origin: 0% 0%;
-webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg);
-moz-transform: translate3d(0, 100%, 0) rotateX(-90deg);
-ms-transform: translate3d(0, 100%, 0) rotateX(-90deg);
transform: translate3d(0, 100%, 0) rotateX(-90deg);
}
/*********************************************
* PAGE TRANSITION
*********************************************/
.page #main {
margin-top: -350px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
-webkit-perspective: 3000px;
-moz-perspective: 3000px;
-ms-perspective: 3000px;
perspective: 3000px;
}
.page #main section {
padding: 30px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.page #main section.past {
z-index: 12;
}
.page #main section:not(.stack):before {
content: '';
position: absolute;
display: block;
width: 100%;
height: 100%;
left: 0;
top: 0;
background: #292929;
-webkit-transform: translateZ( -20px );
-moz-transform: translateZ( -20px );
-ms-transform: translateZ( -20px );
-o-transform: translateZ( -20px );
transform: translateZ( -20px );
}
.page #main 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 );
}
.page #main section.stack {
padding: 0;
background: none;
}
.page #main>section.past {
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
-ms-transform-origin: 0% 0%;
transform-origin: 0% 0%;
-webkit-transform: translate3d(-40%, 0, 0) rotateY(-80deg);
-moz-transform: translate3d(-40%, 0, 0) rotateY(-80deg);
-ms-transform: translate3d(-40%, 0, 0) rotateY(-80deg);
transform: translate3d(-40%, 0, 0) rotateY(-80deg);
}
.page #main>section.future {
-webkit-transform-origin: 100% 0%;
-moz-transform-origin: 100% 0%;
-ms-transform-origin: 100% 0%;
transform-origin: 100% 0%;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.page #main section>section.past {
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
-ms-transform-origin: 0% 0%;
transform-origin: 0% 0%;
-webkit-transform: translate3d(0, -40%, 0) rotateX(80deg);
-moz-transform: translate3d(0, -40%, 0) rotateX(80deg);
-ms-transform: translate3d(0, -40%, 0) rotateX(80deg);
transform: translate3d(0, -40%, 0) rotateX(80deg);
}
.page #main section>section.future {
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
-ms-transform-origin: 0% 100%;
transform-origin: 0% 100%;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
/*********************************************
* NEON THEME
*********************************************/
.neon a,
.neon a:hover,
.neon .controls a.enabled {
color: #5de048;
}
.neon .progress span,
.neon .roll span:after {
background: #5de048;
}
a.image:hover img {
border-color: #5de048;
}
/*********************************************
* OVERVIEW
*********************************************/
.overview #main section {
padding: 20px 0;
opacity: 1;
cursor: pointer;
background: rgba(0,0,0,0.1);
}
.overview #main section:after,
.overview #main section:before {
display: none !important;
}
.overview #main section>section {
opacity: 1;
cursor: pointer;
}
.overview #main section:hover {
background: rgba(0,0,0,0.3);
}
.overview #main section.present {
background: rgba(0,0,0,0.3);
}
.overview #main section.stack {
background: none;
padding: 0;
}

File diff suppressed because one or more lines are too long

641
js/reveal.js Normal file
View File

@@ -0,0 +1,641 @@
/**
* Copyright (C) 2011 Hakim El Hattab, http://hakim.se
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*
* #############################################################################
*
*
* Reveal.js is an easy to use HTML based slideshow enhanced by
* sexy CSS 3D transforms.
*
* Slides are given unique hash based URL's so that they can be
* opened directly.
*
* Public facing methods:
* - Reveal.initialize( { ... options ... } );
* - Reveal.navigateTo( indexh, indexv );
* - Reveal.navigateLeft();
* - Reveal.navigateRight();
* - Reveal.navigateUp();
* - Reveal.navigateDown();
*
*
* version 0.1:
* - First release
*
* version 0.2:
* - Refactored code and added inline documentation
* - Slides now have unique URL's
* - A basic API to invoke navigation was added
*
* version 0.3:
* - Added licensing terms
* - Fixed broken links on touch devices
*
* version 1.0:
* - Added controls
* - Added initialization options
* - Reveal views in fragments
* - Revamped, darker, theme
* - Tweaked markup styles (a, em, strong, b, i, blockquote, q, pre, ul, ol)
* - Support for themes at initialization (default/linear/concave)
* - Code highlighting via highlight.js
*
* version 1.1:
* - Optional progress bar UI element
* - Slide overview available via SPACE
* - Added 'transition' option for specifying transition styles
* - Added 'theme' option for specifying UI styles
* - Slides that contain nested-slides are given the 'stack' class
*
* TODO:
* - Touch/swipe interactions
* - Presentation overview via keyboard shortcut
*
* @author Hakim El Hattab | http://hakim.se
* @version 1.1
*/
var Reveal = (function(){
var HORIZONTAL_SLIDES_SELECTOR = '#main>section',
VERTICAL_SLIDES_SELECTOR = 'section.present>section',
// The horizontal and verical index of the currently active slide
indexh = 0,
indexv = 0,
// Configurations options, including;
// > {Boolean} controls
// > {Boolean} progress
// > {String} theme
// > {String} transition
// > {Boolean} rollingLinks
config = {},
// Cached references to DOM elements
dom = {},
// Detect support for CSS 3D transforms
supports3DTransforms = document.body.style['perspectiveProperty'] !== undefined ||
document.body.style['WebkitPerspective'] !== undefined ||
document.body.style['MozPerspective'] !== undefined ||
document.body.style['msTransform'] !== undefined;
/**
* Starts up the slideshow by applying configuration
* options and binding various events.
*/
function initialize( options ) {
// Cache references to DOM elements
dom.progress = document.querySelector( 'body>.progress' );
dom.progressbar = document.querySelector( 'body>.progress span' );
dom.controls = document.querySelector( '.controls' );
dom.controlsLeft = document.querySelector( '.controls .left' );
dom.controlsRight = document.querySelector( '.controls .right' );
dom.controlsUp = document.querySelector( '.controls .up' );
dom.controlsDown = document.querySelector( '.controls .down' );
// Bind all view events
document.addEventListener('keydown', onDocumentKeyDown, false);
document.addEventListener('touchstart', onDocumentTouchStart, false);
window.addEventListener('hashchange', onWindowHashChange, false);
dom.controlsLeft.addEventListener('click', preventAndForward( navigateLeft ), false);
dom.controlsRight.addEventListener('click', preventAndForward( navigateRight ), false);
dom.controlsUp.addEventListener('click', preventAndForward( navigateUp ), false);
dom.controlsDown.addEventListener('click', preventAndForward( navigateDown ), false);
// Fall back on default options
config.rollingLinks = options.rollingLinks === undefined ? true : options.rollingLinks;
config.controls = options.controls === undefined ? false : options.controls;
config.progress = options.progress === undefined ? false : options.progress;
config.transition = options.transition === undefined ? 'default' : options.transition;
config.theme = options.theme === undefined ? 'default' : options.theme;
// Fall back on the 2D transform theme 'linear'
if( supports3DTransforms === false ) {
config.transition = 'linear';
}
if( config.controls ) {
dom.controls.style.display = 'block';
}
if( config.progress ) {
dom.progress.style.display = 'block';
}
if( config.transition !== 'default' ) {
document.body.classList.add( config.transition );
}
if( config.theme !== 'default' ) {
document.body.classList.add( config.theme );
}
if( config.rollingLinks ) {
// Add some 3D magic to our anchors
linkify();
}
// Read the initial hash
readURL();
}
/**
* Prevents an events defaults behavior calls the
* specified delegate.
*
* @param {Function} delegate The method to call
* after the wrapper has been executed
*/
function preventAndForward( delegate ) {
return function( event ) {
event.preventDefault();
delegate.call();
}
}
/**
* Handler for the document level 'keydown' event.
*
* @param {Object} event
*/
function onDocumentKeyDown( event ) {
// FFT: Use document.querySelector( ':focus' ) === null
// instead of checking contentEditable?
if( event.target.contentEditable === 'inherit' ) {
if( event.keyCode >= 37 && event.keyCode <= 40 ) {
switch( event.keyCode ) {
case 37: navigateLeft(); break; // left
case 39: navigateRight(); break; // right
case 38: navigateUp(); break; // up
case 40: navigateDown(); break; // down
}
slide();
event.preventDefault();
}
// Space bar
else if ( event.keyCode === 32 && supports3DTransforms ) {
if( overviewIsActive() ) {
deactivateOverview();
}
else {
activateOverview();
}
}
}
}
/**
* Handler for the document level 'touchstart' event.
*
* This enables very basic tap interaction for touch
* devices. Added mainly for performance testing of 3D
* transforms on iOS but was so happily surprised with
* how smoothly it runs so I left it in here. Apple +1
*
* @param {Object} event
*/
function onDocumentTouchStart( event ) {
// We're only interested in one point taps
if (event.touches.length === 1) {
// Never prevent taps on anchors and images
if( event.target.tagName.toLowerCase() === 'a' || event.target.tagName.toLowerCase() === 'img' ) {
return;
}
event.preventDefault();
var point = {
x: event.touches[0].clientX,
y: event.touches[0].clientY
};
// Define the extent of the areas that may be tapped
// to navigate
var wt = window.innerWidth * 0.3;
var ht = window.innerHeight * 0.3;
if( point.x < wt ) {
navigateLeft();
}
else if( point.x > window.innerWidth - wt ) {
navigateRight();
}
else if( point.y < ht ) {
navigateUp();
}
else if( point.y > window.innerHeight - ht ) {
navigateDown();
}
slide();
}
}
/**
* Handler for the window level 'hashchange' event.
*
* @param {Object} event
*/
function onWindowHashChange( event ) {
readURL();
}
/**
* Wrap all links in 3D goodness.
*/
function linkify() {
if( supports3DTransforms ) {
var nodes = document.querySelectorAll( 'section a:not(.image)' );
for( var i = 0, len = nodes.length; i < len; i++ ) {
var node = nodes[i];
if( node.textContent && ( !node.className || !node.className.match( /roll/g ) ) ) {
node.className += ' roll';
node.innerHTML = '<span data-title="'+ node.text +'">' + node.innerHTML + '</span>';
}
};
}
}
/**
* Displays the overview of slides (quick nav) by
* scaling down and arranging all slide elements.
*
* Experimental feature, might be dropped if perf
* can't be improved.
*/
function activateOverview() {
document.body.classList.add( 'overview' );
var horizontalSlides = Array.prototype.slice.call( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
for( var i = 0, len1 = horizontalSlides.length; i < len1; i++ ) {
var hslide = horizontalSlides[i],
htransform = 'translateZ(-2500px) translate(' + ( ( i - indexh ) * 105 ) + '%, 0%)';
hslide.setAttribute( 'data-index-h', i );
hslide.style.display = 'block';
hslide.style.WebkitTransform = htransform;
hslide.style.MozTransform = htransform;
hslide.style.msTransform = htransform;
hslide.style.OTransform = htransform;
hslide.style.transform = htransform;
// Navigate to this slide on click
hslide.addEventListener( 'click', onOverviewSlideClicked, true );
var verticalSlides = Array.prototype.slice.call( hslide.querySelectorAll( 'section' ) );
for( var j = 0, len2 = verticalSlides.length; j < len2; j++ ) {
var vslide = verticalSlides[j],
vtransform = 'translate(0%, ' + ( ( j - indexv ) * 105 ) + '%)';
vslide.setAttribute( 'data-index-h', i );
vslide.setAttribute( 'data-index-v', j );
vslide.style.display = 'block';
vslide.style.WebkitTransform = vtransform;
vslide.style.MozTransform = vtransform;
vslide.style.msTransform = vtransform;
vslide.style.OTransform = vtransform;
vslide.style.transform = vtransform;
// Navigate to this slide on click
vslide.addEventListener( 'click', onOverviewSlideClicked, true );
}
}
}
/**
* Exits the slide overview and enters the currently
* active slide.
*/
function deactivateOverview() {
document.body.classList.remove( 'overview' );
var slides = Array.prototype.slice.call( document.querySelectorAll( '#main section' ) );
for( var i = 0, len = slides.length; i < len; i++ ) {
var element = slides[i];
// Resets all transforms to use the external styles
element.style.WebkitTransform = '';
element.style.MozTransform = '';
element.style.msTransform = '';
element.style.OTransform = '';
element.style.transform = '';
element.removeEventListener( 'click', onOverviewSlideClicked );
}
slide();
}
/**
* Checks if the overview is currently active.
*
* @return {Boolean} true if the overview is active,
* false otherwise
*/
function overviewIsActive() {
return document.body.classList.contains( 'overview' );
}
/**
* Invoked when a slide is and we're in the overview.
*/
function onOverviewSlideClicked( event ) {
// TODO There's a bug here where the event listeners are not
// removed after deactivating the overview.
if( overviewIsActive() ) {
event.preventDefault();
deactivateOverview();
indexh = this.getAttribute( 'data-index-h' );
indexv = this.getAttribute( 'data-index-v' );
slide();
}
}
/**
* 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 = Array.prototype.slice.call( document.querySelectorAll( selector ) );
if( slides.length ) {
// Enforce max and minimum index bounds
index = Math.max(Math.min(index, slides.length - 1), 0);
slides[index].setAttribute('class', 'present');
for( var i = 0; i < slides.length; i++ ) {
var slide = slides[i];
// Optimization; hide all slides that are three or more steps
// away from the present slide
if( overviewIsActive() === false ) {
slide.style.display = Math.abs( index - i ) > 3 ? 'none' : 'block';
}
if( i < index ) {
// Any element previous to index is given the 'past' class
slide.setAttribute('class', 'past');
}
else if( i > index ) {
// Any element subsequent to index is given the 'future' class
slide.setAttribute('class', 'future');
}
// If this element contains vertical slides
if( slide.querySelector( 'section' ) ) {
slide.classList.add( 'stack' );
}
}
}
else {
// Since there are no slides we can't be anywhere beyond the
// zeroth index
index = 0;
}
return index;
}
/**
* Updates the visual slides to represent the currently
* set indices.
*/
function slide() {
indexh = updateSlides( HORIZONTAL_SLIDES_SELECTOR, indexh );
indexv = updateSlides( VERTICAL_SLIDES_SELECTOR, indexv );
// Update progress if enabled
if( config.progress ) {
dom.progressbar.style.width = ( indexh / ( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ).length - 1 ) ) * window.innerWidth + 'px';
}
// Close the overview if it's active
if( overviewIsActive() ) {
activateOverview();
}
updateControls();
writeURL();
}
/**
* Updates the state and link pointers of the controls.
*/
function updateControls() {
var routes = availableRoutes();
// Remove the 'enabled' class from all directions
[ dom.controlsLeft, dom.controlsRight, dom.controlsUp, dom.controlsDown ].forEach( function( node ) {
node.classList.remove( 'enabled' );
} )
if( routes.left ) dom.controlsLeft.classList.add( 'enabled' );
if( routes.right ) dom.controlsRight.classList.add( 'enabled' );
if( routes.up ) dom.controlsUp.classList.add( 'enabled' );
if( routes.down ) dom.controlsDown.classList.add( 'enabled' );
}
/**
* Determine what available routes there are for navigation.
*
* @return {Object} containing four booleans: left/right/up/down
*/
function availableRoutes() {
var horizontalSlides = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR );
var verticalSlides = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR );
return {
left: indexh > 0,
right: indexh < horizontalSlides.length - 1,
up: indexv > 0,
down: indexv < verticalSlides.length - 1
};
}
/**
* Reads the current URL (hash) and navigates accordingly.
*/
function readURL() {
// Break the hash down to separate components
var bits = window.location.hash.slice(2).split('/');
// Read the index components of the hash
indexh = bits[0] ? parseInt( bits[0] ) : 0;
indexv = bits[1] ? parseInt( bits[1] ) : 0;
navigateTo( indexh, indexv );
}
/**
* Updates the page URL (hash) to reflect the current
* state.
*/
function writeURL() {
var url = '/';
// Only include the minimum possible number of components in
// the URL
if( indexh > 0 || indexv > 0 ) url += indexh;
if( indexv > 0 ) url += '/' + indexv;
window.location.hash = url;
}
/**
* Navigate to the next slide fragment.
*
* @return {Boolean} true if there was a next fragment,
* false otherwise
*/
function nextFragment() {
// Vertical slides:
if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' );
if( verticalFragments.length ) {
verticalFragments[0].classList.add( 'visible' );
return true;
}
}
// Horizontal slides:
else {
var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' );
if( horizontalFragments.length ) {
horizontalFragments[0].classList.add( 'visible' );
return true;
}
}
return false;
}
/**
* Navigate to the previous slide fragment.
*
* @return {Boolean} true if there was a previous fragment,
* false otherwise
*/
function previousFragment() {
// Vertical slides:
if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment.visible' );
if( verticalFragments.length ) {
verticalFragments[ verticalFragments.length - 1 ].classList.remove( 'visible' );
return true;
}
}
// Horizontal slides:
else {
var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment.visible' );
if( horizontalFragments.length ) {
horizontalFragments[ horizontalFragments.length - 1 ].classList.remove( 'visible' );
return true;
}
}
return false;
}
/**
* Triggers a navigation to the specified indices.
*
* @param {Number} h The horizontal index of the slide to show
* @param {Number} v The vertical index of the slide to show
*/
function navigateTo( h, v ) {
indexh = h === undefined ? indexh : h;
indexv = v === undefined ? indexv : v;
slide();
}
function navigateLeft() {
// Prioritize hiding fragments
if( overviewIsActive() || previousFragment() === false ) {
indexh --;
indexv = 0;
slide();
}
}
function navigateRight() {
// Prioritize revealing fragments
if( overviewIsActive() || nextFragment() === false ) {
indexh ++;
indexv = 0;
slide();
}
}
function navigateUp() {
// Prioritize hiding fragments
if( overviewIsActive() || previousFragment() === false ) {
indexv --;
slide();
}
}
function navigateDown() {
// Prioritize revealing fragments
if( overviewIsActive() || nextFragment() === false ) {
indexv ++;
slide();
}
}
// Expose some methods publicly
return {
initialize: initialize,
navigateTo: navigateTo,
navigateLeft: navigateLeft,
navigateRight: navigateRight,
navigateUp: navigateUp,
navigateDown: navigateDown
};
})();

View File

@@ -1,289 +0,0 @@
/**
* Copyright (C) 2011 Hakim El Hattab, http://hakim.se
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Handles the very minimal navigation logic involved in the
* slideshow. Including keyboard navigation, touch interaction
* and URL history behavior.
*
* Slides are given unique hash based URL's so that they can be
* opened directly. I didn't use the HTML5 History API for this
* as it would have required the addition of server side rewrite
* rules and hence require more effort for anyone to set up.
*
* This component can be called from other scripts via a tiny API:
* - Slideshow.navigateTo( indexh, indexv );
* - Slideshow.navigateLeft();
* - Slideshow.navigateRight();
* - Slideshow.navigateUp();
* - Slideshow.navigateDown();
*
*
* version 0.1:
* - First release
*
* version 0.2:
* - Refactored code and added inline documentation
* - Slides now have unique URL's
* - A basic API to invoke navigation was added
*
* version 0.3:
* - Added licensing terms
*
* version 0.4:
* - Fixed broken links on touch devices.
*
*
* @author Hakim El Hattab
* @version 0.4
*/
var Slideshow = (function(){
var indexh = 0,
indexv = 0;
/**
* Activates the main program logic.
*/
function initialize() {
document.addEventListener('keydown', onDocumentKeyDown, false);
document.addEventListener('touchstart', onDocumentTouchStart, false);
window.addEventListener('hashchange', onWindowHashChange, false);
// Read the initial state of the URL (hash)
readURL();
}
/**
* Handler for the document level 'keydown' event.
*
* @param {Object} event
*/
function onDocumentKeyDown( event ) {
if( event.keyCode >= 37 && event.keyCode <= 40 ) {
switch( event.keyCode ) {
case 37: navigateLeft(); break; // left
case 39: navigateRight(); break; // right
case 38: navigateUp(); break; // up
case 40: navigateDown(); break; // down
}
slide();
event.preventDefault();
}
}
/**
* Handler for the document level 'touchstart' event.
*
* This enables very basic tap interaction for touch
* devices. Added mainly for performance testing of 3D
* transforms on iOS but was so happily surprised with
* how smoothly it runs so I left it in here. Apple +1
*
* @param {Object} event
*/
function onDocumentTouchStart( event ) {
// We're only interested in one point taps
if (event.touches.length === 1) {
// Never prevent taps on anchors and images
if( event.target.tagName.toLowerCase() === 'a' || event.target.tagName.toLowerCase() === 'img' ) {
return;
}
event.preventDefault();
var point = {
x: event.touches[0].clientX,
y: event.touches[0].clientY
};
// Define the extent of the areas that may be tapped
// to navigate
var wt = window.innerWidth * 0.3;
var ht = window.innerHeight * 0.3;
if( point.x < wt ) {
navigateLeft();
}
else if( point.x > window.innerWidth - wt ) {
navigateRight();
}
else if( point.y < ht ) {
navigateUp();
}
else if( point.y > window.innerHeight - ht ) {
navigateDown();
}
slide();
}
}
/**
* Handler for the window level 'hashchange' event.
*
* @param {Object} event
*/
function onWindowHashChange( event ) {
readURL();
}
/**
* 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 = Array.prototype.slice.call( document.querySelectorAll( selector ) );
if( slides.length ) {
// Enforce max and minimum index bounds
index = Math.max(Math.min(index, slides.length - 1), 0);
slides[index].setAttribute('class', 'present');
// Any element previous to index is given the 'past' class
slides.slice(0, index).map(function(element){
element.setAttribute('class', 'past');
});
// Any element subsequent to index is given the 'future' class
slides.slice(index + 1).map(function(element){
element.setAttribute('class', 'future');
});
}
else {
// Since there are no slides we can't be anywhere beyond the
// zeroth index
index = 0;
}
return index;
}
/**
* Updates the visual slides to represent the currently
* set indices.
*/
function slide() {
indexh = updateSlides( '#main>section', indexh );
indexv = updateSlides( 'section.present>section', indexv );
writeURL();
}
/**
* Reads the current URL (hash) and navigates accordingly.
*/
function readURL() {
// Break the hash down to separate components
var bits = window.location.hash.slice(2).split('/');
// Read the index components of the hash
indexh = bits[0] ? parseInt( bits[0] ) : 0;
indexv = bits[1] ? parseInt( bits[1] ) : 0;
navigateTo( indexh, indexv );
}
/**
* Updates the page URL (hash) to reflect the current
* navigational state.
*/
function writeURL() {
var url = '/';
// Only include the minimum possible number of components in
// the URL
if( indexh > 0 || indexv > 0 ) url += indexh
if( indexv > 0 ) url += '/' + indexv
window.location.hash = url;
}
/**
* Triggers a navigation to the specified indices.
*
* @param {Number} h The horizontal index of the slide to show
* @param {Number} v The vertical index of the slide to show
*/
function navigateTo( h, v ) {
indexh = h === undefined ? indexh : h;
indexv = v === undefined ? indexv : v;
slide();
}
function navigateLeft() {
indexh --;
indexv = 0;
slide();
}
function navigateRight() {
indexh ++;
indexv = 0;
slide();
}
function navigateUp() {
indexv --;
slide();
}
function navigateDown() {
indexv ++;
slide();
}
// Initialize the program. Done right before returning to ensure
// that any inline variable definitions are available to all
// functions
initialize();
// Expose some methods publicly
return {
navigateTo: navigateTo,
navigateLeft: navigateLeft,
navigateRight: navigateRight,
navigateUp: navigateUp,
navigateDown: navigateDown
};
})();

5
lib/highlight.js Normal file

File diff suppressed because one or more lines are too long

115
lib/zenburn.css Normal file
View File

@@ -0,0 +1,115 @@
/*
Zenburn style from voldmar.ru (c) Vladimir Epifanov <voldmar@voldmar.ru>
based on dark.css by Ivan Sagalaev
*/
pre code {
display: block; padding: 0.5em;
background: #3F3F3F;
color: #DCDCDC;
}
pre .keyword,
pre .tag,
pre .django .tag,
pre .django .keyword,
pre .css .class,
pre .css .id,
pre .lisp .title {
color: #E3CEAB;
}
pre .django .template_tag,
pre .django .variable,
pre .django .filter .argument {
color: #DCDCDC;
}
pre .number,
pre .date {
color: #8CD0D3;
}
pre .dos .envvar,
pre .dos .stream,
pre .variable,
pre .apache .sqbracket {
color: #EFDCBC;
}
pre .dos .flow,
pre .diff .change,
pre .python .exception,
pre .python .built_in,
pre .literal,
pre .tex .special {
color: #EFEFAF;
}
pre .diff .chunk,
pre .ruby .subst {
color: #8F8F8F;
}
pre .dos .keyword,
pre .python .decorator,
pre .class .title,
pre .haskell .label,
pre .function .title,
pre .ini .title,
pre .diff .header,
pre .ruby .class .parent,
pre .apache .tag,
pre .nginx .built_in,
pre .tex .command,
pre .input_number {
color: #efef8f;
}
pre .dos .winutils,
pre .ruby .symbol,
pre .ruby .symbol .string,
pre .ruby .symbol .keyword,
pre .ruby .symbol .keymethods,
pre .ruby .string,
pre .ruby .instancevar {
color: #DCA3A3;
}
pre .diff .deletion,
pre .string,
pre .tag .value,
pre .preprocessor,
pre .built_in,
pre .sql .aggregate,
pre .javadoc,
pre .smalltalk .class,
pre .smalltalk .localvars,
pre .smalltalk .array,
pre .css .rules .value,
pre .attr_selector,
pre .pseudo,
pre .apache .cbracket,
pre .tex .formula {
color: #CC9393;
}
pre .shebang,
pre .diff .addition,
pre .comment,
pre .java .annotation,
pre .template_comment,
pre .pi,
pre .doctype {
color: #7F9F7F;
}
pre .xml .css,
pre .xml .javascript,
pre .xml .vbscript,
pre .tex .formula {
opacity: 0.5;
}