1
0
mirror of https://github.com/hakimel/reveal.js.git synced 2025-09-15 17:12:10 +02:00

Compare commits

...

10 Commits
0.3.0 ... 1.0.0

Author SHA1 Message Date
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 1045 additions and 368 deletions

View File

@@ -1,8 +1,33 @@
# 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://lab.hakim.se/reveal-js/).
# History
### 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
Curious about how this looks in action? [Check out the demo page.](http://hakim.se/experiments/css/slideshow/).
# License

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -1,4 +1,6 @@
/**
* Main styles of reveal.js
*
* @author Hakim El Hattab
*/
@@ -20,33 +22,31 @@
*********************************************/
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;
background: #111;
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;
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%);
}
@@ -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,8 +76,21 @@ 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);
}
@@ -88,18 +99,24 @@ h4.inverted {
*********************************************/
#main {
position: absolute;
width: 800px;
width: 900px;
height: 600px;
left: 50%;
top: 50%;
margin-left: -400px;
margin-left: -450px;
margin-top: -320px;
padding: 20px 0px;
text-align: center;
-webkit-perspective: 600px;
-moz-perspective: 600px;
perspective: 600px;
-webkit-perspective-origin: 50% 25%;
-moz-perspective-origin: 50% 25%;
perspective-origin: 50% 25%;
}
#main>section,
@@ -111,6 +128,8 @@ h4.inverted {
min-height: 600px;
-webkit-transform-style: preserve-3d;
-moz-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);
@@ -118,56 +137,148 @@ h4.inverted {
transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
}
#main section.present {
display: block;
position: absolute;
z-index: 10;
}
/*********************************************
* DEFAULT THEME
*********************************************/
#main section.past {
display: block;
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0)
rotateY(-90deg)
translate3d(-100%, 0, 0);
}
#main section.present {
display: block;
position: relative;
z-index: 10;
-webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
-moz-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);
-webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
-moz-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);
-webkit-transform: translate3d(0, -50%, 0) rotateX(70deg) translate3d(0, -50%, 0);
-moz-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);
-webkit-transform: translate3d(0, 50%, 0) rotateX(-70deg) translate3d(0, 50%, 0);
-moz-transform: translate3d(0, 50%, 0) rotateX(-70deg) translate3d(0, 50%, 0);
transform: translate3d(0, 50%, 0) rotateX(-70deg) translate3d(0, 50%, 0);
}
/*********************************************
* CONCAVE THEME
*********************************************/
.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);
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);
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);
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);
transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0);
}
/*********************************************
* LINEAR THEME
*********************************************/
.linear #main>section.past {
-webkit-transform: translate3d(-100%, 0, 0);
-moz-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
.linear #main>section.future {
-webkit-transform: translate3d(100%, 0, 0);
-moz-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
.linear #main section>section.past {
-webkit-transform: translate3d(0, -100%, 0);
-moz-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
.linear #main section>section.future {
-webkit-transform: translate3d(0, 100%, 0);
-moz-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
/*********************************************
* VIEW FRAGMENTS
*********************************************/
#main section .fragment {
opacity: 0;
-webkit-transition: all .2s ease;
-moz-transition: all .2s ease;
-o-transition: all .2s ease;
transition: all .2s ease;
}
#main section .fragment.visible {
opacity: 1;
}
/*********************************************
* DEFAULT ELEMENT STYLES
*********************************************/
#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 +286,227 @@ 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%;
}
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;
-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;
-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;
}
/*********************************************
* ROLLING LINKS
*********************************************/
.roll {
display: inline-block;
overflow: hidden;
vertical-align: top;
-webkit-perspective: 400px;
-moz-perspective: 400px;
perspective: 400px;
-webkit-perspective-origin: 50% 50%;
-moz-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;
transition: all 400ms ease;
-webkit-transform-origin: 50% 0%;
-moz-transform-origin: 50% 0%;
transform-origin: 50% 0%;
-webkit-transform-style: preserve-3d;
-moz-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 );
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%;
transform-origin: 50% 0%;
-webkit-transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
-moz-transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
}

File diff suppressed because one or more lines are too long

460
js/reveal.js Normal file
View File

@@ -0,0 +1,460 @@
/**
* 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
*
* TODO:
* - Touch/swipe interactions
* - Presentation overview via keyboard shortcut
*
* @author Hakim El Hattab | http://hakim.se
* @version 1.0
*/
var Reveal = (function(){
var HORIZONTAL_SLIDES_SELECTOR = '#main>section',
VERTICAL_SLIDES_SELECTOR = 'section.present>section',
indexh = 0,
indexv = 0,
config = {},
dom = {};
/**
* Activates the main program logic.
*/
function initialize( options ) {
// Gather references to DOM elements
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' );
// Add event listeners
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);
// Default options
config.rollingLinks = options.rollingLinks === undefined ? true : options.rollingLinks;
config.controls = options.controls === undefined ? false : options.controls;
config.theme = options.theme === undefined ? 'default' : options.theme;
if( config.controls ) {
dom.controls.style.display = 'block';
}
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.
*/
function preventAndForward( delegate ) {
return function( event ) {
event.preventDefault();
delegate.call();
}
}
/**
* Handler for the document level 'keydown' event.
*
* @param {Object} event
*/
function onDocumentKeyDown( event ) {
if( event.keyCode >= 37 && event.keyCode <= 40 && event.target.contentEditable === 'inherit' ) {
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();
}
/**
* Wrap all links in 3D goodness.
*/
function linkify() {
var supports3DTransforms = document.body.style['webkitPerspective'] !== undefined ||
document.body.style['MozPerspective'] !== undefined ||
document.body.style['perspective'] !== undefined;
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.className || !node.className.match( /roll/g ) ) {
node.className += ' roll';
node.innerHTML = '<span data-title="'+ node.text +'">' + node.innerHTML + '</span>';
}
};
}
}
/**
* 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( HORIZONTAL_SLIDES_SELECTOR, indexh );
indexv = updateSlides( VERTICAL_SLIDES_SELECTOR, indexv );
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
* 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;
}
/**
* Navigate to the nexy slide fragment.
*
* @return {Boolean} true if there was a next fragment,
* false otherwise
*/
function nextFragment() {
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;
}
}
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() {
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;
}
}
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( previousFragment() === false ) {
indexh --;
indexv = 0;
slide();
}
}
function navigateRight() {
// Prioritize revealing fragments
if( nextFragment() === false ) {
indexh ++;
indexv = 0;
slide();
}
}
function navigateUp() {
// Prioritize hiding fragments
if( previousFragment() === false ) {
indexv --;
slide();
}
}
function navigateDown() {
// Prioritize revealing fragments
if( 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;
}