Merge remote-tracking branch 'upstream/master' into solarized
This commit is contained in:
commit
49ada91eb1
@ -1,3 +1,5 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- 0.8
|
- 0.8
|
||||||
|
before_script:
|
||||||
|
- npm install -g grunt-cli
|
@ -3,19 +3,11 @@ module.exports = function(grunt) {
|
|||||||
|
|
||||||
// Project configuration
|
// Project configuration
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
pkg: '<json:package.json>',
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
|
|
||||||
inputJS: 'js/reveal.js',
|
|
||||||
inputCSS: 'css/reveal.css',
|
|
||||||
|
|
||||||
outputJS: 'js/reveal.min.js',
|
|
||||||
outputCSS: 'css/reveal.min.css',
|
|
||||||
|
|
||||||
meta: {
|
meta: {
|
||||||
version: '2.3',
|
|
||||||
banner:
|
banner:
|
||||||
'/*!\n' +
|
'/*!\n' +
|
||||||
' * reveal.js <%= meta.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
|
' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
|
||||||
' * http://lab.hakim.se/reveal-js\n' +
|
' * http://lab.hakim.se/reveal-js\n' +
|
||||||
' * MIT licensed\n' +
|
' * MIT licensed\n' +
|
||||||
' *\n' +
|
' *\n' +
|
||||||
@ -23,8 +15,8 @@ module.exports = function(grunt) {
|
|||||||
' */'
|
' */'
|
||||||
},
|
},
|
||||||
|
|
||||||
lint: {
|
jshint: {
|
||||||
files: [ 'grunt.js', '<%= inputJS %>' ]
|
files: [ 'Gruntfile.js', 'js/reveal.js' ]
|
||||||
},
|
},
|
||||||
|
|
||||||
// Tests will be added soon
|
// Tests will be added soon
|
||||||
@ -32,17 +24,20 @@ module.exports = function(grunt) {
|
|||||||
files: [ 'test/**/*.html' ]
|
files: [ 'test/**/*.html' ]
|
||||||
},
|
},
|
||||||
|
|
||||||
min: {
|
uglify: {
|
||||||
dist: {
|
options: {
|
||||||
src: [ '<banner:meta.banner>', '<%= inputJS %>' ],
|
banner: '<%= meta.banner %>\n'
|
||||||
dest: '<%= outputJS %>'
|
},
|
||||||
|
build: {
|
||||||
|
src: 'js/reveal.js',
|
||||||
|
dest: 'js/reveal.min.js'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mincss: {
|
cssmin: {
|
||||||
compress: {
|
compress: {
|
||||||
files: {
|
files: {
|
||||||
'<%= outputCSS %>': [ '<%= inputCSS %>' ]
|
'css/reveal.min.css': [ 'css/reveal.css' ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -69,16 +64,19 @@ module.exports = function(grunt) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
files: [ 'grunt.js', '<%= inputJS %>', '<%= inputCSS %>' ],
|
files: [ 'Gruntfile.js', 'js/reveal.js', 'css/reveal.css' ],
|
||||||
tasks: 'default'
|
tasks: 'default'
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-mincss' );
|
grunt.loadNpmTasks( 'grunt-contrib-jshint' );
|
||||||
|
grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
|
||||||
|
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
|
||||||
|
grunt.loadNpmTasks( 'grunt-contrib-watch' );
|
||||||
|
|
||||||
// Default task
|
// Default task
|
||||||
grunt.registerTask( 'default', [ 'lint', 'mincss', 'min' ] );
|
grunt.registerTask( 'default', [ 'jshint', 'cssmin', 'uglify' ] );
|
||||||
|
|
||||||
};
|
};
|
20
README.md
20
README.md
@ -37,7 +37,7 @@ Markup heirarchy needs to be ``<div class="reveal"> <div class="slides"> <sectio
|
|||||||
|
|
||||||
It's possible to write your slides using Markdown. To enable Markdown, add the ```data-markdown``` attribute to your ```<section>``` elements and wrap the contents in a ```<script type="text/template">``` like the example below.
|
It's possible to write your slides using Markdown. To enable Markdown, add the ```data-markdown``` attribute to your ```<section>``` elements and wrap the contents in a ```<script type="text/template">``` like the example below.
|
||||||
|
|
||||||
This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Irish](https://github.com/paulirish) which in turn uses [showdown](https://github.com/coreyti/showdown/). This is sensitive to indentation (avoid mixing tabs and spaces) and line breaks (avoid consecutive breaks).
|
This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Irish](https://github.com/paulirish) which in turn uses [showdown](https://github.com/coreyti/showdown/). Sensitive to indentation (avoid mixing tabs and spaces) and line breaks (avoid consecutive breaks).
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<section data-markdown>
|
<section data-markdown>
|
||||||
@ -49,6 +49,14 @@ This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Iri
|
|||||||
</section>
|
</section>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### External Markdown
|
||||||
|
|
||||||
|
You can write your content as a separate file and have reveal.js load it at runtime. Note the separator arguments which determine how slides are delimited in the external file.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n"></section>
|
||||||
|
```
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
At the end of your page you need to initialize reveal by running the following code. Note that all config values are optional and will default as specified below.
|
At the end of your page you need to initialize reveal by running the following code. Note that all config values are optional and will default as specified below.
|
||||||
@ -270,6 +278,16 @@ Multiple fragments can be applied to the same element sequentially by wrapping i
|
|||||||
</section>
|
</section>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The display order of fragments can be controlled using the ```data-fragment-index``` attribute.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<section>
|
||||||
|
<p class="fragment" data-fragment-index="3">Appears last</p>
|
||||||
|
<p class="fragment" data-fragment-index="1">Appears first</p>
|
||||||
|
<p class="fragment" data-fragment-index="2">Appears second</p>
|
||||||
|
</section>
|
||||||
|
```
|
||||||
|
|
||||||
### Fragment events
|
### Fragment events
|
||||||
|
|
||||||
When a slide fragment is either shown or hidden reveal.js will dispatch an event.
|
When a slide fragment is either shown or hidden reveal.js will dispatch an event.
|
||||||
|
2
css/reveal.min.css
vendored
2
css/reveal.min.css
vendored
File diff suppressed because one or more lines are too long
170
js/reveal.js
170
js/reveal.js
@ -129,6 +129,9 @@ var Reveal = (function(){
|
|||||||
// A delay used to deactivate the overview mode
|
// A delay used to deactivate the overview mode
|
||||||
deactivateOverviewTimeout = 0,
|
deactivateOverviewTimeout = 0,
|
||||||
|
|
||||||
|
// Flags if the interaction event listeners are bound
|
||||||
|
eventsAreBound = false,
|
||||||
|
|
||||||
// Holds information about the currently ongoing touch input
|
// Holds information about the currently ongoing touch input
|
||||||
touch = {
|
touch = {
|
||||||
startX: 0,
|
startX: 0,
|
||||||
@ -310,10 +313,6 @@ var Reveal = (function(){
|
|||||||
// Updates the presentation to match the current configuration values
|
// Updates the presentation to match the current configuration values
|
||||||
configure();
|
configure();
|
||||||
|
|
||||||
// Force an initial layout, will thereafter be invoked as the window
|
|
||||||
// is resized
|
|
||||||
layout();
|
|
||||||
|
|
||||||
// Read the initial hash
|
// Read the initial hash
|
||||||
readURL();
|
readURL();
|
||||||
|
|
||||||
@ -335,40 +334,51 @@ var Reveal = (function(){
|
|||||||
/**
|
/**
|
||||||
* Applies the configuration settings from the config object.
|
* Applies the configuration settings from the config object.
|
||||||
*/
|
*/
|
||||||
function configure() {
|
function configure( options ) {
|
||||||
|
|
||||||
if( supports3DTransforms === false ) {
|
dom.wrapper.classList.remove( config.transition );
|
||||||
config.transition = 'linear';
|
|
||||||
}
|
|
||||||
|
|
||||||
if( config.controls && dom.controls ) {
|
// New config options may be passed when this method
|
||||||
dom.controls.style.display = 'block';
|
// is invoked through the API after initialization
|
||||||
}
|
if( typeof options === 'object' ) extend( config, options );
|
||||||
|
|
||||||
if( config.progress && dom.progress ) {
|
// Force linear transition based on browser capabilities
|
||||||
dom.progress.style.display = 'block';
|
if( supports3DTransforms === false ) config.transition = 'linear';
|
||||||
}
|
|
||||||
|
|
||||||
if( config.transition !== 'default' ) {
|
|
||||||
dom.wrapper.classList.add( config.transition );
|
dom.wrapper.classList.add( config.transition );
|
||||||
}
|
|
||||||
|
dom.controls.style.display = ( config.controls && dom.controls ) ? 'block' : 'none';
|
||||||
|
dom.progress.style.display = ( config.progress && dom.progress ) ? 'block' : 'none';
|
||||||
|
|
||||||
if( config.rtl ) {
|
if( config.rtl ) {
|
||||||
dom.wrapper.classList.add( 'rtl' );
|
dom.wrapper.classList.add( 'rtl' );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
dom.wrapper.classList.remove( 'rtl' );
|
||||||
|
}
|
||||||
|
|
||||||
if( config.center ) {
|
if( config.center ) {
|
||||||
dom.wrapper.classList.add( 'center' );
|
dom.wrapper.classList.add( 'center' );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
dom.wrapper.classList.remove( 'center' );
|
||||||
|
}
|
||||||
|
|
||||||
if( config.mouseWheel ) {
|
if( config.mouseWheel ) {
|
||||||
document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
|
document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
|
||||||
document.addEventListener( 'mousewheel', onDocumentMouseScroll, false );
|
document.addEventListener( 'mousewheel', onDocumentMouseScroll, false );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
document.removeEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
|
||||||
|
document.removeEventListener( 'mousewheel', onDocumentMouseScroll, false );
|
||||||
|
}
|
||||||
|
|
||||||
// 3D links
|
// 3D links
|
||||||
if( config.rollingLinks ) {
|
if( config.rollingLinks ) {
|
||||||
linkify();
|
enable3DLinks();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
disable3DLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the theme in the config, if it's not already loaded
|
// Load the theme in the config, if it's not already loaded
|
||||||
@ -383,6 +393,9 @@ var Reveal = (function(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force a layout to make sure the current config is accounted for
|
||||||
|
layout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -390,6 +403,8 @@ var Reveal = (function(){
|
|||||||
*/
|
*/
|
||||||
function addEventListeners() {
|
function addEventListeners() {
|
||||||
|
|
||||||
|
eventsAreBound = true;
|
||||||
|
|
||||||
window.addEventListener( 'hashchange', onWindowHashChange, false );
|
window.addEventListener( 'hashchange', onWindowHashChange, false );
|
||||||
window.addEventListener( 'resize', onWindowResize, false );
|
window.addEventListener( 'resize', onWindowResize, false );
|
||||||
|
|
||||||
@ -424,6 +439,8 @@ var Reveal = (function(){
|
|||||||
*/
|
*/
|
||||||
function removeEventListeners() {
|
function removeEventListeners() {
|
||||||
|
|
||||||
|
eventsAreBound = false;
|
||||||
|
|
||||||
document.removeEventListener( 'keydown', onDocumentKeyDown, false );
|
document.removeEventListener( 'keydown', onDocumentKeyDown, false );
|
||||||
window.removeEventListener( 'hashchange', onWindowHashChange, false );
|
window.removeEventListener( 'hashchange', onWindowHashChange, false );
|
||||||
window.removeEventListener( 'resize', onWindowResize, false );
|
window.removeEventListener( 'resize', onWindowResize, false );
|
||||||
@ -524,28 +541,79 @@ var Reveal = (function(){
|
|||||||
/**
|
/**
|
||||||
* Wrap all links in 3D goodness.
|
* Wrap all links in 3D goodness.
|
||||||
*/
|
*/
|
||||||
function linkify() {
|
function enable3DLinks() {
|
||||||
|
|
||||||
if( supports3DTransforms && !( 'msPerspective' in document.body.style ) ) {
|
if( supports3DTransforms && !( 'msPerspective' in document.body.style ) ) {
|
||||||
var nodes = document.querySelectorAll( SLIDES_SELECTOR + ' a:not(.image)' );
|
var anchors = document.querySelectorAll( SLIDES_SELECTOR + ' a:not(.image)' );
|
||||||
|
|
||||||
for( var i = 0, len = nodes.length; i < len; i++ ) {
|
for( var i = 0, len = anchors.length; i < len; i++ ) {
|
||||||
var node = nodes[i];
|
var anchor = anchors[i];
|
||||||
|
|
||||||
if( node.textContent && !node.querySelector( '*' ) && ( !node.className || !node.classList.contains( node, 'roll' ) ) ) {
|
if( anchor.textContent && !anchor.querySelector( '*' ) && ( !anchor.className || !anchor.classList.contains( anchor, 'roll' ) ) ) {
|
||||||
var span = document.createElement('span');
|
var span = document.createElement('span');
|
||||||
span.setAttribute('data-title', node.text);
|
span.setAttribute('data-title', anchor.text);
|
||||||
span.innerHTML = node.innerHTML;
|
span.innerHTML = anchor.innerHTML;
|
||||||
|
|
||||||
node.classList.add( 'roll' );
|
anchor.classList.add( 'roll' );
|
||||||
node.innerHTML = '';
|
anchor.innerHTML = '';
|
||||||
node.appendChild(span);
|
anchor.appendChild(span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unwrap all 3D links.
|
||||||
|
*/
|
||||||
|
function disable3DLinks() {
|
||||||
|
|
||||||
|
var anchors = document.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
function sortFragments( fragments ) {
|
||||||
|
|
||||||
|
var a = toArray( fragments );
|
||||||
|
|
||||||
|
a.forEach( function( el, idx ) {
|
||||||
|
if( !el.hasAttribute( 'data-fragment-index' ) ) {
|
||||||
|
el.setAttribute( 'data-fragment-index', idx );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
a.sort( function( l, r ) {
|
||||||
|
return l.getAttribute( 'data-fragment-index' ) - r.getAttribute( 'data-fragment-index');
|
||||||
|
} );
|
||||||
|
|
||||||
|
return a
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies JavaScript-controlled layout rules to the
|
* Applies JavaScript-controlled layout rules to the
|
||||||
* presentation.
|
* presentation.
|
||||||
@ -602,14 +670,9 @@ var Reveal = (function(){
|
|||||||
dom.slides.style.transform = transform;
|
dom.slides.style.transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( config.center ) {
|
|
||||||
|
|
||||||
// Select all slides, vertical and horizontal
|
// Select all slides, vertical and horizontal
|
||||||
var slides = toArray( document.querySelectorAll( SLIDES_SELECTOR ) );
|
var slides = toArray( document.querySelectorAll( SLIDES_SELECTOR ) );
|
||||||
|
|
||||||
// Determine the minimum top offset for slides
|
|
||||||
var minTop = -slideHeight / 2;
|
|
||||||
|
|
||||||
for( var i = 0, len = slides.length; i < len; i++ ) {
|
for( var i = 0, len = slides.length; i < len; i++ ) {
|
||||||
var slide = slides[ i ];
|
var slide = slides[ i ];
|
||||||
|
|
||||||
@ -618,15 +681,19 @@ var Reveal = (function(){
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( config.center ) {
|
||||||
// Vertical stacks are not centered since their section
|
// Vertical stacks are not centered since their section
|
||||||
// children will be
|
// children will be
|
||||||
if( slide.classList.contains( 'stack' ) ) {
|
if( slide.classList.contains( 'stack' ) ) {
|
||||||
slide.style.top = 0;
|
slide.style.top = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
slide.style.top = Math.max( - ( slide.offsetHeight / 2 ) - 20, minTop ) + 'px';
|
slide.style.top = Math.max( - ( slide.offsetHeight / 2 ) - 20, -slideHeight / 2 ) + 'px';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
slide.style.top = '';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -871,9 +938,15 @@ var Reveal = (function(){
|
|||||||
*/
|
*/
|
||||||
function pause() {
|
function pause() {
|
||||||
|
|
||||||
|
var wasPaused = dom.wrapper.classList.contains( 'paused' );
|
||||||
|
|
||||||
cancelAutoSlide();
|
cancelAutoSlide();
|
||||||
dom.wrapper.classList.add( 'paused' );
|
dom.wrapper.classList.add( 'paused' );
|
||||||
|
|
||||||
|
if( wasPaused === false ) {
|
||||||
|
dispatchEvent( 'paused' );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -881,9 +954,15 @@ var Reveal = (function(){
|
|||||||
*/
|
*/
|
||||||
function resume() {
|
function resume() {
|
||||||
|
|
||||||
|
var wasPaused = dom.wrapper.classList.contains( 'paused' );
|
||||||
|
|
||||||
cueAutoSlide();
|
cueAutoSlide();
|
||||||
dom.wrapper.classList.remove( 'paused' );
|
dom.wrapper.classList.remove( 'paused' );
|
||||||
|
|
||||||
|
if( wasPaused ) {
|
||||||
|
dispatchEvent( 'resumed' );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -996,7 +1075,7 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
// Show fragment, if specified
|
// Show fragment, if specified
|
||||||
if( typeof f !== 'undefined' ) {
|
if( typeof f !== 'undefined' ) {
|
||||||
var fragments = currentSlide.querySelectorAll( '.fragment' );
|
var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment' ) );
|
||||||
|
|
||||||
toArray( fragments ).forEach( function( fragment, indexf ) {
|
toArray( fragments ).forEach( function( fragment, indexf ) {
|
||||||
if( indexf < f ) {
|
if( indexf < f ) {
|
||||||
@ -1367,7 +1446,8 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
// Vertical slides:
|
// Vertical slides:
|
||||||
if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
|
if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
|
||||||
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' );
|
var verticalFragments = sortFragments( document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' ) );
|
||||||
|
|
||||||
if( verticalFragments.length ) {
|
if( verticalFragments.length ) {
|
||||||
verticalFragments[0].classList.add( 'visible' );
|
verticalFragments[0].classList.add( 'visible' );
|
||||||
|
|
||||||
@ -1378,7 +1458,8 @@ var Reveal = (function(){
|
|||||||
}
|
}
|
||||||
// Horizontal slides:
|
// Horizontal slides:
|
||||||
else {
|
else {
|
||||||
var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' );
|
var horizontalFragments = sortFragments( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' ) );
|
||||||
|
|
||||||
if( horizontalFragments.length ) {
|
if( horizontalFragments.length ) {
|
||||||
horizontalFragments[0].classList.add( 'visible' );
|
horizontalFragments[0].classList.add( 'visible' );
|
||||||
|
|
||||||
@ -1402,7 +1483,8 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
// Vertical slides:
|
// Vertical slides:
|
||||||
if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
|
if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
|
||||||
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment.visible' );
|
var verticalFragments = sortFragments( document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment.visible' ) );
|
||||||
|
|
||||||
if( verticalFragments.length ) {
|
if( verticalFragments.length ) {
|
||||||
verticalFragments[ verticalFragments.length - 1 ].classList.remove( 'visible' );
|
verticalFragments[ verticalFragments.length - 1 ].classList.remove( 'visible' );
|
||||||
|
|
||||||
@ -1413,7 +1495,8 @@ var Reveal = (function(){
|
|||||||
}
|
}
|
||||||
// Horizontal slides:
|
// Horizontal slides:
|
||||||
else {
|
else {
|
||||||
var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment.visible' );
|
var horizontalFragments = sortFragments( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment.visible' ) );
|
||||||
|
|
||||||
if( horizontalFragments.length ) {
|
if( horizontalFragments.length ) {
|
||||||
horizontalFragments[ horizontalFragments.length - 1 ].classList.remove( 'visible' );
|
horizontalFragments[ horizontalFragments.length - 1 ].classList.remove( 'visible' );
|
||||||
|
|
||||||
@ -1783,23 +1866,27 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
// TODO There's a bug here where the event listeners are not
|
// TODO There's a bug here where the event listeners are not
|
||||||
// removed after deactivating the overview.
|
// removed after deactivating the overview.
|
||||||
if( isOverview() ) {
|
if( eventsAreBound && isOverview() ) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
deactivateOverview();
|
|
||||||
|
|
||||||
var element = event.target;
|
var element = event.target;
|
||||||
|
|
||||||
while( element && !element.nodeName.match( /section/gi ) ) {
|
while( element && !element.nodeName.match( /section/gi ) ) {
|
||||||
element = element.parentNode;
|
element = element.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( element && !element.classList.contains( 'disabled' ) ) {
|
||||||
|
|
||||||
|
deactivateOverview();
|
||||||
|
|
||||||
if( element.nodeName.match( /section/gi ) ) {
|
if( element.nodeName.match( /section/gi ) ) {
|
||||||
var h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),
|
var h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),
|
||||||
v = parseInt( element.getAttribute( 'data-index-v' ), 10 );
|
v = parseInt( element.getAttribute( 'data-index-v' ), 10 );
|
||||||
|
|
||||||
slide( h, v );
|
slide( h, v );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1812,6 +1899,7 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
initialize: initialize,
|
initialize: initialize,
|
||||||
|
configure: configure,
|
||||||
|
|
||||||
// Navigation methods
|
// Navigation methods
|
||||||
slide: slide,
|
slide: slide,
|
||||||
|
4
js/reveal.min.js
vendored
4
js/reveal.min.js
vendored
File diff suppressed because one or more lines are too long
17
package.json
17
package.json
@ -16,16 +16,19 @@
|
|||||||
"node": "~0.8.0"
|
"node": "~0.8.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "grunt lint qunit"
|
"test": "grunt jshint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"underscore" : "~1.3.3",
|
"underscore": "~1.3.3",
|
||||||
"express" : "~2.5.9",
|
"express": "~2.5.9",
|
||||||
"socket.io" : "~0.9.6",
|
"socket.io": "~0.9.6",
|
||||||
"mustache" : "~0.4.0"
|
"mustache": "~0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"grunt-contrib-mincss": "~0.3.1",
|
"grunt-contrib-jshint": "~0.2.0",
|
||||||
"grunt": "~0.3.17"
|
"grunt-contrib-cssmin": "~0.4.1",
|
||||||
|
"grunt-contrib-uglify": "~0.1.1",
|
||||||
|
"grunt-contrib-watch": "~0.2.0",
|
||||||
|
"grunt": "~0.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
97
plugin/markdown/example.html
Normal file
97
plugin/markdown/example.html
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title>reveal.js - Markdown Demo</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../../css/reveal.css">
|
||||||
|
<link rel="stylesheet" href="../../css/theme/default.css" id="theme">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="reveal">
|
||||||
|
|
||||||
|
<div class="slides">
|
||||||
|
|
||||||
|
<!-- Use external markdown resource, and separate slides by three newlines; vertical slides by two newlines -->
|
||||||
|
<section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n"></section>
|
||||||
|
|
||||||
|
<!-- Slides are separated by three dashes (quick 'n dirty regular expression) -->
|
||||||
|
<section data-markdown data-separator="---">
|
||||||
|
<script type="text/template">
|
||||||
|
## Demo 1
|
||||||
|
Slide 1
|
||||||
|
---
|
||||||
|
## Demo 1
|
||||||
|
Slide 2
|
||||||
|
---
|
||||||
|
## Demo 1
|
||||||
|
Slide 3
|
||||||
|
</script>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Slides are separated by newline + three dashes + newline, vertical slides identical but two dashes -->
|
||||||
|
<section data-markdown data-separator="^\n---\n$" data-vertical="^\n--\n$">
|
||||||
|
<script type="text/template">
|
||||||
|
## Demo 2
|
||||||
|
Slide 1.1
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
## Demo 2
|
||||||
|
Slide 1.2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Demo 2
|
||||||
|
Slide 2
|
||||||
|
</script>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- No "extra" slides, since there are no separators defined (so they'll become horizontal rulers) -->
|
||||||
|
<section data-markdown>
|
||||||
|
<script type="text/template">
|
||||||
|
A
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
B
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
C
|
||||||
|
</script>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="../../lib/js/head.min.js"></script>
|
||||||
|
<script src="../../js/reveal.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
Reveal.initialize({
|
||||||
|
controls: true,
|
||||||
|
progress: true,
|
||||||
|
history: true,
|
||||||
|
center: true,
|
||||||
|
|
||||||
|
theme: Reveal.getQueryHash().theme,
|
||||||
|
transition: Reveal.getQueryHash().transition || 'default',
|
||||||
|
|
||||||
|
// Optional libraries used to extend on reveal.js
|
||||||
|
dependencies: [
|
||||||
|
{ src: '../../lib/js/classList.js', condition: function() { return !document.body.classList; } },
|
||||||
|
{ src: 'showdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
||||||
|
{ src: 'markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
29
plugin/markdown/example.md
Normal file
29
plugin/markdown/example.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Markdown Demo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## External 1.1
|
||||||
|
|
||||||
|
Content 1.1
|
||||||
|
|
||||||
|
|
||||||
|
## External 1.2
|
||||||
|
|
||||||
|
Content 1.2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## External 2
|
||||||
|
|
||||||
|
Content 2.1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## External 3.1
|
||||||
|
|
||||||
|
Content 3.1
|
||||||
|
|
||||||
|
|
||||||
|
## External 3.2
|
||||||
|
|
||||||
|
Content 3.2
|
@ -6,16 +6,12 @@
|
|||||||
throw 'The reveal.js Markdown plugin requires Showdown to be loaded';
|
throw 'The reveal.js Markdown plugin requires Showdown to be loaded';
|
||||||
}
|
}
|
||||||
|
|
||||||
var sections = document.querySelectorAll( '[data-markdown]' );
|
var stripLeadingWhitespace = function(section) {
|
||||||
|
|
||||||
for( var i = 0, len = sections.length; i < len; i++ ) {
|
|
||||||
var section = sections[i];
|
|
||||||
var notes = section.querySelector( 'aside.notes' );
|
|
||||||
|
|
||||||
var template = section.querySelector( 'script' );
|
var template = section.querySelector( 'script' );
|
||||||
|
|
||||||
// strip leading whitespace so it isn't evaluated as code
|
// strip leading whitespace so it isn't evaluated as code
|
||||||
var text = ( template || section ).innerHTML;
|
var text = ( template || section ).textContent;
|
||||||
|
|
||||||
var leadingWs = text.match(/^\n?(\s*)/)[1].length,
|
var leadingWs = text.match(/^\n?(\s*)/)[1].length,
|
||||||
leadingTabs = text.match(/^\n?(\t*)/)[1].length;
|
leadingTabs = text.match(/^\n?(\t*)/)[1].length;
|
||||||
@ -27,11 +23,125 @@
|
|||||||
text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
|
text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
|
||||||
}
|
}
|
||||||
|
|
||||||
section.innerHTML = (new Showdown.converter()).makeHtml(text);
|
return text;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var slidifyMarkdown = function(markdown, separator, vertical) {
|
||||||
|
|
||||||
|
separator = separator || '^\n---\n$';
|
||||||
|
|
||||||
|
var reSeparator = new RegExp(separator + (vertical ? '|' + vertical : ''), 'mg'),
|
||||||
|
reHorSeparator = new RegExp(separator),
|
||||||
|
matches,
|
||||||
|
lastIndex = 0,
|
||||||
|
isHorizontal,
|
||||||
|
wasHorizontal = true,
|
||||||
|
content,
|
||||||
|
sectionStack = [],
|
||||||
|
markdownSections = '';
|
||||||
|
|
||||||
|
// iterate until all blocks between separators are stacked up
|
||||||
|
while( matches = reSeparator.exec(markdown) ) {
|
||||||
|
|
||||||
|
// determine direction (horizontal by default)
|
||||||
|
isHorizontal = reHorSeparator.test(matches[0]);
|
||||||
|
|
||||||
|
if( !isHorizontal && wasHorizontal ) {
|
||||||
|
// create vertical stack
|
||||||
|
sectionStack.push([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pluck slide content from markdown input
|
||||||
|
content = markdown.substring(lastIndex, matches.index);
|
||||||
|
|
||||||
|
if( isHorizontal && wasHorizontal ) {
|
||||||
|
// add to horizontal stack
|
||||||
|
sectionStack.push(content);
|
||||||
|
} else {
|
||||||
|
// add to vertical stack
|
||||||
|
sectionStack[sectionStack.length-1].push(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastIndex = reSeparator.lastIndex;
|
||||||
|
wasHorizontal = isHorizontal;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the remaining slide
|
||||||
|
(wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1]).push(markdown.substring(lastIndex));
|
||||||
|
|
||||||
|
// flatten the hierarchical stack, and insert <section data-markdown> tags
|
||||||
|
for( var k = 0, klen = sectionStack.length; k < klen; k++ ) {
|
||||||
|
markdownSections += typeof sectionStack[k] === 'string'
|
||||||
|
? '<section data-markdown>' + sectionStack[k] + '</section>'
|
||||||
|
: '<section><section data-markdown>' + sectionStack[k].join('</section><section data-markdown>') + '</section></section>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return markdownSections;
|
||||||
|
};
|
||||||
|
|
||||||
|
var querySlidingMarkdown = function() {
|
||||||
|
|
||||||
|
var sections = document.querySelectorAll( '[data-markdown]'),
|
||||||
|
section;
|
||||||
|
|
||||||
|
for( var j = 0, jlen = sections.length; j < jlen; j++ ) {
|
||||||
|
|
||||||
|
section = sections[j];
|
||||||
|
|
||||||
|
if( section.getAttribute('data-markdown').length ) {
|
||||||
|
|
||||||
|
var xhr = new XMLHttpRequest(),
|
||||||
|
url = section.getAttribute('data-markdown');
|
||||||
|
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
if( xhr.readyState === 4 ) {
|
||||||
|
section.outerHTML = slidifyMarkdown( xhr.responseText, section.getAttribute('data-separator'), section.getAttribute('data-vertical') );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.open('GET', url, false);
|
||||||
|
xhr.send();
|
||||||
|
|
||||||
|
} else if( section.getAttribute('data-separator') ) {
|
||||||
|
|
||||||
|
var markdown = stripLeadingWhitespace(section);
|
||||||
|
section.outerHTML = slidifyMarkdown( markdown, section.getAttribute('data-separator'), section.getAttribute('data-vertical') );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var queryMarkdownSlides = function() {
|
||||||
|
|
||||||
|
var sections = document.querySelectorAll( '[data-markdown]');
|
||||||
|
|
||||||
|
for( var j = 0, jlen = sections.length; j < jlen; j++ ) {
|
||||||
|
|
||||||
|
makeHtml(sections[j]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var makeHtml = function(section) {
|
||||||
|
|
||||||
|
var notes = section.querySelector( 'aside.notes' );
|
||||||
|
|
||||||
|
var markdown = stripLeadingWhitespace(section);
|
||||||
|
|
||||||
|
section.innerHTML = (new Showdown.converter()).makeHtml(markdown);
|
||||||
|
|
||||||
if( notes ) {
|
if( notes ) {
|
||||||
section.appendChild( notes );
|
section.appendChild( notes );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
};
|
||||||
|
|
||||||
|
querySlidingMarkdown();
|
||||||
|
|
||||||
|
queryMarkdownSlides();
|
||||||
|
|
||||||
})();
|
})();
|
@ -225,6 +225,13 @@
|
|||||||
|
|
||||||
}, 1000 );
|
}, 1000 );
|
||||||
|
|
||||||
|
// Navigate the main window when the notes slide changes
|
||||||
|
currentSlide.contentWindow.Reveal.addEventListener( 'slidechanged', function( event ) {
|
||||||
|
|
||||||
|
window.opener.Reveal.slide( event.indexh, event.indexv );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user