Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
d8fb09fb64
@ -17,7 +17,7 @@ module.exports = function(grunt) {
|
|||||||
|
|
||||||
// Tests will be added soon
|
// Tests will be added soon
|
||||||
qunit: {
|
qunit: {
|
||||||
files: [ 'test/**/*.html' ]
|
files: [ 'test/*.html' ]
|
||||||
},
|
},
|
||||||
|
|
||||||
uglify: {
|
uglify: {
|
||||||
@ -109,6 +109,7 @@ module.exports = function(grunt) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
|
grunt.loadNpmTasks( 'grunt-contrib-qunit' );
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-jshint' );
|
grunt.loadNpmTasks( 'grunt-contrib-jshint' );
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
|
grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
|
||||||
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
|
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
|
||||||
@ -118,7 +119,7 @@ module.exports = function(grunt) {
|
|||||||
grunt.loadNpmTasks( 'grunt-zip' );
|
grunt.loadNpmTasks( 'grunt-zip' );
|
||||||
|
|
||||||
// Default task
|
// Default task
|
||||||
grunt.registerTask( 'default', [ 'jshint', 'cssmin', 'uglify' ] );
|
grunt.registerTask( 'default', [ 'jshint', 'cssmin', 'uglify', 'qunit' ] );
|
||||||
|
|
||||||
// Theme task
|
// Theme task
|
||||||
grunt.registerTask( 'themes', [ 'sass' ] );
|
grunt.registerTask( 'themes', [ 'sass' ] );
|
||||||
@ -129,4 +130,7 @@ module.exports = function(grunt) {
|
|||||||
// Serve presentation locally
|
// Serve presentation locally
|
||||||
grunt.registerTask( 'serve', [ 'connect', 'watch' ] );
|
grunt.registerTask( 'serve', [ 'connect', 'watch' ] );
|
||||||
|
|
||||||
|
// Run tests
|
||||||
|
grunt.registerTask( 'test', [ 'jshint', 'qunit' ] );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
170
README.md
170
README.md
@ -52,10 +52,10 @@ This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Iri
|
|||||||
|
|
||||||
#### External Markdown
|
#### 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.
|
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. The ```data-charset``` attribute is optional and specifies which charset to use when loading the external file.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n"></section>
|
<section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n" data-notes="^Note:" data-charset="iso-8859-15"></section>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
@ -100,9 +100,6 @@ Reveal.initialize({
|
|||||||
// Enable slide navigation via mouse wheel
|
// Enable slide navigation via mouse wheel
|
||||||
mouseWheel: false,
|
mouseWheel: false,
|
||||||
|
|
||||||
// Apply a 3D roll to links on hover
|
|
||||||
rollingLinks: true,
|
|
||||||
|
|
||||||
// Transition style
|
// Transition style
|
||||||
transition: 'default', // default/cube/page/concave/zoom/linear/fade/none
|
transition: 'default', // default/cube/page/concave/zoom/linear/fade/none
|
||||||
|
|
||||||
@ -110,7 +107,7 @@ Reveal.initialize({
|
|||||||
transitionSpeed: 'default', // default/fast/slow
|
transitionSpeed: 'default', // default/fast/slow
|
||||||
|
|
||||||
// Transition style for full page backgrounds
|
// Transition style for full page backgrounds
|
||||||
backgroundTransition: 'default' // default/linear
|
backgroundTransition: 'default' // default/linear/none
|
||||||
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -153,7 +150,10 @@ Reveal.initialize({
|
|||||||
{ src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } },
|
{ src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } },
|
||||||
|
|
||||||
// Remote control your reveal.js presentation using a touch device
|
// Remote control your reveal.js presentation using a touch device
|
||||||
{ src: 'plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }
|
{ src: 'plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } },
|
||||||
|
|
||||||
|
// MathJax
|
||||||
|
{ src: 'plugin/math/math.js', async: true }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -370,6 +370,8 @@ The display order of fragments can be controlled using the ```data-fragment-inde
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
Some libraries, like MathJax (see #505), get confused by the initially hidden fragment elements. Often times this can be fixed by calling their update or render function from this callback.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
Reveal.addEventListener( 'fragmentshown', function( event ) {
|
Reveal.addEventListener( 'fragmentshown', function( event ) {
|
||||||
// event.fragment = the fragment DOM element
|
// event.fragment = the fragment DOM element
|
||||||
@ -398,7 +400,7 @@ By default, Reveal is configured with [highlight.js](http://softwaremaniacs.org/
|
|||||||
|
|
||||||
### Overview mode
|
### Overview mode
|
||||||
|
|
||||||
Press "Esc" key to toggle the overview mode on and off. While you're in this mode, you can still navigate between slides,
|
Press "Esc" or "o" keys to toggle the overview mode on and off. While you're in this mode, you can still navigate between slides,
|
||||||
as if you were at 1,000 feet above your presentation. The overview mode comes with a few API hooks:
|
as if you were at 1,000 feet above your presentation. The overview mode comes with a few API hooks:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@ -414,7 +416,7 @@ Just press »F« on your keyboard to show your presentation in fullscreen mode.
|
|||||||
|
|
||||||
|
|
||||||
### Embedded media
|
### Embedded media
|
||||||
Embedded HTML5 `<video>`/`<audio>` and YouTube iframes are automatically paused when your navigate away from a slide. This can be disabled by decorating your element with a `data-ignore` attribute.
|
Embedded HTML5 `<video>`/`<audio>` and YouTube iframes are automatically paused when you navigate away from a slide. This can be disabled by decorating your element with a `data-ignore` attribute.
|
||||||
|
|
||||||
Add `data-autoplay` to your media element if you want it to automatically start playing when the slide is shown:
|
Add `data-autoplay` to your media element if you want it to automatically start playing when the slide is shown:
|
||||||
|
|
||||||
@ -423,6 +425,21 @@ Add `data-autoplay` to your media element if you want it to automatically start
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Stretching elements
|
||||||
|
Sometimes it's desirable to have an element, like an image or video, stretch to consume as much space as possible within a given slide. This can be done by adding the ```.stretch``` class to an element as seen below:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<section>
|
||||||
|
<h2>This video will use up the remaining space on the slide</h2>
|
||||||
|
<video class="stretch" src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
|
||||||
|
</section>
|
||||||
|
```
|
||||||
|
|
||||||
|
Limitations:
|
||||||
|
- Only direct descendants of a slide section can be stretched
|
||||||
|
- Only one descendant per slide section can be stretched
|
||||||
|
|
||||||
|
|
||||||
## PDF Export
|
## PDF Export
|
||||||
|
|
||||||
Presentations can be exported to PDF via a special print stylesheet. This feature requires that you use [Google Chrome](http://google.com/chrome).
|
Presentations can be exported to PDF via a special print stylesheet. This feature requires that you use [Google Chrome](http://google.com/chrome).
|
||||||
@ -461,7 +478,7 @@ If you want to add a theme of your own see the instructions here: [/css/theme/RE
|
|||||||
|
|
||||||
reveal.js comes with a speaker notes plugin which can be used to present per-slide notes in a separate browser window. The notes window also gives you a preview of the next upcoming slide so it may be helpful even if you haven't written any notes. Press the 's' key on your keyboard to open the notes window.
|
reveal.js comes with a speaker notes plugin which can be used to present per-slide notes in a separate browser window. The notes window also gives you a preview of the next upcoming slide so it may be helpful even if you haven't written any notes. Press the 's' key on your keyboard to open the notes window.
|
||||||
|
|
||||||
By default notes are written using standard HTML, see below, but you can add a ```data-markdown``` attribute to the ```<aside>``` to write them using Markdown.
|
Notes are defined by appending an ```<aside>``` element to a slide as seen below. You can add the ```data-markdown``` attribute to the aside element if you prefer writing notes using Markdown.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<section>
|
<section>
|
||||||
@ -473,6 +490,20 @@ By default notes are written using standard HTML, see below, but you can add a `
|
|||||||
</section>
|
</section>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you're using the external Markdown plugin, you can add notes with the help of a special delimiter:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n" data-notes="^Note:"></section>
|
||||||
|
|
||||||
|
# Title
|
||||||
|
## Sub-title
|
||||||
|
|
||||||
|
Here is some content...
|
||||||
|
|
||||||
|
Note:
|
||||||
|
This will only display in the notes window.
|
||||||
|
```
|
||||||
|
|
||||||
## Server Side Speaker Notes
|
## Server Side Speaker Notes
|
||||||
|
|
||||||
In some cases it can be desirable to run notes on a separate device from the one you're presenting on. The Node.js-based notes plugin lets you do this using the same note definitions as its client side counterpart. Include the required scripts by adding the following dependencies:
|
In some cases it can be desirable to run notes on a separate device from the one you're presenting on. The Node.js-based notes plugin lets you do this using the same note definitions as its client side counterpart. Include the required scripts by adding the following dependencies:
|
||||||
@ -520,23 +551,24 @@ You can then access your master presentation at ```http://localhost:1947```
|
|||||||
Example configuration:
|
Example configuration:
|
||||||
```javascript
|
```javascript
|
||||||
Reveal.initialize({
|
Reveal.initialize({
|
||||||
// other options
|
// other options...
|
||||||
|
|
||||||
multiplex: {
|
multiplex: {
|
||||||
// Example values. Generate your own.
|
// Example values. To generate your own, see the socket.io server instructions.
|
||||||
secret: '13652805320794272084', // Obtained from the socket.io server. Gives this (the master) control of the presentation
|
secret: '13652805320794272084', // Obtained from the socket.io server. Gives this (the master) control of the presentation
|
||||||
id: '1ea875674b17ca76', // Obtained from socket.io server
|
id: '1ea875674b17ca76', // Obtained from socket.io server
|
||||||
url: 'revealjs.jit.su:80' // Location of socket.io server
|
url: 'revealjs.jit.su:80' // Location of socket.io server
|
||||||
},
|
},
|
||||||
|
|
||||||
// Optional libraries used to extend on reveal.js
|
// Don't forget to add the dependencies
|
||||||
dependencies: [
|
dependencies: [
|
||||||
// other deps
|
|
||||||
{ src: '//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.10/socket.io.min.js', async: true },
|
{ src: '//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.10/socket.io.min.js', async: true },
|
||||||
{ src: 'plugin/multiplex/master.js', async: true },
|
{ src: 'plugin/multiplex/master.js', async: true },
|
||||||
|
|
||||||
// and if you want speaker notes
|
// and if you want speaker notes
|
||||||
{ src: 'plugin/notes-server/client.js', async: true }
|
{ src: 'plugin/notes-server/client.js', async: true }
|
||||||
|
|
||||||
|
// other dependencies...
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -547,20 +579,21 @@ Served from a publicly accessible static file server. Examples include: GitHub P
|
|||||||
Example configuration:
|
Example configuration:
|
||||||
```javascript
|
```javascript
|
||||||
Reveal.initialize({
|
Reveal.initialize({
|
||||||
// other options
|
// other options...
|
||||||
|
|
||||||
multiplex: {
|
multiplex: {
|
||||||
// Example values. Generate your own.
|
// Example values. To generate your own, see the socket.io server instructions.
|
||||||
secret: null, // null so the clients do not have control of the master presentation
|
secret: null, // null so the clients do not have control of the master presentation
|
||||||
id: '1ea875674b17ca76', // id, obtained from socket.io server
|
id: '1ea875674b17ca76', // id, obtained from socket.io server
|
||||||
url: 'revealjs.jit.su:80' // Location of socket.io server
|
url: 'revealjs.jit.su:80' // Location of socket.io server
|
||||||
},
|
},
|
||||||
|
|
||||||
// Optional libraries used to extend on reveal.js
|
// Don't forget to add the dependencies
|
||||||
dependencies: [
|
dependencies: [
|
||||||
// other deps
|
|
||||||
{ src: '//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.10/socket.io.min.js', async: true },
|
{ src: '//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.10/socket.io.min.js', async: true },
|
||||||
{ src: 'plugin/multiplex/client.js', async: true }
|
{ src: 'plugin/multiplex/client.js', async: true }
|
||||||
|
|
||||||
|
// other dependencies...
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -584,20 +617,21 @@ The socket.io server can play the role of static file server for your client pre
|
|||||||
Example configuration:
|
Example configuration:
|
||||||
```javascript
|
```javascript
|
||||||
Reveal.initialize({
|
Reveal.initialize({
|
||||||
// other options
|
// other options...
|
||||||
|
|
||||||
multiplex: {
|
multiplex: {
|
||||||
// Example values. Generate your own.
|
// Example values. To generate your own, see the socket.io server instructions.
|
||||||
secret: null, // null so the clients do not have control of the master presentation
|
secret: null, // null so the clients do not have control of the master presentation
|
||||||
id: '1ea875674b17ca76', // id, obtained from socket.io server
|
id: '1ea875674b17ca76', // id, obtained from socket.io server
|
||||||
url: 'example.com:80' // Location of your socket.io server
|
url: 'example.com:80' // Location of your socket.io server
|
||||||
},
|
},
|
||||||
|
|
||||||
// Optional libraries used to extend on reveal.js
|
// Don't forget to add the dependencies
|
||||||
dependencies: [
|
dependencies: [
|
||||||
// other deps
|
|
||||||
{ src: '//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.10/socket.io.min.js', async: true },
|
{ src: '//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.10/socket.io.min.js', async: true },
|
||||||
{ src: 'plugin/multiplex/client.js', async: true }
|
{ src: 'plugin/multiplex/client.js', async: true }
|
||||||
|
|
||||||
|
// other dependencies...
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -606,21 +640,22 @@ It can also play the role of static file server for your master presentation and
|
|||||||
Example configuration:
|
Example configuration:
|
||||||
```javascript
|
```javascript
|
||||||
Reveal.initialize({
|
Reveal.initialize({
|
||||||
// other options
|
// other options...
|
||||||
|
|
||||||
multiplex: {
|
multiplex: {
|
||||||
// Example values. Generate your own.
|
// Example values. To generate your own, see the socket.io server instructions.
|
||||||
secret: '13652805320794272084', // Obtained from the socket.io server. Gives this (the master) control of the presentation
|
secret: '13652805320794272084', // Obtained from the socket.io server. Gives this (the master) control of the presentation
|
||||||
id: '1ea875674b17ca76', // Obtained from socket.io server
|
id: '1ea875674b17ca76', // Obtained from socket.io server
|
||||||
url: 'example.com:80' // Location of your socket.io server
|
url: 'example.com:80' // Location of your socket.io server
|
||||||
},
|
},
|
||||||
|
|
||||||
// Optional libraries used to extend on reveal.js
|
// Don't forget to add the dependencies
|
||||||
dependencies: [
|
dependencies: [
|
||||||
// other deps
|
|
||||||
{ src: '//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.10/socket.io.min.js', async: true },
|
{ src: '//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.10/socket.io.min.js', async: true },
|
||||||
{ src: 'plugin/multiplex/master.js', async: true },
|
{ src: 'plugin/multiplex/master.js', async: true },
|
||||||
{ src: 'plugin/multiplex/client.js', async: true }
|
{ src: 'plugin/multiplex/client.js', async: true }
|
||||||
|
|
||||||
|
// other dependencies...
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -629,46 +664,75 @@ Reveal.initialize({
|
|||||||
The Leap Motion plugin lets you utilize your [Leap Motion](https://www.leapmotion.com/) device to control basic navigation of your presentation. The gestures currently supported are:
|
The Leap Motion plugin lets you utilize your [Leap Motion](https://www.leapmotion.com/) device to control basic navigation of your presentation. The gestures currently supported are:
|
||||||
|
|
||||||
##### 1 to 2 fingers
|
##### 1 to 2 fingers
|
||||||
* Pointer — Point to anything on screen. Move your finger past the device to expand the pointer.
|
Pointer — Point to anything on screen. Move your finger past the device to expand the pointer.
|
||||||
|
|
||||||
##### 1 hand + 3 or more fingers
|
|
||||||
|
|
||||||
* Left
|
|
||||||
* Right
|
|
||||||
* Up
|
|
||||||
* down
|
|
||||||
|
|
||||||
|
##### 1 hand + 3 or more fingers (left/right/up/down)
|
||||||
Navigate through your slides. See config options to invert movements.
|
Navigate through your slides. See config options to invert movements.
|
||||||
|
|
||||||
##### 2 hands
|
##### 2 hands upwards
|
||||||
* Up
|
|
||||||
|
|
||||||
Toggle the overview mode. Do it a second time to exit the overview.
|
Toggle the overview mode. Do it a second time to exit the overview.
|
||||||
|
|
||||||
#### Config Options
|
#### Config Options
|
||||||
You can edit the following options:
|
You can edit the following options:
|
||||||
* autoCenter: Defaults to true. Center the pointer based on where you put your finger into the leap motions detection field.
|
|
||||||
* gestureDelay: Defaults to 500. How long to delay between gestures in milliseconds.
|
| Property | Default | Description
|
||||||
* naturalSwipe: Defaults to true. Swipe as though you were touching a touch screen. Set to false to invert.
|
| ----------------- |:-----------------:| :-------------
|
||||||
* pointerColor: Defaults to #00aaff. The color of the pointer.
|
| autoCenter | true | Center the pointer based on where you put your finger into the leap motions detection field.
|
||||||
* pointerOpacity: Defaults to 0.7. The opacity of the pointer.
|
| gestureDelay | 500 | How long to delay between gestures in milliseconds.
|
||||||
* pointerSize: Defaults to 15. The minimum height and width of the pointer.
|
| naturalSwipe | true | Swipe as though you were touching a touch screen. Set to false to invert.
|
||||||
* pointerTolerance: Defaults to 120. Bigger = slower pointer.
|
| pointerColor | #00aaff | The color of the pointer.
|
||||||
|
| pointerOpacity | 0.7 | The opacity of the pointer.
|
||||||
|
| pointerSize | 15 | The minimum height and width of the pointer.
|
||||||
|
| pointerTolerance | 120 | Bigger = slower pointer.
|
||||||
|
|
||||||
|
|
||||||
Example configuration:
|
Example configuration:
|
||||||
```js
|
```js
|
||||||
Reveal.initialize({
|
Reveal.initialize({
|
||||||
// other options
|
|
||||||
|
// other options...
|
||||||
|
|
||||||
leap: {
|
leap: {
|
||||||
naturalSwipe : false, // Invert swipe gestures
|
naturalSwipe : false, // Invert swipe gestures
|
||||||
pointerOpacity : 0.5, // Set pointer opacity to 0.5
|
pointerOpacity : 0.5, // Set pointer opacity to 0.5
|
||||||
pointerColor : '#d80000' // Red pointer
|
pointerColor : '#d80000' // Red pointer
|
||||||
}
|
},
|
||||||
|
|
||||||
// Optional libraries used to extend on reveal.js
|
dependencies: [
|
||||||
{ src: 'plugin/leap/leap.js', async: true }
|
{ src: 'plugin/leap/leap.js', async: true }
|
||||||
|
]
|
||||||
|
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## MathJax
|
||||||
|
|
||||||
|
If you want to display math equations in your presentation you can easily do so by including this plugin. The plugin is a very thin wrapper around the [MathJax](http://www.mathjax.org/) library. To use it you'll need to include it as a reveal.js dependency, [find our more about dependencies here](#dependencies).
|
||||||
|
|
||||||
|
The plugin defaults to using [LaTeX](http://en.wikipedia.org/wiki/LaTeX) but that can be adjusted through the ```math``` configuration object. Note that MathJax is loaded from a remote server. If you want to use it offline you'll need to download a copy of the library and adjust the ```mathjax``` configuration value.
|
||||||
|
|
||||||
|
Below is an example of how the plugin can be configured. If you don't intend to change these values you do not need to include the ```math``` config object at all.
|
||||||
|
|
||||||
|
```js
|
||||||
|
Reveal.initialize({
|
||||||
|
|
||||||
|
// other options ...
|
||||||
|
|
||||||
|
math: {
|
||||||
|
mathjax: 'http://cdn.mathjax.org/mathjax/latest/MathJax.js',
|
||||||
|
config: 'TeX-AMS_HTML-full' // See http://docs.mathjax.org/en/latest/config-files.html
|
||||||
|
},
|
||||||
|
|
||||||
|
dependencies: [
|
||||||
|
{ src: 'plugin/math/math.js', async: true }
|
||||||
|
]
|
||||||
|
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Read MathJax's documentation if you need [HTTPS delivery](http://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn) or serving of [specific versions](http://docs.mathjax.org/en/latest/configuration.html#loading-mathjax-from-the-cdn) for stability.
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
The **basic setup** is for authoring presentations only. The **full setup** gives you access to all reveal.js features and plugins such as speaker notes as well as the development tasks needed to make changes to the source.
|
The **basic setup** is for authoring presentations only. The **full setup** gives you access to all reveal.js features and plugins such as speaker notes as well as the development tasks needed to make changes to the source.
|
||||||
@ -692,22 +756,22 @@ Some reveal.js features, like external markdown, require that presentations run
|
|||||||
|
|
||||||
2. Install [Grunt](http://gruntjs.com/getting-started#installing-the-cli)
|
2. Install [Grunt](http://gruntjs.com/getting-started#installing-the-cli)
|
||||||
|
|
||||||
4. Clone the reveal.js repository
|
4. Clone the reveal.js repository
|
||||||
```
|
```
|
||||||
$ git clone git@github.com:hakimel/reveal.js.git
|
$ git clone git@github.com:hakimel/reveal.js.git
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Navigate to the reveal.js folder
|
5. Navigate to the reveal.js folder
|
||||||
```
|
```
|
||||||
$ cd reveal.js
|
$ cd reveal.js
|
||||||
```
|
```
|
||||||
|
|
||||||
6. Install dependencies
|
6. Install dependencies
|
||||||
```
|
```
|
||||||
$ npm install
|
$ npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
7. Serve the presentation and monitor source files for changes
|
7. Serve the presentation and monitor source files for changes
|
||||||
```
|
```
|
||||||
$ grunt serve
|
$ grunt serve
|
||||||
```
|
```
|
||||||
|
@ -49,7 +49,7 @@ body, p, td, li, div, a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* SECTION 4: Set heading font face, sizes, and color.
|
/* SECTION 4: Set heading font face, sizes, and color.
|
||||||
Diffrentiate your headings from your body text.
|
Differentiate your headings from your body text.
|
||||||
Perhaps use a large sans-serif for distinction. */
|
Perhaps use a large sans-serif for distinction. */
|
||||||
h1,h2,h3,h4,h5,h6 {
|
h1,h2,h3,h4,h5,h6 {
|
||||||
color: #000!important;
|
color: #000!important;
|
||||||
|
@ -56,7 +56,7 @@ body, p, td, li, div {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* SECTION 4: Set heading font face, sizes, and color.
|
/* SECTION 4: Set heading font face, sizes, and color.
|
||||||
Diffrentiate your headings from your body text.
|
Differentiate your headings from your body text.
|
||||||
Perhaps use a large sans-serif for distinction. */
|
Perhaps use a large sans-serif for distinction. */
|
||||||
h1,h2,h3,h4,h5,h6 {
|
h1,h2,h3,h4,h5,h6 {
|
||||||
text-shadow: 0 0 0 #000 !important;
|
text-shadow: 0 0 0 #000 !important;
|
||||||
|
223
css/reveal.css
223
css/reveal.css
@ -205,6 +205,10 @@ body {
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reveal iframe {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure certain elements are never larger than the slide itself */
|
/* Ensure certain elements are never larger than the slide itself */
|
||||||
.reveal img,
|
.reveal img,
|
||||||
.reveal video,
|
.reveal video,
|
||||||
@ -314,6 +318,14 @@ body {
|
|||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
word-wrap: normal;
|
word-wrap: normal;
|
||||||
}
|
}
|
||||||
|
.reveal pre.stretch code {
|
||||||
|
height: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
.reveal table th,
|
.reveal table th,
|
||||||
.reveal table td {
|
.reveal table td {
|
||||||
@ -343,6 +355,11 @@ body {
|
|||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reveal .stretch {
|
||||||
|
max-width: none;
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************
|
/*********************************************
|
||||||
* CONTROLS
|
* CONTROLS
|
||||||
@ -460,90 +477,6 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************
|
|
||||||
* ROLLING LINKS
|
|
||||||
*********************************************/
|
|
||||||
|
|
||||||
.reveal .roll {
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 1.2;
|
|
||||||
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%;
|
|
||||||
}
|
|
||||||
.reveal .roll:hover {
|
|
||||||
background: none;
|
|
||||||
text-shadow: none;
|
|
||||||
}
|
|
||||||
.reveal .roll span {
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
padding: 0 2px;
|
|
||||||
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
-webkit-transition: all 400ms ease;
|
|
||||||
-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;
|
|
||||||
|
|
||||||
-webkit-backface-visibility: hidden;
|
|
||||||
-moz-backface-visibility: hidden;
|
|
||||||
backface-visibility: hidden;
|
|
||||||
}
|
|
||||||
.reveal .roll:hover span {
|
|
||||||
background: rgba(0,0,0,0.5);
|
|
||||||
|
|
||||||
-webkit-transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
|
|
||||||
-moz-transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
|
|
||||||
-ms-transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
|
|
||||||
transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
|
|
||||||
}
|
|
||||||
.reveal .roll span:after {
|
|
||||||
content: attr(data-title);
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
padding: 0 2px;
|
|
||||||
|
|
||||||
-webkit-backface-visibility: hidden;
|
|
||||||
-moz-backface-visibility: hidden;
|
|
||||||
backface-visibility: hidden;
|
|
||||||
|
|
||||||
-webkit-transform-origin: 50% 0%;
|
|
||||||
-moz-transform-origin: 50% 0%;
|
|
||||||
-ms-transform-origin: 50% 0%;
|
|
||||||
transform-origin: 50% 0%;
|
|
||||||
|
|
||||||
-webkit-transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg );
|
|
||||||
-moz-transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg );
|
|
||||||
-ms-transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg );
|
|
||||||
transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************
|
/*********************************************
|
||||||
* SLIDES
|
* SLIDES
|
||||||
*********************************************/
|
*********************************************/
|
||||||
@ -673,6 +606,19 @@ body {
|
|||||||
min-height: auto !important;
|
min-height: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't allow interaction with invisible slides */
|
||||||
|
.reveal .slides>section.future,
|
||||||
|
.reveal .slides>section>section.future,
|
||||||
|
.reveal .slides>section.past,
|
||||||
|
.reveal .slides>section>section.past {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal.overview .slides>section,
|
||||||
|
.reveal.overview .slides>section>section {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************
|
/*********************************************
|
||||||
@ -1152,9 +1098,10 @@ body {
|
|||||||
|
|
||||||
.reveal.overview .slides section {
|
.reveal.overview .slides section {
|
||||||
height: 600px;
|
height: 600px;
|
||||||
|
top: -300px !important;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
opacity: 1!important;
|
opacity: 1 !important;
|
||||||
visibility: visible!important;
|
visibility: visible !important;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: rgba(0,0,0,0.1);
|
background: rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
@ -1177,6 +1124,7 @@ body {
|
|||||||
}
|
}
|
||||||
.reveal.overview .slides>section.stack {
|
.reveal.overview .slides>section.stack {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
top: 0 !important;
|
||||||
background: none;
|
background: none;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
@ -1345,6 +1293,16 @@ body {
|
|||||||
visibility: visible !important;
|
visibility: visible !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Immediate transition style */
|
||||||
|
.reveal[data-background-transition=none]>.backgrounds .slide-background,
|
||||||
|
.reveal>.backgrounds .slide-background[data-background-transition=none] {
|
||||||
|
-webkit-transition: none;
|
||||||
|
-moz-transition: none;
|
||||||
|
-ms-transition: none;
|
||||||
|
-o-transition: none;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Linear sliding transition style */
|
/* Linear sliding transition style */
|
||||||
.reveal[data-background-transition=slide]>.backgrounds .slide-background,
|
.reveal[data-background-transition=slide]>.backgrounds .slide-background,
|
||||||
.reveal>.backgrounds .slide-background[data-background-transition=slide] {
|
.reveal>.backgrounds .slide-background[data-background-transition=slide] {
|
||||||
@ -1564,6 +1522,90 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* ROLLING LINKS
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
.reveal .roll {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1.2;
|
||||||
|
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%;
|
||||||
|
}
|
||||||
|
.reveal .roll:hover {
|
||||||
|
background: none;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
.reveal .roll span {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 2px;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
-webkit-transition: all 400ms ease;
|
||||||
|
-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;
|
||||||
|
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
-moz-backface-visibility: hidden;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
}
|
||||||
|
.reveal .roll:hover span {
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
|
||||||
|
-webkit-transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
|
||||||
|
-moz-transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
|
||||||
|
-ms-transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
|
||||||
|
transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg );
|
||||||
|
}
|
||||||
|
.reveal .roll span:after {
|
||||||
|
content: attr(data-title);
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
padding: 0 2px;
|
||||||
|
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
-moz-backface-visibility: hidden;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
|
||||||
|
-webkit-transform-origin: 50% 0%;
|
||||||
|
-moz-transform-origin: 50% 0%;
|
||||||
|
-ms-transform-origin: 50% 0%;
|
||||||
|
transform-origin: 50% 0%;
|
||||||
|
|
||||||
|
-webkit-transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg );
|
||||||
|
-moz-transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg );
|
||||||
|
-ms-transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg );
|
||||||
|
transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************
|
/*********************************************
|
||||||
* SPEAKER NOTES
|
* SPEAKER NOTES
|
||||||
*********************************************/
|
*********************************************/
|
||||||
@ -1605,12 +1647,3 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************
|
|
||||||
* LEAP PLUGIN
|
|
||||||
*********************************************/
|
|
||||||
|
|
||||||
#leap {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 50;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
2
css/reveal.min.css
vendored
2
css/reveal.min.css
vendored
File diff suppressed because one or more lines are too long
@ -10,6 +10,7 @@ $mainFontSize: 36px;
|
|||||||
$mainColor: #eee;
|
$mainColor: #eee;
|
||||||
|
|
||||||
// Headings
|
// Headings
|
||||||
|
$headingMargin: 0 0 20px 0;
|
||||||
$headingFont: 'League Gothic', Impact, sans-serif;
|
$headingFont: 'League Gothic', Impact, sans-serif;
|
||||||
$headingColor: #eee;
|
$headingColor: #eee;
|
||||||
$headingLineHeight: 0.9em;
|
$headingLineHeight: 0.9em;
|
||||||
|
@ -33,7 +33,7 @@ body {
|
|||||||
.reveal h4,
|
.reveal h4,
|
||||||
.reveal h5,
|
.reveal h5,
|
||||||
.reveal h6 {
|
.reveal h6 {
|
||||||
margin: 0 0 20px 0;
|
margin: $headingMargin;
|
||||||
color: $headingColor;
|
color: $headingColor;
|
||||||
|
|
||||||
font-family: $headingFont;
|
font-family: $headingFont;
|
||||||
|
@ -371,9 +371,6 @@ function linkify( selector ) {
|
|||||||
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
|
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
|
||||||
{ src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
|
{ src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
|
||||||
{ src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
|
{ src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
|
||||||
// { src: 'plugin/leap/leap.js', async: true }
|
|
||||||
// { src: 'plugin/search/search.js', async: true, condition: function() { return !!document.body.classList; } }
|
|
||||||
// { src: 'plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
640
js/reveal.js
640
js/reveal.js
@ -59,6 +59,10 @@ var Reveal = (function(){
|
|||||||
// Turns fragments on and off globally
|
// Turns fragments on and off globally
|
||||||
fragments: true,
|
fragments: true,
|
||||||
|
|
||||||
|
// Flags if the presentation is running in an embedded mode,
|
||||||
|
// i.e. contained within a limited portion of the screen
|
||||||
|
embedded: false,
|
||||||
|
|
||||||
// Number of milliseconds between automatically proceeding to the
|
// Number of milliseconds between automatically proceeding to the
|
||||||
// next slide, disabled when set to 0, this value can be overwritten
|
// next slide, disabled when set to 0, this value can be overwritten
|
||||||
// by using a data-autoslide attribute on your slides
|
// by using a data-autoslide attribute on your slides
|
||||||
@ -68,7 +72,7 @@ var Reveal = (function(){
|
|||||||
mouseWheel: false,
|
mouseWheel: false,
|
||||||
|
|
||||||
// Apply a 3D roll to links on hover
|
// Apply a 3D roll to links on hover
|
||||||
rollingLinks: true,
|
rollingLinks: false,
|
||||||
|
|
||||||
// Opens links in an iframe preview overlay
|
// Opens links in an iframe preview overlay
|
||||||
previewLinks: false,
|
previewLinks: false,
|
||||||
@ -83,18 +87,24 @@ var Reveal = (function(){
|
|||||||
transitionSpeed: 'default', // default/fast/slow
|
transitionSpeed: 'default', // default/fast/slow
|
||||||
|
|
||||||
// Transition style for full page slide backgrounds
|
// Transition style for full page slide backgrounds
|
||||||
backgroundTransition: 'default', // default/linear
|
backgroundTransition: 'default', // default/linear/none
|
||||||
|
|
||||||
|
// Number of slides away from the current that are visible
|
||||||
|
viewDistance: 3,
|
||||||
|
|
||||||
// Script dependencies to load
|
// Script dependencies to load
|
||||||
dependencies: []
|
dependencies: []
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Flags if reveal.js is loaded (has dispatched the 'ready' event)
|
||||||
|
loaded = false,
|
||||||
|
|
||||||
// The current auto-slide duration
|
// The current auto-slide duration
|
||||||
autoSlide = 0,
|
autoSlide = 0,
|
||||||
|
|
||||||
// The horizontal and vertical index of the currently active slide
|
// The horizontal and vertical index of the currently active slide
|
||||||
indexh = 0,
|
indexh,
|
||||||
indexv = 0,
|
indexv,
|
||||||
|
|
||||||
// The previous and current slide HTML elements
|
// The previous and current slide HTML elements
|
||||||
previousSlide,
|
previousSlide,
|
||||||
@ -111,19 +121,14 @@ var Reveal = (function(){
|
|||||||
// Cached references to DOM elements
|
// Cached references to DOM elements
|
||||||
dom = {},
|
dom = {},
|
||||||
|
|
||||||
// Detect support for CSS 3D transforms
|
// Client support for CSS 3D transforms, see #checkCapabilities()
|
||||||
supports3DTransforms = 'WebkitPerspective' in document.body.style ||
|
supports3DTransforms,
|
||||||
'MozPerspective' in document.body.style ||
|
|
||||||
'msPerspective' in document.body.style ||
|
|
||||||
'OPerspective' in document.body.style ||
|
|
||||||
'perspective' in document.body.style,
|
|
||||||
|
|
||||||
// Detect support for CSS 2D transforms
|
// Client support for CSS 2D transforms, see #checkCapabilities()
|
||||||
supports2DTransforms = 'WebkitTransform' in document.body.style ||
|
supports2DTransforms,
|
||||||
'MozTransform' in document.body.style ||
|
|
||||||
'msTransform' in document.body.style ||
|
// Client is a mobile device, see #checkCapabilities()
|
||||||
'OTransform' in document.body.style ||
|
isMobileDevice,
|
||||||
'transform' in document.body.style,
|
|
||||||
|
|
||||||
// Throttles mouse wheel navigation
|
// Throttles mouse wheel navigation
|
||||||
lastMouseWheelStep = 0,
|
lastMouseWheelStep = 0,
|
||||||
@ -149,8 +154,8 @@ var Reveal = (function(){
|
|||||||
startY: 0,
|
startY: 0,
|
||||||
startSpan: 0,
|
startSpan: 0,
|
||||||
startCount: 0,
|
startCount: 0,
|
||||||
handled: false,
|
captured: false,
|
||||||
threshold: 80
|
threshold: 40
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,6 +163,8 @@ var Reveal = (function(){
|
|||||||
*/
|
*/
|
||||||
function initialize( options ) {
|
function initialize( options ) {
|
||||||
|
|
||||||
|
checkCapabilities();
|
||||||
|
|
||||||
if( !supports2DTransforms && !supports3DTransforms ) {
|
if( !supports2DTransforms && !supports3DTransforms ) {
|
||||||
document.body.setAttribute( 'class', 'no-transforms' );
|
document.body.setAttribute( 'class', 'no-transforms' );
|
||||||
|
|
||||||
@ -180,6 +187,136 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inspect the client to see what it's capable of, this
|
||||||
|
* should only happens once per runtime.
|
||||||
|
*/
|
||||||
|
function checkCapabilities() {
|
||||||
|
|
||||||
|
supports3DTransforms = 'WebkitPerspective' in document.body.style ||
|
||||||
|
'MozPerspective' in document.body.style ||
|
||||||
|
'msPerspective' in document.body.style ||
|
||||||
|
'OPerspective' in document.body.style ||
|
||||||
|
'perspective' in document.body.style;
|
||||||
|
|
||||||
|
supports2DTransforms = 'WebkitTransform' in document.body.style ||
|
||||||
|
'MozTransform' in document.body.style ||
|
||||||
|
'msTransform' in document.body.style ||
|
||||||
|
'OTransform' in document.body.style ||
|
||||||
|
'transform' in document.body.style;
|
||||||
|
|
||||||
|
isMobileDevice = navigator.userAgent.match( /(iphone|ipod|android)/gi );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the dependencies of reveal.js. Dependencies are
|
||||||
|
* defined via the configuration option 'dependencies'
|
||||||
|
* and will be loaded prior to starting/binding reveal.js.
|
||||||
|
* Some dependencies may have an 'async' flag, if so they
|
||||||
|
* will load after reveal.js has been started up.
|
||||||
|
*/
|
||||||
|
function load() {
|
||||||
|
|
||||||
|
var scripts = [],
|
||||||
|
scriptsAsync = [];
|
||||||
|
|
||||||
|
for( var i = 0, len = config.dependencies.length; i < len; i++ ) {
|
||||||
|
var s = config.dependencies[i];
|
||||||
|
|
||||||
|
// Load if there's no condition or the condition is truthy
|
||||||
|
if( !s.condition || s.condition() ) {
|
||||||
|
if( s.async ) {
|
||||||
|
scriptsAsync.push( s.src );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scripts.push( s.src );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension may contain callback functions
|
||||||
|
if( typeof s.callback === 'function' ) {
|
||||||
|
head.ready( s.src.match( /([\w\d_\-]*)\.?js$|[^\\\/]*$/i )[0], s.callback );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called once synchronous scripts finish loading
|
||||||
|
function proceed() {
|
||||||
|
if( scriptsAsync.length ) {
|
||||||
|
// Load asynchronous scripts
|
||||||
|
head.js.apply( null, scriptsAsync );
|
||||||
|
}
|
||||||
|
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( scripts.length ) {
|
||||||
|
head.ready( proceed );
|
||||||
|
|
||||||
|
// Load synchronous scripts
|
||||||
|
head.js.apply( null, scripts );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proceed();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts up reveal.js by binding input events and navigating
|
||||||
|
* to the current URL deeplink if there is one.
|
||||||
|
*/
|
||||||
|
function start() {
|
||||||
|
|
||||||
|
// Make sure we've got all the DOM elements we need
|
||||||
|
setupDOM();
|
||||||
|
|
||||||
|
// Decorate the slide DOM elements with state classes (past/future)
|
||||||
|
setupSlides();
|
||||||
|
|
||||||
|
// Updates the presentation to match the current configuration values
|
||||||
|
configure();
|
||||||
|
|
||||||
|
// Read the initial hash
|
||||||
|
readURL();
|
||||||
|
|
||||||
|
// Notify listeners that the presentation is ready but use a 1ms
|
||||||
|
// timeout to ensure it's not fired synchronously after #initialize()
|
||||||
|
setTimeout( function() {
|
||||||
|
// Enable transitions now that we're loaded
|
||||||
|
dom.slides.classList.remove( 'no-transition' );
|
||||||
|
|
||||||
|
loaded = true;
|
||||||
|
|
||||||
|
dispatchEvent( 'ready', {
|
||||||
|
'indexh': indexh,
|
||||||
|
'indexv': indexv,
|
||||||
|
'currentSlide': currentSlide
|
||||||
|
} );
|
||||||
|
}, 1 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates through and decorates slides DOM elements with
|
||||||
|
* appropriate classes.
|
||||||
|
*/
|
||||||
|
function setupSlides() {
|
||||||
|
|
||||||
|
var horizontalSlides = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
||||||
|
horizontalSlides.forEach( function( horizontalSlide ) {
|
||||||
|
|
||||||
|
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
|
||||||
|
verticalSlides.forEach( function( verticalSlide, y ) {
|
||||||
|
|
||||||
|
if( y > 0 ) verticalSlide.classList.add( 'future' );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds and stores references to DOM elements which are
|
* Finds and stores references to DOM elements which are
|
||||||
* required by the presentation. If a required element is
|
* required by the presentation. If a required element is
|
||||||
@ -192,50 +329,30 @@ var Reveal = (function(){
|
|||||||
dom.wrapper = document.querySelector( '.reveal' );
|
dom.wrapper = document.querySelector( '.reveal' );
|
||||||
dom.slides = document.querySelector( '.reveal .slides' );
|
dom.slides = document.querySelector( '.reveal .slides' );
|
||||||
|
|
||||||
|
// Prevent transitions while we're loading
|
||||||
|
dom.slides.classList.add( 'no-transition' );
|
||||||
|
|
||||||
// Background element
|
// Background element
|
||||||
if( !document.querySelector( '.reveal .backgrounds' ) ) {
|
dom.background = createSingletonNode( dom.wrapper, 'div', 'backgrounds', null );
|
||||||
dom.background = document.createElement( 'div' );
|
|
||||||
dom.background.classList.add( 'backgrounds' );
|
|
||||||
dom.wrapper.appendChild( dom.background );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Progress bar
|
// Progress bar
|
||||||
if( !dom.wrapper.querySelector( '.progress' ) ) {
|
dom.progress = createSingletonNode( dom.wrapper, 'div', 'progress', '<span></span>' );
|
||||||
var progressElement = document.createElement( 'div' );
|
dom.progressbar = dom.progress.querySelector( 'span' );
|
||||||
progressElement.classList.add( 'progress' );
|
|
||||||
progressElement.innerHTML = '<span></span>';
|
|
||||||
dom.wrapper.appendChild( progressElement );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Arrow controls
|
// Arrow controls
|
||||||
if( !dom.wrapper.querySelector( '.controls' ) ) {
|
createSingletonNode( dom.wrapper, 'aside', 'controls',
|
||||||
var controlsElement = document.createElement( 'aside' );
|
'<div class="navigate-left"></div>' +
|
||||||
controlsElement.classList.add( 'controls' );
|
'<div class="navigate-right"></div>' +
|
||||||
controlsElement.innerHTML = '<div class="navigate-left"></div>' +
|
'<div class="navigate-up"></div>' +
|
||||||
'<div class="navigate-right"></div>' +
|
'<div class="navigate-down"></div>' );
|
||||||
'<div class="navigate-up"></div>' +
|
|
||||||
'<div class="navigate-down"></div>';
|
|
||||||
dom.wrapper.appendChild( controlsElement );
|
|
||||||
}
|
|
||||||
|
|
||||||
// State background element [DEPRECATED]
|
// State background element [DEPRECATED]
|
||||||
if( !dom.wrapper.querySelector( '.state-background' ) ) {
|
createSingletonNode( dom.wrapper, 'div', 'state-background', null );
|
||||||
var stateBackgroundElement = document.createElement( 'div' );
|
|
||||||
stateBackgroundElement.classList.add( 'state-background' );
|
|
||||||
dom.wrapper.appendChild( stateBackgroundElement );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overlay graphic which is displayed during the paused mode
|
// Overlay graphic which is displayed during the paused mode
|
||||||
if( !dom.wrapper.querySelector( '.pause-overlay' ) ) {
|
createSingletonNode( dom.wrapper, 'div', 'pause-overlay', null );
|
||||||
var pausedElement = document.createElement( 'div' );
|
|
||||||
pausedElement.classList.add( 'pause-overlay' );
|
|
||||||
dom.wrapper.appendChild( pausedElement );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache references to elements
|
// Cache references to elements
|
||||||
dom.progress = document.querySelector( '.reveal .progress' );
|
|
||||||
dom.progressbar = document.querySelector( '.reveal .progress span' );
|
|
||||||
|
|
||||||
if ( config.controls ) {
|
if ( config.controls ) {
|
||||||
dom.controls = document.querySelector( '.reveal .controls' );
|
dom.controls = document.querySelector( '.reveal .controls' );
|
||||||
|
|
||||||
@ -250,6 +367,26 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an HTML element and returns a reference to it.
|
||||||
|
* If the element already exists the existing instance will
|
||||||
|
* be returned.
|
||||||
|
*/
|
||||||
|
function createSingletonNode( container, tagname, classname, innerHTML ) {
|
||||||
|
|
||||||
|
var node = container.querySelector( '.' + classname );
|
||||||
|
if( !node ) {
|
||||||
|
node = document.createElement( tagname );
|
||||||
|
node.classList.add( classname );
|
||||||
|
if( innerHTML !== null ) {
|
||||||
|
node.innerHTML = innerHTML;
|
||||||
|
}
|
||||||
|
container.appendChild( node );
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the slide background elements and appends them
|
* Creates the slide background elements and appends them
|
||||||
* to the background container. One element is created per
|
* to the background container. One element is created per
|
||||||
@ -334,99 +471,6 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides the address bar if we're on a mobile device.
|
|
||||||
*/
|
|
||||||
function hideAddressBar() {
|
|
||||||
|
|
||||||
if( /iphone|ipod|android/gi.test( navigator.userAgent ) && !/crios/gi.test( navigator.userAgent ) ) {
|
|
||||||
// Events that should trigger the address bar to hide
|
|
||||||
window.addEventListener( 'load', removeAddressBar, false );
|
|
||||||
window.addEventListener( 'orientationchange', removeAddressBar, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the dependencies of reveal.js. Dependencies are
|
|
||||||
* defined via the configuration option 'dependencies'
|
|
||||||
* and will be loaded prior to starting/binding reveal.js.
|
|
||||||
* Some dependencies may have an 'async' flag, if so they
|
|
||||||
* will load after reveal.js has been started up.
|
|
||||||
*/
|
|
||||||
function load() {
|
|
||||||
|
|
||||||
var scripts = [],
|
|
||||||
scriptsAsync = [];
|
|
||||||
|
|
||||||
for( var i = 0, len = config.dependencies.length; i < len; i++ ) {
|
|
||||||
var s = config.dependencies[i];
|
|
||||||
|
|
||||||
// Load if there's no condition or the condition is truthy
|
|
||||||
if( !s.condition || s.condition() ) {
|
|
||||||
if( s.async ) {
|
|
||||||
scriptsAsync.push( s.src );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scripts.push( s.src );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extension may contain callback functions
|
|
||||||
if( typeof s.callback === 'function' ) {
|
|
||||||
head.ready( s.src.match( /([\w\d_\-]*)\.?js$|[^\\\/]*$/i )[0], s.callback );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called once synchronous scripts finish loading
|
|
||||||
function proceed() {
|
|
||||||
if( scriptsAsync.length ) {
|
|
||||||
// Load asynchronous scripts
|
|
||||||
head.js.apply( null, scriptsAsync );
|
|
||||||
}
|
|
||||||
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( scripts.length ) {
|
|
||||||
head.ready( proceed );
|
|
||||||
|
|
||||||
// Load synchronous scripts
|
|
||||||
head.js.apply( null, scripts );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
proceed();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts up reveal.js by binding input events and navigating
|
|
||||||
* to the current URL deeplink if there is one.
|
|
||||||
*/
|
|
||||||
function start() {
|
|
||||||
|
|
||||||
// Make sure we've got all the DOM elements we need
|
|
||||||
setupDOM();
|
|
||||||
|
|
||||||
// Updates the presentation to match the current configuration values
|
|
||||||
configure();
|
|
||||||
|
|
||||||
// Read the initial hash
|
|
||||||
readURL();
|
|
||||||
|
|
||||||
// Notify listeners that the presentation is ready but use a 1ms
|
|
||||||
// timeout to ensure it's not fired synchronously after #initialize()
|
|
||||||
setTimeout( function() {
|
|
||||||
dispatchEvent( 'ready', {
|
|
||||||
'indexh': indexh,
|
|
||||||
'indexv': indexv,
|
|
||||||
'currentSlide': currentSlide
|
|
||||||
} );
|
|
||||||
}, 1 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the configuration settings from the config
|
* Applies the configuration settings from the config
|
||||||
* object. May be called multiple times.
|
* object. May be called multiple times.
|
||||||
@ -630,6 +674,19 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a CSS transform to the target element.
|
||||||
|
*/
|
||||||
|
function transformElement( element, transform ) {
|
||||||
|
|
||||||
|
element.style.WebkitTransform = transform;
|
||||||
|
element.style.MozTransform = transform;
|
||||||
|
element.style.msTransform = transform;
|
||||||
|
element.style.OTransform = transform;
|
||||||
|
element.style.transform = transform;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the height of the given element by looking
|
* Retrieves the height of the given element by looking
|
||||||
* at the position and height of its immediate children.
|
* at the position and height of its immediate children.
|
||||||
@ -665,6 +722,48 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the remaining height within the parent of the
|
||||||
|
* target element after subtracting the height of all
|
||||||
|
* siblings.
|
||||||
|
*
|
||||||
|
* remaining height = [parent height] - [ siblings height]
|
||||||
|
*/
|
||||||
|
function getRemainingHeight( element, height ) {
|
||||||
|
|
||||||
|
height = height || 0;
|
||||||
|
|
||||||
|
if( element ) {
|
||||||
|
var parent = element.parentNode;
|
||||||
|
var siblings = parent.childNodes;
|
||||||
|
|
||||||
|
// Subtract the height of each sibling
|
||||||
|
toArray( siblings ).forEach( function( sibling ) {
|
||||||
|
|
||||||
|
if( typeof sibling.offsetHeight === 'number' && sibling !== element ) {
|
||||||
|
|
||||||
|
var styles = window.getComputedStyle( sibling ),
|
||||||
|
marginTop = parseInt( styles.marginTop, 10 ),
|
||||||
|
marginBottom = parseInt( styles.marginBottom, 10 );
|
||||||
|
|
||||||
|
height -= sibling.offsetHeight + marginTop + marginBottom;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
var elementStyles = window.getComputedStyle( element );
|
||||||
|
|
||||||
|
// Subtract the margins of the target element
|
||||||
|
height -= parseInt( elementStyles.marginTop, 10 ) +
|
||||||
|
parseInt( elementStyles.marginBottom, 10 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return height;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this instance is being used to print a PDF.
|
* Checks if this instance is being used to print a PDF.
|
||||||
*/
|
*/
|
||||||
@ -674,6 +773,19 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides the address bar if we're on a mobile device.
|
||||||
|
*/
|
||||||
|
function hideAddressBar() {
|
||||||
|
|
||||||
|
if( /iphone|ipod|android/gi.test( navigator.userAgent ) && !/crios/gi.test( navigator.userAgent ) ) {
|
||||||
|
// Events that should trigger the address bar to hide
|
||||||
|
window.addEventListener( 'load', removeAddressBar, false );
|
||||||
|
window.addEventListener( 'orientationchange', removeAddressBar, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Causes the address bar to hide on mobile devices,
|
* Causes the address bar to hide on mobile devices,
|
||||||
* more vertical space ftw.
|
* more vertical space ftw.
|
||||||
@ -886,7 +998,11 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
// Dimensions of the content
|
// Dimensions of the content
|
||||||
var slideWidth = config.width,
|
var slideWidth = config.width,
|
||||||
slideHeight = config.height;
|
slideHeight = config.height,
|
||||||
|
slidePadding = 20; // TODO Dig this out of DOM
|
||||||
|
|
||||||
|
// Layout the contents of the slides
|
||||||
|
layoutSlideContents( config.width, config.height, slidePadding );
|
||||||
|
|
||||||
// Slide width may be a percentage of available width
|
// Slide width may be a percentage of available width
|
||||||
if( typeof slideWidth === 'string' && /%$/.test( slideWidth ) ) {
|
if( typeof slideWidth === 'string' && /%$/.test( slideWidth ) ) {
|
||||||
@ -915,13 +1031,7 @@ var Reveal = (function(){
|
|||||||
}
|
}
|
||||||
// Apply scale transform as a fallback
|
// Apply scale transform as a fallback
|
||||||
else {
|
else {
|
||||||
var transform = 'translate(-50%, -50%) scale('+ scale +') translate(50%, 50%)';
|
transformElement( dom.slides, 'translate(-50%, -50%) scale('+ scale +') translate(50%, 50%)' );
|
||||||
|
|
||||||
dom.slides.style.WebkitTransform = transform;
|
|
||||||
dom.slides.style.MozTransform = transform;
|
|
||||||
dom.slides.style.msTransform = transform;
|
|
||||||
dom.slides.style.OTransform = transform;
|
|
||||||
dom.slides.style.transform = transform;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select all slides, vertical and horizontal
|
// Select all slides, vertical and horizontal
|
||||||
@ -942,7 +1052,7 @@ var Reveal = (function(){
|
|||||||
slide.style.top = 0;
|
slide.style.top = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
slide.style.top = Math.max( - ( getAbsoluteHeight( slide ) / 2 ) - 20, -slideHeight / 2 ) + 'px';
|
slide.style.top = Math.max( - ( getAbsoluteHeight( slide ) / 2 ) - slidePadding, -slideHeight / 2 ) + 'px';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -957,6 +1067,38 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies layout logic to the contents of all slides in
|
||||||
|
* the presentation.
|
||||||
|
*/
|
||||||
|
function layoutSlideContents( width, height, padding ) {
|
||||||
|
|
||||||
|
// Handle sizing of elements with the 'stretch' class
|
||||||
|
toArray( dom.slides.querySelectorAll( 'section > .stretch' ) ).forEach( function( element ) {
|
||||||
|
|
||||||
|
// Determine how much vertical space we can use
|
||||||
|
var remainingHeight = getRemainingHeight( element, ( height - ( padding * 2 ) ) );
|
||||||
|
|
||||||
|
// Consider the aspect ratio of media elements
|
||||||
|
if( /(img|video)/gi.test( element.nodeName ) ) {
|
||||||
|
var nw = element.naturalWidth || element.videoWidth,
|
||||||
|
nh = element.naturalHeight || element.videoHeight;
|
||||||
|
|
||||||
|
var es = Math.min( width / nw, remainingHeight / nh );
|
||||||
|
|
||||||
|
element.style.width = ( nw * es ) + 'px';
|
||||||
|
element.style.height = ( nh * es ) + 'px';
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
element.style.width = width + 'px';
|
||||||
|
element.style.height = remainingHeight + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the vertical index of a stack so that the same
|
* Stores the vertical index of a stack so that the same
|
||||||
* vertical slide can be selected when navigating to and
|
* vertical slide can be selected when navigating to and
|
||||||
@ -1010,6 +1152,9 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
var wasActive = dom.wrapper.classList.contains( 'overview' );
|
var wasActive = dom.wrapper.classList.contains( 'overview' );
|
||||||
|
|
||||||
|
// Vary the depth of the overview based on screen size
|
||||||
|
var depth = window.innerWidth < 400 ? 1000 : 2500;
|
||||||
|
|
||||||
dom.wrapper.classList.add( 'overview' );
|
dom.wrapper.classList.add( 'overview' );
|
||||||
dom.wrapper.classList.remove( 'exit-overview' );
|
dom.wrapper.classList.remove( 'exit-overview' );
|
||||||
|
|
||||||
@ -1025,16 +1170,12 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
for( var i = 0, len1 = horizontalSlides.length; i < len1; i++ ) {
|
for( var i = 0, len1 = horizontalSlides.length; i < len1; i++ ) {
|
||||||
var hslide = horizontalSlides[i],
|
var hslide = horizontalSlides[i],
|
||||||
hoffset = config.rtl ? -105 : 105,
|
hoffset = config.rtl ? -105 : 105;
|
||||||
htransform = 'translateZ(-2500px) translate(' + ( ( i - indexh ) * hoffset ) + '%, 0%)';
|
|
||||||
|
|
||||||
hslide.setAttribute( 'data-index-h', i );
|
hslide.setAttribute( 'data-index-h', i );
|
||||||
hslide.style.display = 'block';
|
|
||||||
hslide.style.WebkitTransform = htransform;
|
// Apply CSS transform
|
||||||
hslide.style.MozTransform = htransform;
|
transformElement( hslide, 'translateZ(-'+ depth +'px) translate(' + ( ( i - indexh ) * hoffset ) + '%, 0%)' );
|
||||||
hslide.style.msTransform = htransform;
|
|
||||||
hslide.style.OTransform = htransform;
|
|
||||||
hslide.style.transform = htransform;
|
|
||||||
|
|
||||||
if( hslide.classList.contains( 'stack' ) ) {
|
if( hslide.classList.contains( 'stack' ) ) {
|
||||||
|
|
||||||
@ -1043,17 +1184,13 @@ var Reveal = (function(){
|
|||||||
for( var j = 0, len2 = verticalSlides.length; j < len2; j++ ) {
|
for( var j = 0, len2 = verticalSlides.length; j < len2; j++ ) {
|
||||||
var verticalIndex = i === indexh ? indexv : getPreviousVerticalIndex( hslide );
|
var verticalIndex = i === indexh ? indexv : getPreviousVerticalIndex( hslide );
|
||||||
|
|
||||||
var vslide = verticalSlides[j],
|
var vslide = verticalSlides[j];
|
||||||
vtransform = 'translate(0%, ' + ( ( j - verticalIndex ) * 105 ) + '%)';
|
|
||||||
|
|
||||||
vslide.setAttribute( 'data-index-h', i );
|
vslide.setAttribute( 'data-index-h', i );
|
||||||
vslide.setAttribute( 'data-index-v', j );
|
vslide.setAttribute( 'data-index-v', j );
|
||||||
vslide.style.display = 'block';
|
|
||||||
vslide.style.WebkitTransform = vtransform;
|
// Apply CSS transform
|
||||||
vslide.style.MozTransform = vtransform;
|
transformElement( vslide, 'translate(0%, ' + ( ( j - verticalIndex ) * 105 ) + '%)' );
|
||||||
vslide.style.msTransform = vtransform;
|
|
||||||
vslide.style.OTransform = vtransform;
|
|
||||||
vslide.style.transform = vtransform;
|
|
||||||
|
|
||||||
// Navigate to this slide on click
|
// Navigate to this slide on click
|
||||||
vslide.addEventListener( 'click', onOverviewSlideClicked, true );
|
vslide.addEventListener( 'click', onOverviewSlideClicked, true );
|
||||||
@ -1068,6 +1205,8 @@ var Reveal = (function(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSlidesVisibility();
|
||||||
|
|
||||||
layout();
|
layout();
|
||||||
|
|
||||||
if( !wasActive ) {
|
if( !wasActive ) {
|
||||||
@ -1117,11 +1256,7 @@ var Reveal = (function(){
|
|||||||
element.style.display = '';
|
element.style.display = '';
|
||||||
|
|
||||||
// Resets all transforms to use the external styles
|
// Resets all transforms to use the external styles
|
||||||
element.style.WebkitTransform = '';
|
transformElement( element, '' );
|
||||||
element.style.MozTransform = '';
|
|
||||||
element.style.msTransform = '';
|
|
||||||
element.style.OTransform = '';
|
|
||||||
element.style.transform = '';
|
|
||||||
|
|
||||||
element.removeEventListener( 'click', onOverviewSlideClicked, true );
|
element.removeEventListener( 'click', onOverviewSlideClicked, true );
|
||||||
}
|
}
|
||||||
@ -1182,7 +1317,7 @@ var Reveal = (function(){
|
|||||||
// Prefer slide argument, otherwise use current slide
|
// Prefer slide argument, otherwise use current slide
|
||||||
slide = slide ? slide : currentSlide;
|
slide = slide ? slide : currentSlide;
|
||||||
|
|
||||||
return slide && !!slide.parentNode.nodeName.match( /section/i );
|
return slide && slide.parentNode && !!slide.parentNode.nodeName.match( /section/i );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1302,13 +1437,16 @@ var Reveal = (function(){
|
|||||||
// Reset the state array
|
// Reset the state array
|
||||||
state.length = 0;
|
state.length = 0;
|
||||||
|
|
||||||
var indexhBefore = indexh,
|
var indexhBefore = indexh || 0,
|
||||||
indexvBefore = indexv;
|
indexvBefore = indexv || 0;
|
||||||
|
|
||||||
// Activate and transition to the new slide
|
// Activate and transition to the new slide
|
||||||
indexh = updateSlides( HORIZONTAL_SLIDES_SELECTOR, h === undefined ? indexh : h );
|
indexh = updateSlides( HORIZONTAL_SLIDES_SELECTOR, h === undefined ? indexh : h );
|
||||||
indexv = updateSlides( VERTICAL_SLIDES_SELECTOR, v === undefined ? indexv : v );
|
indexv = updateSlides( VERTICAL_SLIDES_SELECTOR, v === undefined ? indexv : v );
|
||||||
|
|
||||||
|
// Update the visibility of slides now that the indices have changed
|
||||||
|
updateSlidesVisibility();
|
||||||
|
|
||||||
layout();
|
layout();
|
||||||
|
|
||||||
// Apply the new state
|
// Apply the new state
|
||||||
@ -1338,10 +1476,6 @@ var Reveal = (function(){
|
|||||||
activateOverview();
|
activateOverview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the URL hash after a delay since updating it mid-transition
|
|
||||||
// is likely to cause visual lag
|
|
||||||
writeURL( 1500 );
|
|
||||||
|
|
||||||
// Find the current horizontal slide and any possible vertical slides
|
// Find the current horizontal slide and any possible vertical slides
|
||||||
// within it
|
// within it
|
||||||
var currentHorizontalSlide = horizontalSlides[ indexh ],
|
var currentHorizontalSlide = horizontalSlides[ indexh ],
|
||||||
@ -1413,6 +1547,9 @@ var Reveal = (function(){
|
|||||||
updateProgress();
|
updateProgress();
|
||||||
updateBackground();
|
updateBackground();
|
||||||
|
|
||||||
|
// Update the URL hash
|
||||||
|
writeURL();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1481,16 +1618,6 @@ var Reveal = (function(){
|
|||||||
for( var i = 0; i < slidesLength; i++ ) {
|
for( var i = 0; i < slidesLength; i++ ) {
|
||||||
var element = slides[i];
|
var element = slides[i];
|
||||||
|
|
||||||
// Optimization; hide all slides that are three or more steps
|
|
||||||
// away from the present slide
|
|
||||||
if( isOverview() === false ) {
|
|
||||||
// The distance loops so that it measures 1 between the first
|
|
||||||
// and last slides
|
|
||||||
var distance = Math.abs( ( index - i ) % ( slidesLength - 3 ) ) || 0;
|
|
||||||
|
|
||||||
element.style.display = distance > 3 ? 'none' : 'block';
|
|
||||||
}
|
|
||||||
|
|
||||||
var reverse = config.rtl && !isVerticalSlide( element );
|
var reverse = config.rtl && !isVerticalSlide( element );
|
||||||
|
|
||||||
element.classList.remove( 'past' );
|
element.classList.remove( 'past' );
|
||||||
@ -1507,6 +1634,13 @@ var Reveal = (function(){
|
|||||||
else if( i > index ) {
|
else if( i > index ) {
|
||||||
// Any element subsequent to index is given the 'future' class
|
// Any element subsequent to index is given the 'future' class
|
||||||
element.classList.add( reverse ? 'past' : 'future' );
|
element.classList.add( reverse ? 'past' : 'future' );
|
||||||
|
|
||||||
|
var fragments = toArray( element.querySelectorAll( '.fragment.visible' ) );
|
||||||
|
|
||||||
|
// No fragments in future slides should be visible ahead of time
|
||||||
|
while( fragments.length ) {
|
||||||
|
fragments.pop().classList.remove( 'visible' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this element contains vertical slides
|
// If this element contains vertical slides
|
||||||
@ -1526,7 +1660,7 @@ var Reveal = (function(){
|
|||||||
state = state.concat( slideState.split( ' ' ) );
|
state = state.concat( slideState.split( ' ' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this slide has a data-autoslide attribtue associated use this as
|
// If this slide has a data-autoslide attribute associated use this as
|
||||||
// autoSlide value otherwise use the global configured time
|
// autoSlide value otherwise use the global configured time
|
||||||
var slideAutoSlide = slides[index].getAttribute( 'data-autoslide' );
|
var slideAutoSlide = slides[index].getAttribute( 'data-autoslide' );
|
||||||
if( slideAutoSlide ) {
|
if( slideAutoSlide ) {
|
||||||
@ -1536,6 +1670,8 @@ var Reveal = (function(){
|
|||||||
autoSlide = config.autoSlide;
|
autoSlide = config.autoSlide;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cueAutoSlide();
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Since there are no slides we can't be anywhere beyond the
|
// Since there are no slides we can't be anywhere beyond the
|
||||||
@ -1547,6 +1683,61 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimization method; hide all slides that are far away
|
||||||
|
* from the present slide.
|
||||||
|
*/
|
||||||
|
function updateSlidesVisibility() {
|
||||||
|
|
||||||
|
// Select all slides and convert the NodeList result to
|
||||||
|
// an array
|
||||||
|
var horizontalSlides = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ),
|
||||||
|
horizontalSlidesLength = horizontalSlides.length,
|
||||||
|
distanceX,
|
||||||
|
distanceY;
|
||||||
|
|
||||||
|
if( horizontalSlidesLength ) {
|
||||||
|
|
||||||
|
// The number of steps away from the present slide that will
|
||||||
|
// be visible
|
||||||
|
var viewDistance = isOverview() ? 10 : config.viewDistance;
|
||||||
|
|
||||||
|
// Limit view distance on weaker devices
|
||||||
|
if( isMobileDevice ) {
|
||||||
|
viewDistance = isOverview() ? 6 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( var x = 0; x < horizontalSlidesLength; x++ ) {
|
||||||
|
var horizontalSlide = horizontalSlides[x];
|
||||||
|
|
||||||
|
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) ),
|
||||||
|
verticalSlidesLength = verticalSlides.length;
|
||||||
|
|
||||||
|
// Loops so that it measures 1 between the first and last slides
|
||||||
|
distanceX = Math.abs( ( indexh - x ) % ( horizontalSlidesLength - viewDistance ) ) || 0;
|
||||||
|
|
||||||
|
// Show the horizontal slide if it's within the view distance
|
||||||
|
horizontalSlide.style.display = distanceX > viewDistance ? 'none' : 'block';
|
||||||
|
|
||||||
|
if( verticalSlidesLength ) {
|
||||||
|
|
||||||
|
var oy = getPreviousVerticalIndex( horizontalSlide );
|
||||||
|
|
||||||
|
for( var y = 0; y < verticalSlidesLength; y++ ) {
|
||||||
|
var verticalSlide = verticalSlides[y];
|
||||||
|
|
||||||
|
distanceY = x === indexh ? Math.abs( indexv - y ) : Math.abs( y - oy );
|
||||||
|
|
||||||
|
verticalSlide.style.display = ( distanceX + distanceY ) > viewDistance ? 'none' : 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the progress bar to reflect the current slide.
|
* Updates the progress bar to reflect the current slide.
|
||||||
*/
|
*/
|
||||||
@ -1803,7 +1994,7 @@ var Reveal = (function(){
|
|||||||
}
|
}
|
||||||
// If the slide doesn't exist, navigate to the current slide
|
// If the slide doesn't exist, navigate to the current slide
|
||||||
else {
|
else {
|
||||||
slide( indexh, indexv );
|
slide( indexh || 0, indexv || 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1811,7 +2002,9 @@ var Reveal = (function(){
|
|||||||
var h = parseInt( bits[0], 10 ) || 0,
|
var h = parseInt( bits[0], 10 ) || 0,
|
||||||
v = parseInt( bits[1], 10 ) || 0;
|
v = parseInt( bits[1], 10 ) || 0;
|
||||||
|
|
||||||
slide( h, v );
|
if( h !== indexh || v !== indexv ) {
|
||||||
|
slide( h, v );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1888,8 +2081,9 @@ var Reveal = (function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( !slide && currentSlide ) {
|
if( !slide && currentSlide ) {
|
||||||
var visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' );
|
var hasFragments = currentSlide.querySelectorAll( '.fragment' ).length > 0;
|
||||||
if( visibleFragments.length ) {
|
if( hasFragments ) {
|
||||||
|
var visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' );
|
||||||
f = visibleFragments.length;
|
f = visibleFragments.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2119,7 +2313,7 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
var value = config.keyboard[ key ];
|
var value = config.keyboard[ key ];
|
||||||
|
|
||||||
// Calback function
|
// Callback function
|
||||||
if( typeof value === 'function' ) {
|
if( typeof value === 'function' ) {
|
||||||
value.apply( null, [ event ] );
|
value.apply( null, [ event ] );
|
||||||
}
|
}
|
||||||
@ -2178,7 +2372,8 @@ var Reveal = (function(){
|
|||||||
if( triggered ) {
|
if( triggered ) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
else if ( event.keyCode === 27 && supports3DTransforms ) {
|
// ESC or O key
|
||||||
|
else if ( ( event.keyCode === 27 || event.keyCode === 79 ) && supports3DTransforms ) {
|
||||||
toggleOverview();
|
toggleOverview();
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -2220,11 +2415,11 @@ var Reveal = (function(){
|
|||||||
function onTouchMove( event ) {
|
function onTouchMove( event ) {
|
||||||
|
|
||||||
// Each touch should only trigger one action
|
// Each touch should only trigger one action
|
||||||
if( !touch.handled ) {
|
if( !touch.captured ) {
|
||||||
var currentX = event.touches[0].clientX;
|
var currentX = event.touches[0].clientX;
|
||||||
var currentY = event.touches[0].clientY;
|
var currentY = event.touches[0].clientY;
|
||||||
|
|
||||||
// If the touch started off with two points and still has
|
// If the touch started with two points and still has
|
||||||
// two active touches; test for the pinch gesture
|
// two active touches; test for the pinch gesture
|
||||||
if( event.touches.length === 2 && touch.startCount === 2 && config.overview ) {
|
if( event.touches.length === 2 && touch.startCount === 2 && config.overview ) {
|
||||||
|
|
||||||
@ -2240,7 +2435,7 @@ var Reveal = (function(){
|
|||||||
// If the span is larger than the desire amount we've got
|
// If the span is larger than the desire amount we've got
|
||||||
// ourselves a pinch
|
// ourselves a pinch
|
||||||
if( Math.abs( touch.startSpan - currentSpan ) > touch.threshold ) {
|
if( Math.abs( touch.startSpan - currentSpan ) > touch.threshold ) {
|
||||||
touch.handled = true;
|
touch.captured = true;
|
||||||
|
|
||||||
if( currentSpan < touch.startSpan ) {
|
if( currentSpan < touch.startSpan ) {
|
||||||
activateOverview();
|
activateOverview();
|
||||||
@ -2260,23 +2455,34 @@ var Reveal = (function(){
|
|||||||
deltaY = currentY - touch.startY;
|
deltaY = currentY - touch.startY;
|
||||||
|
|
||||||
if( deltaX > touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
|
if( deltaX > touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
|
||||||
touch.handled = true;
|
touch.captured = true;
|
||||||
navigateLeft();
|
navigateLeft();
|
||||||
}
|
}
|
||||||
else if( deltaX < -touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
|
else if( deltaX < -touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
|
||||||
touch.handled = true;
|
touch.captured = true;
|
||||||
navigateRight();
|
navigateRight();
|
||||||
}
|
}
|
||||||
else if( deltaY > touch.threshold ) {
|
else if( deltaY > touch.threshold ) {
|
||||||
touch.handled = true;
|
touch.captured = true;
|
||||||
navigateUp();
|
navigateUp();
|
||||||
}
|
}
|
||||||
else if( deltaY < -touch.threshold ) {
|
else if( deltaY < -touch.threshold ) {
|
||||||
touch.handled = true;
|
touch.captured = true;
|
||||||
navigateDown();
|
navigateDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
event.preventDefault();
|
// If we're embedded, only block touch events if they have
|
||||||
|
// triggered an action
|
||||||
|
if( config.embedded ) {
|
||||||
|
if( touch.captured || isVerticalSlide( currentSlide ) ) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not embedded? Block them all to avoid needless tossing
|
||||||
|
// around of the viewport in iOS
|
||||||
|
else {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2293,7 +2499,7 @@ var Reveal = (function(){
|
|||||||
*/
|
*/
|
||||||
function onTouchEnd( event ) {
|
function onTouchEnd( event ) {
|
||||||
|
|
||||||
touch.handled = false;
|
touch.captured = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2553,12 +2759,22 @@ var Reveal = (function(){
|
|||||||
|
|
||||||
// Returns true if we're currently on the last slide
|
// Returns true if we're currently on the last slide
|
||||||
isLastSlide: function() {
|
isLastSlide: function() {
|
||||||
if( currentSlide && currentSlide.classList.contains( '.stack' ) ) {
|
if( currentSlide ) {
|
||||||
return currentSlide.querySelector( SLIDES_SELECTOR + '.future' ) == null ? true : false;
|
// Does this slide has next a sibling?
|
||||||
}
|
if( currentSlide.nextElementSibling ) return false;
|
||||||
else {
|
|
||||||
return document.querySelector( SLIDES_SELECTOR + '.future' ) == null ? true : false;
|
// If it's vertical, does its parent have a next sibling?
|
||||||
|
if( isVerticalSlide( currentSlide ) && currentSlide.parentNode.nextElementSibling ) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Checks if reveal.js has been loaded and is ready for use
|
||||||
|
isReady: function() {
|
||||||
|
return loaded;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Forward event binding to the reveal DOM element
|
// Forward event binding to the reveal DOM element
|
||||||
|
4
js/reveal.min.js
vendored
4
js/reveal.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "reveal.js",
|
"name": "reveal.js",
|
||||||
"version": "2.5.0",
|
"version": "2.6.0-dev",
|
||||||
"description": "The HTML Presentation Framework",
|
"description": "The HTML Presentation Framework",
|
||||||
"homepage": "http://lab.hakim.se/reveal-js",
|
"homepage": "http://lab.hakim.se/reveal-js",
|
||||||
"subdomain": "revealjs",
|
"subdomain": "revealjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "grunt jshint",
|
"test": "grunt test",
|
||||||
"start": ""
|
"start": ""
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
@ -27,6 +27,7 @@
|
|||||||
"socket.io": "~0.9.13"
|
"socket.io": "~0.9.13"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"grunt-contrib-qunit": "~0.2.2",
|
||||||
"grunt-contrib-jshint": "~0.2.0",
|
"grunt-contrib-jshint": "~0.2.0",
|
||||||
"grunt-contrib-cssmin": "~0.4.1",
|
"grunt-contrib-cssmin": "~0.4.1",
|
||||||
"grunt-contrib-uglify": "~0.1.1",
|
"grunt-contrib-uglify": "~0.1.1",
|
||||||
|
@ -48,6 +48,9 @@ var b=right.criteria;if(a!==b){if(a>b||a===void 0)return 1;if(a<b||b===void 0)re
|
|||||||
|
|
||||||
pointer.id = 'leap';
|
pointer.id = 'leap';
|
||||||
|
|
||||||
|
pointer.style.position = 'absolute';
|
||||||
|
pointer.style.visibility = 'hidden';
|
||||||
|
pointer.style.zIndex = 50;
|
||||||
pointer.style.opacity = config.pointerOpacity;
|
pointer.style.opacity = config.pointerOpacity;
|
||||||
pointer.style.backgroundColor = config.pointerColor;
|
pointer.style.backgroundColor = config.pointerColor;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<div class="slides">
|
<div class="slides">
|
||||||
|
|
||||||
<!-- Use external markdown resource, and separate slides by three newlines; vertical slides by two newlines -->
|
<!-- Use external markdown resource, 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>
|
<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) -->
|
<!-- Slides are separated by three dashes (quick 'n dirty regular expression) -->
|
||||||
@ -87,7 +87,8 @@
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
{ src: '../../lib/js/classList.js', condition: function() { return !document.body.classList; } },
|
{ src: '../../lib/js/classList.js', condition: function() { return !document.body.classList; } },
|
||||||
{ src: 'marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
{ src: 'marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
||||||
{ src: 'markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }
|
{ src: 'markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
||||||
|
{ src: '../notes/notes.js' }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
Content 1.1
|
Content 1.1
|
||||||
|
|
||||||
|
Note: This will only appear in the speaker notes window.
|
||||||
|
|
||||||
|
|
||||||
## External 1.2
|
## External 1.2
|
||||||
|
|
||||||
|
@ -1,190 +1,271 @@
|
|||||||
// From https://gist.github.com/1343518
|
/**
|
||||||
// Modified by Hakim to handle Markdown indented with tabs
|
* The reveal.js markdown plugin. Handles parsing of
|
||||||
|
* markdown inside of presentations as well as loading
|
||||||
|
* of external markdown documents.
|
||||||
|
*/
|
||||||
(function(){
|
(function(){
|
||||||
|
|
||||||
if( typeof marked === 'undefined' ) {
|
if( typeof marked === 'undefined' ) {
|
||||||
throw 'The reveal.js Markdown plugin requires marked to be loaded';
|
throw 'The reveal.js Markdown plugin requires marked to be loaded';
|
||||||
}
|
}
|
||||||
|
|
||||||
var stripLeadingWhitespace = function(section) {
|
if( typeof hljs !== 'undefined' ) {
|
||||||
|
marked.setOptions({
|
||||||
|
highlight: function( lang, code ) {
|
||||||
|
return hljs.highlightAuto( lang, code ).value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var template = section.querySelector( 'script' );
|
/**
|
||||||
|
* Retrieves the markdown contents of a slide section
|
||||||
|
* element. Normalizes leading tabs/whitespace.
|
||||||
|
*/
|
||||||
|
function getMarkdownFromSlide( section ) {
|
||||||
|
|
||||||
// strip leading whitespace so it isn't evaluated as code
|
var template = section.querySelector( 'script' );
|
||||||
var text = ( template || section ).textContent;
|
|
||||||
|
|
||||||
var leadingWs = text.match(/^\n?(\s*)/)[1].length,
|
// strip leading whitespace so it isn't evaluated as code
|
||||||
leadingTabs = text.match(/^\n?(\t*)/)[1].length;
|
var text = ( template || section ).textContent;
|
||||||
|
|
||||||
if( leadingTabs > 0 ) {
|
var leadingWs = text.match( /^\n?(\s*)/ )[1].length,
|
||||||
text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
|
leadingTabs = text.match( /^\n?(\t*)/ )[1].length;
|
||||||
}
|
|
||||||
else if( leadingWs > 1 ) {
|
|
||||||
text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
if( leadingTabs > 0 ) {
|
||||||
|
text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
|
||||||
|
}
|
||||||
|
else if( leadingWs > 1 ) {
|
||||||
|
text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
|
||||||
|
}
|
||||||
|
|
||||||
};
|
return text;
|
||||||
|
|
||||||
var twrap = function(el) {
|
}
|
||||||
return '<script type="text/template">' + el + '</script>';
|
|
||||||
};
|
|
||||||
|
|
||||||
var getForwardedAttributes = function(section) {
|
/**
|
||||||
var attributes = section.attributes;
|
* Given a markdown slide section element, this will
|
||||||
var result = [];
|
* return all arguments that aren't related to markdown
|
||||||
|
* parsing. Used to forward any other user-defined arguments
|
||||||
|
* to the output markdown slide.
|
||||||
|
*/
|
||||||
|
function getForwardedAttributes( section ) {
|
||||||
|
|
||||||
for( var i = 0, len = attributes.length; i < len; i++ ) {
|
var attributes = section.attributes;
|
||||||
var name = attributes[i].name,
|
var result = [];
|
||||||
value = attributes[i].value;
|
|
||||||
|
|
||||||
// disregard attributes that are used for markdown loading/parsing
|
for( var i = 0, len = attributes.length; i < len; i++ ) {
|
||||||
if( /data\-(markdown|separator|vertical)/gi.test( name ) ) continue;
|
var name = attributes[i].name,
|
||||||
|
value = attributes[i].value;
|
||||||
|
|
||||||
if( value ) {
|
// disregard attributes that are used for markdown loading/parsing
|
||||||
result.push( name + '=' + value );
|
if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;
|
||||||
}
|
|
||||||
else {
|
|
||||||
result.push( name );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.join( ' ' );
|
if( value ) {
|
||||||
}
|
result.push( name + '=' + value );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.push( name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var slidifyMarkdown = function(markdown, separator, vertical, attributes) {
|
return result.join( ' ' );
|
||||||
|
|
||||||
separator = separator || '^\n---\n$';
|
}
|
||||||
|
|
||||||
var reSeparator = new RegExp(separator + (vertical ? '|' + vertical : ''), 'mg'),
|
/**
|
||||||
reHorSeparator = new RegExp(separator),
|
* Helper function for constructing a markdown slide.
|
||||||
matches,
|
*/
|
||||||
lastIndex = 0,
|
function createMarkdownSlide( data ) {
|
||||||
isHorizontal,
|
|
||||||
wasHorizontal = true,
|
|
||||||
content,
|
|
||||||
sectionStack = [],
|
|
||||||
markdownSections = '';
|
|
||||||
|
|
||||||
// iterate until all blocks between separators are stacked up
|
var content = data.content || data;
|
||||||
while( matches = reSeparator.exec(markdown) ) {
|
|
||||||
|
|
||||||
// determine direction (horizontal by default)
|
if( data.notes ) {
|
||||||
isHorizontal = reHorSeparator.test(matches[0]);
|
content += '<aside class="notes" data-markdown>' + data.notes + '</aside>';
|
||||||
|
}
|
||||||
|
|
||||||
if( !isHorizontal && wasHorizontal ) {
|
return '<script type="text/template">' + content + '</script>';
|
||||||
// create vertical stack
|
|
||||||
sectionStack.push([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pluck slide content from markdown input
|
}
|
||||||
content = markdown.substring(lastIndex, matches.index);
|
|
||||||
|
|
||||||
if( isHorizontal && wasHorizontal ) {
|
/**
|
||||||
// add to horizontal stack
|
* Parses a data string into multiple slides based
|
||||||
sectionStack.push(content);
|
* on the passed in separator arguments.
|
||||||
} else {
|
*/
|
||||||
// add to vertical stack
|
function slidifyMarkdown( markdown, options ) {
|
||||||
sectionStack[sectionStack.length-1].push(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastIndex = reSeparator.lastIndex;
|
options = options || {};
|
||||||
wasHorizontal = isHorizontal;
|
options.separator = options.separator || '^\n---\n$';
|
||||||
|
options.notesSeparator = options.notesSeparator || 'note:';
|
||||||
|
options.attributes = options.attributes || '';
|
||||||
|
|
||||||
}
|
var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
|
||||||
|
horizontalSeparatorRegex = new RegExp( options.separator ),
|
||||||
|
notesSeparatorRegex = new RegExp( options.notesSeparator, 'mgi' );
|
||||||
|
|
||||||
// add the remaining slide
|
var matches,
|
||||||
(wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1]).push(markdown.substring(lastIndex));
|
noteMatch,
|
||||||
|
lastIndex = 0,
|
||||||
|
isHorizontal,
|
||||||
|
wasHorizontal = true,
|
||||||
|
content,
|
||||||
|
notes,
|
||||||
|
slide,
|
||||||
|
sectionStack = [];
|
||||||
|
|
||||||
// flatten the hierarchical stack, and insert <section data-markdown> tags
|
// iterate until all blocks between separators are stacked up
|
||||||
for( var k = 0, klen = sectionStack.length; k < klen; k++ ) {
|
while( matches = separatorRegex.exec( markdown ) ) {
|
||||||
// horizontal
|
notes = null;
|
||||||
if( typeof sectionStack[k] === 'string' ) {
|
|
||||||
markdownSections += '<section '+ attributes +' data-markdown>' + twrap( sectionStack[k] ) + '</section>';
|
|
||||||
}
|
|
||||||
// vertical
|
|
||||||
else {
|
|
||||||
markdownSections += '<section '+ attributes +'>' +
|
|
||||||
'<section data-markdown>' + sectionStack[k].map(twrap).join('</section><section data-markdown>') + '</section>' +
|
|
||||||
'</section>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return markdownSections;
|
// determine direction (horizontal by default)
|
||||||
};
|
isHorizontal = horizontalSeparatorRegex.test( matches[0] );
|
||||||
|
|
||||||
var querySlidingMarkdown = function() {
|
if( !isHorizontal && wasHorizontal ) {
|
||||||
|
// create vertical stack
|
||||||
|
sectionStack.push( [] );
|
||||||
|
}
|
||||||
|
|
||||||
var sections = document.querySelectorAll( '[data-markdown]'),
|
// pluck slide content from markdown input
|
||||||
section;
|
content = markdown.substring( lastIndex, matches.index );
|
||||||
|
noteMatch = content.split( notesSeparatorRegex );
|
||||||
|
|
||||||
for( var j = 0, jlen = sections.length; j < jlen; j++ ) {
|
if( noteMatch.length === 2 ) {
|
||||||
|
content = noteMatch[0];
|
||||||
|
notes = noteMatch[1].trim();
|
||||||
|
}
|
||||||
|
|
||||||
section = sections[j];
|
slide = {
|
||||||
|
content: content,
|
||||||
|
notes: notes || ''
|
||||||
|
};
|
||||||
|
|
||||||
if( section.getAttribute('data-markdown').length ) {
|
if( isHorizontal && wasHorizontal ) {
|
||||||
|
// add to horizontal stack
|
||||||
|
sectionStack.push( slide );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// add to vertical stack
|
||||||
|
sectionStack[sectionStack.length-1].push( slide );
|
||||||
|
}
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest(),
|
lastIndex = separatorRegex.lastIndex;
|
||||||
url = section.getAttribute('data-markdown');
|
wasHorizontal = isHorizontal;
|
||||||
|
}
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
// add the remaining slide
|
||||||
if( xhr.readyState === 4 ) {
|
( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );
|
||||||
if (xhr.status >= 200 && xhr.status < 300) {
|
|
||||||
section.outerHTML = slidifyMarkdown( xhr.responseText, section.getAttribute('data-separator'), section.getAttribute('data-vertical'), getForwardedAttributes(section) );
|
|
||||||
} else {
|
|
||||||
section.outerHTML = '<section data-state="alert">ERROR: The attempt to fetch ' + url + ' failed with the HTTP status ' + xhr.status +
|
|
||||||
'. Check your browser\'s JavaScript console for more details.' +
|
|
||||||
'<p>Remember that you need to serve the presentation HTML from a HTTP server and the Markdown file must be there too.</p></section>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.open('GET', url, false);
|
var markdownSections = '';
|
||||||
try {
|
|
||||||
xhr.send();
|
|
||||||
} catch (e) {
|
|
||||||
alert('Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if( section.getAttribute('data-separator') ) {
|
// flatten the hierarchical stack, and insert <section data-markdown> tags
|
||||||
|
for( var i = 0, len = sectionStack.length; i < len; i++ ) {
|
||||||
|
// vertical
|
||||||
|
if( sectionStack[i].propertyIsEnumerable( length ) && typeof sectionStack[i].splice === 'function' ) {
|
||||||
|
markdownSections += '<section '+ options.attributes +'>' +
|
||||||
|
'<section data-markdown>' + sectionStack[i].map( createMarkdownSlide ).join( '</section><section data-markdown>' ) + '</section>' +
|
||||||
|
'</section>';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
markdownSections += '<section '+ options.attributes +' data-markdown>' + createMarkdownSlide( sectionStack[i] ) + '</section>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var markdown = stripLeadingWhitespace(section);
|
return markdownSections;
|
||||||
section.outerHTML = slidifyMarkdown( markdown, section.getAttribute('data-separator'), section.getAttribute('data-vertical'), getForwardedAttributes(section) );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
};
|
function loadExternalMarkdown() {
|
||||||
|
|
||||||
var queryMarkdownSlides = function() {
|
var sections = document.querySelectorAll( '[data-markdown]'),
|
||||||
|
section;
|
||||||
|
|
||||||
var sections = document.querySelectorAll( '[data-markdown]');
|
for( var i = 0, len = sections.length; i < len; i++ ) {
|
||||||
|
|
||||||
for( var j = 0, jlen = sections.length; j < jlen; j++ ) {
|
section = sections[i];
|
||||||
|
|
||||||
makeHtml(sections[j]);
|
if( section.getAttribute( 'data-markdown' ).length ) {
|
||||||
|
|
||||||
}
|
var xhr = new XMLHttpRequest(),
|
||||||
|
url = section.getAttribute( 'data-markdown' );
|
||||||
|
|
||||||
};
|
datacharset = section.getAttribute( 'data-charset' );
|
||||||
|
|
||||||
var makeHtml = function(section) {
|
// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
|
||||||
|
if( datacharset != null && datacharset != '' ) {
|
||||||
|
xhr.overrideMimeType( 'text/html; charset=' + datacharset );
|
||||||
|
}
|
||||||
|
|
||||||
var notes = section.querySelector( 'aside.notes' );
|
xhr.onreadystatechange = function() {
|
||||||
|
if( xhr.readyState === 4 ) {
|
||||||
|
if ( xhr.status >= 200 && xhr.status < 300 ) {
|
||||||
|
|
||||||
var markdown = stripLeadingWhitespace(section);
|
section.outerHTML = slidifyMarkdown( xhr.responseText, {
|
||||||
|
separator: section.getAttribute( 'data-separator' ),
|
||||||
|
verticalSeparator: section.getAttribute( 'data-vertical' ),
|
||||||
|
notesSeparator: section.getAttribute( 'data-notes' ),
|
||||||
|
attributes: getForwardedAttributes( section )
|
||||||
|
});
|
||||||
|
|
||||||
section.innerHTML = marked(markdown);
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
if( notes ) {
|
section.outerHTML = '<section data-state="alert">' +
|
||||||
section.appendChild( notes );
|
'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
|
||||||
}
|
'Check your browser\'s JavaScript console for more details.' +
|
||||||
|
'<p>Remember that you need to serve the presentation HTML from a HTTP server.</p>' +
|
||||||
|
'</section>';
|
||||||
|
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
querySlidingMarkdown();
|
xhr.open( 'GET', url, false );
|
||||||
|
|
||||||
queryMarkdownSlides();
|
try {
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
catch ( e ) {
|
||||||
|
alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if( section.getAttribute( 'data-separator' ) ) {
|
||||||
|
|
||||||
|
section.outerHTML = slidifyMarkdown( getMarkdownFromSlide( section ), {
|
||||||
|
separator: section.getAttribute( 'data-separator' ),
|
||||||
|
verticalSeparator: section.getAttribute( 'data-vertical' ),
|
||||||
|
notesSeparator: section.getAttribute( 'data-notes' ),
|
||||||
|
attributes: getForwardedAttributes( section )
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertMarkdownToHTML() {
|
||||||
|
|
||||||
|
var sections = document.querySelectorAll( '[data-markdown]');
|
||||||
|
|
||||||
|
for( var i = 0, len = sections.length; i < len; i++ ) {
|
||||||
|
|
||||||
|
var section = sections[i];
|
||||||
|
|
||||||
|
var notes = section.querySelector( 'aside.notes' );
|
||||||
|
var markdown = getMarkdownFromSlide( section );
|
||||||
|
|
||||||
|
section.innerHTML = marked( markdown );
|
||||||
|
|
||||||
|
// If there were notes, we need to re-add them after
|
||||||
|
// having overwritten the section's HTML
|
||||||
|
if( notes ) {
|
||||||
|
section.appendChild( notes );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
loadExternalMarkdown();
|
||||||
|
convertMarkdownToHTML();
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
64
plugin/math/math.js
Executable file
64
plugin/math/math.js
Executable file
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* A plugin which enables rendering of math equations inside
|
||||||
|
* of reveal.js slides. Essentially a thin wrapper for MathJax.
|
||||||
|
*
|
||||||
|
* @author Hakim El Hattab
|
||||||
|
*/
|
||||||
|
var RevealMath = window.RevealMath || (function(){
|
||||||
|
|
||||||
|
var options = Reveal.getConfig().math || {};
|
||||||
|
options.mathjax = options.mathjax || 'http://cdn.mathjax.org/mathjax/latest/MathJax.js';
|
||||||
|
options.config = options.config || 'TeX-AMS_HTML-full';
|
||||||
|
|
||||||
|
loadScript( options.mathjax + '?config=' + options.config, function() {
|
||||||
|
|
||||||
|
MathJax.Hub.Config({
|
||||||
|
messageStyle: 'none',
|
||||||
|
tex2jax: { inlineMath: [['$','$'],['\\(','\\)']] },
|
||||||
|
skipStartupTypeset: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Typeset followed by an immediate reveal.js layout since
|
||||||
|
// the typesetting process could affect slide height
|
||||||
|
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub ] );
|
||||||
|
MathJax.Hub.Queue( Reveal.layout );
|
||||||
|
|
||||||
|
// Reprocess equations in slides when they turn visible
|
||||||
|
Reveal.addEventListener( 'slidechanged', function( event ) {
|
||||||
|
|
||||||
|
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
function loadScript( url, callback ) {
|
||||||
|
|
||||||
|
var head = document.querySelector( 'head' );
|
||||||
|
var script = document.createElement( 'script' );
|
||||||
|
script.type = 'text/javascript';
|
||||||
|
script.src = url;
|
||||||
|
|
||||||
|
// Wrapper for callback to make sure it only fires once
|
||||||
|
var finish = function() {
|
||||||
|
if( typeof callback === 'function' ) {
|
||||||
|
callback.call();
|
||||||
|
callback = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
script.onload = finish;
|
||||||
|
|
||||||
|
// IE
|
||||||
|
script.onreadystatechange = function() {
|
||||||
|
if ( this.readyState === 'loaded' ) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal browsers
|
||||||
|
head.appendChild( script );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
@ -169,10 +169,12 @@
|
|||||||
|
|
||||||
var notes = document.getElementById( 'notes' ),
|
var notes = document.getElementById( 'notes' ),
|
||||||
currentSlide = document.getElementById( 'current-slide' ),
|
currentSlide = document.getElementById( 'current-slide' ),
|
||||||
nextSlide = document.getElementById( 'next-slide' );
|
nextSlide = document.getElementById( 'next-slide' ),
|
||||||
|
silenced = false;
|
||||||
|
|
||||||
window.addEventListener( 'message', function( event ) {
|
window.addEventListener( 'message', function( event ) {
|
||||||
var data = JSON.parse( event.data );
|
var data = JSON.parse( event.data );
|
||||||
|
|
||||||
// No need for updating the notes in case of fragment changes
|
// No need for updating the notes in case of fragment changes
|
||||||
if ( data.notes !== undefined) {
|
if ( data.notes !== undefined) {
|
||||||
if( data.markdown ) {
|
if( data.markdown ) {
|
||||||
@ -183,18 +185,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Showing and hiding fragments
|
silenced = true;
|
||||||
if( data.fragment === 'next' ) {
|
|
||||||
currentSlide.contentWindow.Reveal.nextFragment();
|
// Update the note slides
|
||||||
}
|
currentSlide.contentWindow.Reveal.slide( data.indexh, data.indexv, data.indexf );
|
||||||
else if( data.fragment === 'prev' ) {
|
nextSlide.contentWindow.Reveal.slide( data.nextindexh, data.nextindexv );
|
||||||
currentSlide.contentWindow.Reveal.prevFragment();
|
|
||||||
}
|
silenced = false;
|
||||||
else {
|
|
||||||
// Update the note slides
|
|
||||||
currentSlide.contentWindow.Reveal.slide( data.indexh, data.indexv );
|
|
||||||
nextSlide.contentWindow.Reveal.slide( data.nextindexh, data.nextindexv );
|
|
||||||
}
|
|
||||||
|
|
||||||
}, false );
|
}, false );
|
||||||
|
|
||||||
@ -226,12 +223,21 @@
|
|||||||
|
|
||||||
}, 1000 );
|
}, 1000 );
|
||||||
|
|
||||||
|
// Broadcasts the state of the notes window to synchronize
|
||||||
|
// the main window
|
||||||
|
function synchronizeMainWindow() {
|
||||||
|
|
||||||
|
if( !silenced ) {
|
||||||
|
var indices = currentSlide.contentWindow.Reveal.getIndices();
|
||||||
|
window.opener.Reveal.slide( indices.h, indices.v, indices.f );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Navigate the main window when the notes slide changes
|
// Navigate the main window when the notes slide changes
|
||||||
currentSlide.contentWindow.Reveal.addEventListener( 'slidechanged', function( event ) {
|
currentSlide.contentWindow.Reveal.addEventListener( 'slidechanged', synchronizeMainWindow );
|
||||||
|
currentSlide.contentWindow.Reveal.addEventListener( 'fragmentshown', synchronizeMainWindow );
|
||||||
window.opener.Reveal.slide( event.indexh, event.indexv );
|
currentSlide.contentWindow.Reveal.addEventListener( 'fragmenthidden', synchronizeMainWindow );
|
||||||
|
|
||||||
} );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -10,72 +10,50 @@ var RevealNotes = (function() {
|
|||||||
var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1120,height=850' );
|
var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1120,height=850' );
|
||||||
|
|
||||||
// Fires when slide is changed
|
// Fires when slide is changed
|
||||||
Reveal.addEventListener( 'slidechanged', function( event ) {
|
Reveal.addEventListener( 'slidechanged', post );
|
||||||
post('slidechanged');
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Fires when a fragment is shown
|
// Fires when a fragment is shown
|
||||||
Reveal.addEventListener( 'fragmentshown', function( event ) {
|
Reveal.addEventListener( 'fragmentshown', post );
|
||||||
post('fragmentshown');
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Fires when a fragment is hidden
|
// Fires when a fragment is hidden
|
||||||
Reveal.addEventListener( 'fragmenthidden', function( event ) {
|
Reveal.addEventListener( 'fragmenthidden', post );
|
||||||
post('fragmenthidden');
|
|
||||||
} );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posts the current slide data to the notes window
|
* Posts the current slide data to the notes window
|
||||||
*
|
|
||||||
* @param {String} eventType Expecting 'slidechanged', 'fragmentshown'
|
|
||||||
* or 'fragmenthidden' set in the events above to define the needed
|
|
||||||
* slideDate.
|
|
||||||
*/
|
*/
|
||||||
function post( eventType ) {
|
function post() {
|
||||||
var slideElement = Reveal.getCurrentSlide(),
|
var slideElement = Reveal.getCurrentSlide(),
|
||||||
|
slideIndices = Reveal.getIndices(),
|
||||||
messageData;
|
messageData;
|
||||||
|
|
||||||
if( eventType === 'slidechanged' ) {
|
var notes = slideElement.querySelector( 'aside.notes' ),
|
||||||
var notes = slideElement.querySelector( 'aside.notes' ),
|
nextindexh,
|
||||||
indexh = Reveal.getIndices().h,
|
nextindexv;
|
||||||
indexv = Reveal.getIndices().v,
|
|
||||||
nextindexh,
|
|
||||||
nextindexv;
|
|
||||||
|
|
||||||
if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) {
|
if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) {
|
||||||
nextindexh = indexh;
|
nextindexh = slideIndices.h;
|
||||||
nextindexv = indexv + 1;
|
nextindexv = slideIndices.v + 1;
|
||||||
} else {
|
} else {
|
||||||
nextindexh = indexh + 1;
|
nextindexh = slideIndices.h + 1;
|
||||||
nextindexv = 0;
|
nextindexv = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
messageData = {
|
messageData = {
|
||||||
notes : notes ? notes.innerHTML : '',
|
notes : notes ? notes.innerHTML : '',
|
||||||
indexh : indexh,
|
indexh : slideIndices.h,
|
||||||
indexv : indexv,
|
indexv : slideIndices.v,
|
||||||
nextindexh : nextindexh,
|
indexf : slideIndices.f,
|
||||||
nextindexv : nextindexv,
|
nextindexh : nextindexh,
|
||||||
markdown : notes ? typeof notes.getAttribute( 'data-markdown' ) === 'string' : false
|
nextindexv : nextindexv,
|
||||||
};
|
markdown : notes ? typeof notes.getAttribute( 'data-markdown' ) === 'string' : false
|
||||||
}
|
};
|
||||||
else if( eventType === 'fragmentshown' ) {
|
|
||||||
messageData = {
|
|
||||||
fragment : 'next'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if( eventType === 'fragmenthidden' ) {
|
|
||||||
messageData = {
|
|
||||||
fragment : 'prev'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
notesPopup.postMessage( JSON.stringify( messageData ), '*' );
|
notesPopup.postMessage( JSON.stringify( messageData ), '*' );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigate to the current slide when the notes are loaded
|
// Navigate to the current slide when the notes are loaded
|
||||||
notesPopup.addEventListener( 'load', function( event ) {
|
notesPopup.addEventListener( 'load', function( event ) {
|
||||||
post('slidechanged');
|
post();
|
||||||
}, false );
|
}, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<title>reveal.js - Barebones</title>
|
<title>reveal.js - Barebones</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="../css/reveal.min.css">
|
<link rel="stylesheet" href="../../css/reveal.min.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -29,8 +29,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="../lib/js/head.min.js"></script>
|
<script src="../../lib/js/head.min.js"></script>
|
||||||
<script src="../js/reveal.min.js"></script>
|
<script src="../../js/reveal.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
|
||||||
<link rel="stylesheet" href="../css/reveal.min.css">
|
<link rel="stylesheet" href="../../css/reveal.min.css">
|
||||||
<link rel="stylesheet" href="../css/theme/default.css" id="theme">
|
<link rel="stylesheet" href="../../css/theme/default.css" id="theme">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -34,8 +34,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="../lib/js/head.min.js"></script>
|
<script src="../../lib/js/head.min.js"></script>
|
||||||
<script src="../js/reveal.min.js"></script>
|
<script src="../../js/reveal.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
185
test/examples/math.html
Normal file
185
test/examples/math.html
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title>reveal.js - Math Plugin</title>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../../css/reveal.min.css">
|
||||||
|
<link rel="stylesheet" href="../../css/theme/night.css" id="theme">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="reveal">
|
||||||
|
|
||||||
|
<div class="slides">
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>reveal.js Math Plugin</h2>
|
||||||
|
<p>A thin wrapper for MathJax</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>The Lorenz Equations</h3>
|
||||||
|
|
||||||
|
\[\begin{aligned}
|
||||||
|
\dot{x} & = \sigma(y-x) \\
|
||||||
|
\dot{y} & = \rho x - y - xz \\
|
||||||
|
\dot{z} & = -\beta z + xy
|
||||||
|
\end{aligned} \]
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>The Cauchy-Schwarz Inequality</h3>
|
||||||
|
|
||||||
|
<script type="math/tex; mode=display">
|
||||||
|
\left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right)
|
||||||
|
</script>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>A Cross Product Formula</h3>
|
||||||
|
|
||||||
|
\[\mathbf{V}_1 \times \mathbf{V}_2 = \begin{vmatrix}
|
||||||
|
\mathbf{i} & \mathbf{j} & \mathbf{k} \\
|
||||||
|
\frac{\partial X}{\partial u} & \frac{\partial Y}{\partial u} & 0 \\
|
||||||
|
\frac{\partial X}{\partial v} & \frac{\partial Y}{\partial v} & 0
|
||||||
|
\end{vmatrix} \]
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>The probability of getting \(k\) heads when flipping \(n\) coins is</h3>
|
||||||
|
|
||||||
|
\[P(E) = {n \choose k} p^k (1-p)^{ n-k} \]
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>An Identity of Ramanujan</h3>
|
||||||
|
|
||||||
|
\[ \frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}-\phi\Bigr) e^{\frac25 \pi}} =
|
||||||
|
1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}}
|
||||||
|
{1+\frac{e^{-8\pi}} {1+\ldots} } } } \]
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>A Rogers-Ramanujan Identity</h3>
|
||||||
|
|
||||||
|
\[ 1 + \frac{q^2}{(1-q)}+\frac{q^6}{(1-q)(1-q^2)}+\cdots =
|
||||||
|
\prod_{j=0}^{\infty}\frac{1}{(1-q^{5j+2})(1-q^{5j+3})}\]
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>Maxwell’s Equations</h3>
|
||||||
|
|
||||||
|
\[ \begin{aligned}
|
||||||
|
\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
|
||||||
|
\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
|
||||||
|
\nabla \cdot \vec{\mathbf{B}} & = 0 \end{aligned}
|
||||||
|
\]
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<section>
|
||||||
|
<h3>The Lorenz Equations</h3>
|
||||||
|
|
||||||
|
<div class="fragment">
|
||||||
|
\[\begin{aligned}
|
||||||
|
\dot{x} & = \sigma(y-x) \\
|
||||||
|
\dot{y} & = \rho x - y - xz \\
|
||||||
|
\dot{z} & = -\beta z + xy
|
||||||
|
\end{aligned} \]
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>The Cauchy-Schwarz Inequality</h3>
|
||||||
|
|
||||||
|
<div class="fragment">
|
||||||
|
\[ \left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right) \]
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>A Cross Product Formula</h3>
|
||||||
|
|
||||||
|
<div class="fragment">
|
||||||
|
\[\mathbf{V}_1 \times \mathbf{V}_2 = \begin{vmatrix}
|
||||||
|
\mathbf{i} & \mathbf{j} & \mathbf{k} \\
|
||||||
|
\frac{\partial X}{\partial u} & \frac{\partial Y}{\partial u} & 0 \\
|
||||||
|
\frac{\partial X}{\partial v} & \frac{\partial Y}{\partial v} & 0
|
||||||
|
\end{vmatrix} \]
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>The probability of getting \(k\) heads when flipping \(n\) coins is</h3>
|
||||||
|
|
||||||
|
<div class="fragment">
|
||||||
|
\[P(E) = {n \choose k} p^k (1-p)^{ n-k} \]
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>An Identity of Ramanujan</h3>
|
||||||
|
|
||||||
|
<div class="fragment">
|
||||||
|
\[ \frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}-\phi\Bigr) e^{\frac25 \pi}} =
|
||||||
|
1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}}
|
||||||
|
{1+\frac{e^{-8\pi}} {1+\ldots} } } } \]
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>A Rogers-Ramanujan Identity</h3>
|
||||||
|
|
||||||
|
<div class="fragment">
|
||||||
|
\[ 1 + \frac{q^2}{(1-q)}+\frac{q^6}{(1-q)(1-q^2)}+\cdots =
|
||||||
|
\prod_{j=0}^{\infty}\frac{1}{(1-q^{5j+2})(1-q^{5j+3})}\]
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>Maxwell’s Equations</h3>
|
||||||
|
|
||||||
|
<div class="fragment">
|
||||||
|
\[ \begin{aligned}
|
||||||
|
\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
|
||||||
|
\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
|
||||||
|
\nabla \cdot \vec{\mathbf{B}} & = 0 \end{aligned}
|
||||||
|
\]
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="../../lib/js/head.min.js"></script>
|
||||||
|
<script src="../../js/reveal.min.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
Reveal.initialize({
|
||||||
|
history: true,
|
||||||
|
transition: 'linear',
|
||||||
|
|
||||||
|
math: {
|
||||||
|
// mathjax: 'http://cdn.mathjax.org/mathjax/latest/MathJax.js',
|
||||||
|
config: 'TeX-AMS_HTML-full'
|
||||||
|
},
|
||||||
|
|
||||||
|
dependencies: [
|
||||||
|
{ src: '../../lib/js/classList.js' },
|
||||||
|
{ src: '../../plugin/math/math.js', async: true }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
|
||||||
<link rel="stylesheet" href="../css/reveal.min.css">
|
<link rel="stylesheet" href="../../css/reveal.min.css">
|
||||||
<link rel="stylesheet" href="../css/theme/serif.css" id="theme">
|
<link rel="stylesheet" href="../../css/theme/serif.css" id="theme">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -79,8 +79,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="../lib/js/head.min.js"></script>
|
<script src="../../lib/js/head.min.js"></script>
|
||||||
<script src="../js/reveal.min.js"></script>
|
<script src="../../js/reveal.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
244
test/qunit-1.12.0.css
Normal file
244
test/qunit-1.12.0.css
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/**
|
||||||
|
* QUnit v1.12.0 - A JavaScript Unit Testing Framework
|
||||||
|
*
|
||||||
|
* http://qunitjs.com
|
||||||
|
*
|
||||||
|
* Copyright 2012 jQuery Foundation and other contributors
|
||||||
|
* Released under the MIT license.
|
||||||
|
* http://jquery.org/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Font Family and Sizes */
|
||||||
|
|
||||||
|
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
|
||||||
|
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||||
|
#qunit-tests { font-size: smaller; }
|
||||||
|
|
||||||
|
|
||||||
|
/** Resets */
|
||||||
|
|
||||||
|
#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Header */
|
||||||
|
|
||||||
|
#qunit-header {
|
||||||
|
padding: 0.5em 0 0.5em 1em;
|
||||||
|
|
||||||
|
color: #8699a4;
|
||||||
|
background-color: #0d3349;
|
||||||
|
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1em;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
-moz-border-radius: 5px 5px 0 0;
|
||||||
|
-webkit-border-top-right-radius: 5px;
|
||||||
|
-webkit-border-top-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #c2ccd1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header a:hover,
|
||||||
|
#qunit-header a:focus {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar label {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 .5em 0 .1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-banner {
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar {
|
||||||
|
padding: 0.5em 0 0.5em 2em;
|
||||||
|
color: #5E740B;
|
||||||
|
background-color: #eee;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-userAgent {
|
||||||
|
padding: 0.5em 0 0.5em 2.5em;
|
||||||
|
background-color: #2b81af;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-modulefilter-container {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tests: Pass/Fail */
|
||||||
|
|
||||||
|
#qunit-tests {
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li {
|
||||||
|
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li strong {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li a {
|
||||||
|
padding: 0.5em;
|
||||||
|
color: #c2ccd1;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
#qunit-tests li a:hover,
|
||||||
|
#qunit-tests li a:focus {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li .runtime {
|
||||||
|
float: right;
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qunit-assert-list {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
border-radius: 5px;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qunit-collapsed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: .2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests th {
|
||||||
|
text-align: right;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 0 .5em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests pre {
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests del {
|
||||||
|
background-color: #e0f2be;
|
||||||
|
color: #374e0c;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests ins {
|
||||||
|
background-color: #ffcaca;
|
||||||
|
color: #500;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Test Counts */
|
||||||
|
|
||||||
|
#qunit-tests b.counts { color: black; }
|
||||||
|
#qunit-tests b.passed { color: #5E740B; }
|
||||||
|
#qunit-tests b.failed { color: #710909; }
|
||||||
|
|
||||||
|
#qunit-tests li li {
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: none;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Passing Styles */
|
||||||
|
|
||||||
|
#qunit-tests li li.pass {
|
||||||
|
color: #3c510c;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: 10px solid #C6E746;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||||
|
#qunit-tests .pass .test-name { color: #366097; }
|
||||||
|
|
||||||
|
#qunit-tests .pass .test-actual,
|
||||||
|
#qunit-tests .pass .test-expected { color: #999999; }
|
||||||
|
|
||||||
|
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||||
|
|
||||||
|
/*** Failing Styles */
|
||||||
|
|
||||||
|
#qunit-tests li li.fail {
|
||||||
|
color: #710909;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: 10px solid #EE5757;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests > li:last-child {
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
-moz-border-radius: 0 0 5px 5px;
|
||||||
|
-webkit-border-bottom-right-radius: 5px;
|
||||||
|
-webkit-border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||||
|
#qunit-tests .fail .test-name,
|
||||||
|
#qunit-tests .fail .module-name { color: #000000; }
|
||||||
|
|
||||||
|
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||||
|
#qunit-tests .fail .test-expected { color: green; }
|
||||||
|
|
||||||
|
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||||
|
|
||||||
|
|
||||||
|
/** Result */
|
||||||
|
|
||||||
|
#qunit-testresult {
|
||||||
|
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||||
|
|
||||||
|
color: #2b81af;
|
||||||
|
background-color: #D2E0E6;
|
||||||
|
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
}
|
||||||
|
#qunit-testresult .module-name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fixture */
|
||||||
|
|
||||||
|
#qunit-fixture {
|
||||||
|
position: absolute;
|
||||||
|
top: -10000px;
|
||||||
|
left: -10000px;
|
||||||
|
width: 1000px;
|
||||||
|
height: 1000px;
|
||||||
|
}
|
2212
test/qunit-1.12.0.js
Normal file
2212
test/qunit-1.12.0.js
Normal file
File diff suppressed because it is too large
Load Diff
62
test/test.html
Normal file
62
test/test.html
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title>reveal.js - Tests</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../css/reveal.min.css">
|
||||||
|
<link rel="stylesheet" href="qunit-1.12.0.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="overflow: auto;">
|
||||||
|
|
||||||
|
<div id="qunit"></div>
|
||||||
|
<div id="qunit-fixture"></div>
|
||||||
|
|
||||||
|
<div class="reveal" style="display: none;">
|
||||||
|
|
||||||
|
<div class="slides">
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>1</h1>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<section>
|
||||||
|
<h1>2.1</h1>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h1>2.2</h1>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h1>2.3</h1>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>4</h1>
|
||||||
|
<ul>
|
||||||
|
<li class="fragment">4.1</li>
|
||||||
|
<li class="fragment">4.2</li>
|
||||||
|
<li class="fragment">4.3</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>4</h1>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="../lib/js/head.min.js"></script>
|
||||||
|
<script src="../js/reveal.min.js"></script>
|
||||||
|
<script src="qunit-1.12.0.js"></script>
|
||||||
|
|
||||||
|
<script src="test.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
353
test/test.js
Normal file
353
test/test.js
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
|
||||||
|
// These tests expect the DOM to contain a presentation
|
||||||
|
// with the following slide structure:
|
||||||
|
//
|
||||||
|
// 1
|
||||||
|
// 2 - Three sub-slides
|
||||||
|
// 3 - Three fragment elements
|
||||||
|
// 4
|
||||||
|
|
||||||
|
|
||||||
|
Reveal.addEventListener( 'ready', function() {
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// API TESTS
|
||||||
|
|
||||||
|
QUnit.module( 'API' );
|
||||||
|
|
||||||
|
test( 'Reveal.isReady', function() {
|
||||||
|
strictEqual( Reveal.isReady(), true, 'returns true' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.isOverview', function() {
|
||||||
|
strictEqual( Reveal.isOverview(), false, 'false by default' );
|
||||||
|
|
||||||
|
Reveal.toggleOverview();
|
||||||
|
strictEqual( Reveal.isOverview(), true, 'true after toggling on' );
|
||||||
|
|
||||||
|
Reveal.toggleOverview();
|
||||||
|
strictEqual( Reveal.isOverview(), false, 'false after toggling off' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.isPaused', function() {
|
||||||
|
strictEqual( Reveal.isPaused(), false, 'false by default' );
|
||||||
|
|
||||||
|
Reveal.togglePause();
|
||||||
|
strictEqual( Reveal.isPaused(), true, 'true after pausing' );
|
||||||
|
|
||||||
|
Reveal.togglePause();
|
||||||
|
strictEqual( Reveal.isPaused(), false, 'false after resuming' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.isFirstSlide', function() {
|
||||||
|
Reveal.slide( 0, 0 );
|
||||||
|
strictEqual( Reveal.isFirstSlide(), true, 'true after Reveal.slide( 0, 0 )' );
|
||||||
|
|
||||||
|
Reveal.slide( 1, 0 );
|
||||||
|
strictEqual( Reveal.isFirstSlide(), false, 'false after Reveal.slide( 1, 0 )' );
|
||||||
|
|
||||||
|
Reveal.slide( 0, 0 );
|
||||||
|
strictEqual( Reveal.isFirstSlide(), true, 'true after Reveal.slide( 0, 0 )' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.isLastSlide', function() {
|
||||||
|
Reveal.slide( 0, 0 );
|
||||||
|
strictEqual( Reveal.isLastSlide(), false, 'false after Reveal.slide( 0, 0 )' );
|
||||||
|
|
||||||
|
var lastSlideIndex = document.querySelectorAll( '.reveal .slides>section' ).length - 1;
|
||||||
|
|
||||||
|
Reveal.slide( lastSlideIndex, 0 );
|
||||||
|
strictEqual( Reveal.isLastSlide(), true, 'true after Reveal.slide( ', 0+ lastSlideIndex +' )' );
|
||||||
|
|
||||||
|
Reveal.slide( 0, 0 );
|
||||||
|
strictEqual( Reveal.isLastSlide(), false, 'false after Reveal.slide( 0, 0 )' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.getIndices', function() {
|
||||||
|
var indices = Reveal.getIndices();
|
||||||
|
|
||||||
|
ok( typeof indices.hasOwnProperty( 'h' ), 'h exists' );
|
||||||
|
ok( typeof indices.hasOwnProperty( 'v' ), 'v exists' );
|
||||||
|
ok( typeof indices.hasOwnProperty( 'f' ), 'f exists' );
|
||||||
|
|
||||||
|
Reveal.slide( 1, 0 );
|
||||||
|
ok( Reveal.getIndices().h === 1 && Reveal.getIndices().v === 0, 'h 1, v 0' );
|
||||||
|
|
||||||
|
Reveal.slide( 1, 2 );
|
||||||
|
ok( Reveal.getIndices().h === 1 && Reveal.getIndices().v === 2, 'h 1, v 2' );
|
||||||
|
|
||||||
|
Reveal.slide( 0, 0 );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.getSlide', function() {
|
||||||
|
var firstSlide = document.querySelector( '.reveal .slides>section:first-child' );
|
||||||
|
|
||||||
|
equal( Reveal.getSlide( 0 ), firstSlide, 'gets correct first slide' );
|
||||||
|
|
||||||
|
strictEqual( Reveal.getSlide( 100 ), undefined, 'returns undefined when slide can\'t be found' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.getPreviousSlide/getCurrentSlide', function() {
|
||||||
|
Reveal.slide( 0, 0 );
|
||||||
|
Reveal.slide( 1, 0 );
|
||||||
|
|
||||||
|
var firstSlide = document.querySelector( '.reveal .slides>section:first-child' );
|
||||||
|
var secondSlide = document.querySelector( '.reveal .slides>section:nth-child(2)>section' );
|
||||||
|
|
||||||
|
equal( Reveal.getPreviousSlide(), firstSlide, 'previous is slide #0' );
|
||||||
|
equal( Reveal.getCurrentSlide(), secondSlide, 'current is slide #1' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.getScale', function() {
|
||||||
|
ok( typeof Reveal.getScale() === 'number', 'has scale' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.getConfig', function() {
|
||||||
|
ok( typeof Reveal.getConfig() === 'object', 'has config' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.configure', function() {
|
||||||
|
strictEqual( Reveal.getConfig().loop, false, '"loop" is false to start with' );
|
||||||
|
|
||||||
|
Reveal.configure({ loop: true });
|
||||||
|
strictEqual( Reveal.getConfig().loop, true, '"loop" has changed to true' );
|
||||||
|
|
||||||
|
Reveal.configure({ loop: false, customTestValue: 1 });
|
||||||
|
strictEqual( Reveal.getConfig().customTestValue, 1, 'supports custom values' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.availableRoutes', function() {
|
||||||
|
Reveal.slide( 0, 0 );
|
||||||
|
deepEqual( Reveal.availableRoutes(), { left: false, up: false, down: false, right: true }, 'correct for first slide' );
|
||||||
|
|
||||||
|
Reveal.slide( 1, 0 );
|
||||||
|
deepEqual( Reveal.availableRoutes(), { left: true, up: false, down: true, right: true }, 'correct for vertical slide' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Reveal.next', function() {
|
||||||
|
Reveal.slide( 0, 0 );
|
||||||
|
|
||||||
|
// Step through the vertical child slides
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 1, v: 0, f: undefined } );
|
||||||
|
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 1, v: 1, f: undefined } );
|
||||||
|
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 1, v: 2, f: undefined } );
|
||||||
|
|
||||||
|
// There's fragments on this slide
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 0 } );
|
||||||
|
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 1 } );
|
||||||
|
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 2 } );
|
||||||
|
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 3 } );
|
||||||
|
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 3, v: 0, f: undefined } );
|
||||||
|
|
||||||
|
// We're at the end, this should have no effect
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 3, v: 0, f: undefined } );
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// FRAGMENT TESTS
|
||||||
|
|
||||||
|
QUnit.module( 'Fragments' );
|
||||||
|
|
||||||
|
test( 'Sliding to fragments', function() {
|
||||||
|
Reveal.slide( 2, 0, 0 );
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 0 }, 'Reveal.slide( 2, 0, 0 )' );
|
||||||
|
|
||||||
|
Reveal.slide( 2, 0, 2 );
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 2 }, 'Reveal.slide( 2, 0, 2 )' );
|
||||||
|
|
||||||
|
Reveal.slide( 2, 0, 1 );
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 1 }, 'Reveal.slide( 2, 0, 1 )' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Stepping through fragments', function() {
|
||||||
|
Reveal.slide( 2, 0, 0 );
|
||||||
|
|
||||||
|
// forwards:
|
||||||
|
|
||||||
|
Reveal.next();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 1 }, 'next() goes to next fragment' );
|
||||||
|
|
||||||
|
Reveal.right();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 2 }, 'right() goes to next fragment' );
|
||||||
|
|
||||||
|
Reveal.down();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 3 }, 'down() goes to next fragment' );
|
||||||
|
|
||||||
|
Reveal.down(); // moves to f #3
|
||||||
|
|
||||||
|
// backwards:
|
||||||
|
|
||||||
|
Reveal.prev();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 2 }, 'prev() goes to prev fragment' );
|
||||||
|
|
||||||
|
Reveal.left();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 1 }, 'left() goes to prev fragment' );
|
||||||
|
|
||||||
|
Reveal.up();
|
||||||
|
deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 0 }, 'left() goes to prev fragment' );
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest( 'fragmentshown event', function() {
|
||||||
|
expect( 2 );
|
||||||
|
|
||||||
|
var _onEvent = function( event ) {
|
||||||
|
ok( true, 'event fired' );
|
||||||
|
}
|
||||||
|
|
||||||
|
Reveal.addEventListener( 'fragmentshown', _onEvent );
|
||||||
|
|
||||||
|
Reveal.slide( 2, 0 );
|
||||||
|
Reveal.slide( 2, 0 ); // should do nothing
|
||||||
|
Reveal.slide( 2, 0, 0 ); // should do nothing
|
||||||
|
Reveal.next();
|
||||||
|
Reveal.next();
|
||||||
|
Reveal.prev(); // shouldn't fire fragmentshown
|
||||||
|
|
||||||
|
start();
|
||||||
|
|
||||||
|
Reveal.removeEventListener( 'fragmentshown', _onEvent );
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest( 'fragmenthidden event', function() {
|
||||||
|
expect( 2 );
|
||||||
|
|
||||||
|
var _onEvent = function( event ) {
|
||||||
|
ok( true, 'event fired' );
|
||||||
|
}
|
||||||
|
|
||||||
|
Reveal.addEventListener( 'fragmenthidden', _onEvent );
|
||||||
|
|
||||||
|
Reveal.slide( 2, 0, 2 );
|
||||||
|
Reveal.slide( 2, 0, 2 ); // should do nothing
|
||||||
|
Reveal.prev();
|
||||||
|
Reveal.prev();
|
||||||
|
Reveal.next(); // shouldn't fire fragmenthidden
|
||||||
|
|
||||||
|
start();
|
||||||
|
|
||||||
|
Reveal.removeEventListener( 'fragmenthidden', _onEvent );
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// CONFIGURATION VALUES
|
||||||
|
|
||||||
|
QUnit.module( 'Configuration' );
|
||||||
|
|
||||||
|
test( 'Controls', function() {
|
||||||
|
var controlsElement = document.querySelector( '.reveal>.controls' );
|
||||||
|
|
||||||
|
Reveal.configure({ controls: false });
|
||||||
|
equal( controlsElement.style.display, 'none', 'controls are hidden' );
|
||||||
|
|
||||||
|
Reveal.configure({ controls: true });
|
||||||
|
equal( controlsElement.style.display, 'block', 'controls are visible' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Progress', function() {
|
||||||
|
var progressElement = document.querySelector( '.reveal>.progress' );
|
||||||
|
|
||||||
|
Reveal.configure({ progress: false });
|
||||||
|
equal( progressElement.style.display, 'none', 'progress are hidden' );
|
||||||
|
|
||||||
|
Reveal.configure({ progress: true });
|
||||||
|
equal( progressElement.style.display, 'block', 'progress are visible' );
|
||||||
|
});
|
||||||
|
|
||||||
|
test( 'Loop', function() {
|
||||||
|
Reveal.configure({ loop: true });
|
||||||
|
|
||||||
|
Reveal.slide( 0, 0 );
|
||||||
|
|
||||||
|
Reveal.left();
|
||||||
|
notEqual( Reveal.getIndices().h, 0, 'looped from start to end' );
|
||||||
|
|
||||||
|
Reveal.right();
|
||||||
|
equal( Reveal.getIndices().h, 0, 'looped from end to start' );
|
||||||
|
|
||||||
|
Reveal.configure({ loop: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// EVENT TESTS
|
||||||
|
|
||||||
|
QUnit.module( 'Events' );
|
||||||
|
|
||||||
|
asyncTest( 'slidechanged', function() {
|
||||||
|
expect( 3 );
|
||||||
|
|
||||||
|
var _onEvent = function( event ) {
|
||||||
|
ok( true, 'event fired' );
|
||||||
|
}
|
||||||
|
|
||||||
|
Reveal.addEventListener( 'slidechanged', _onEvent );
|
||||||
|
|
||||||
|
Reveal.slide( 1, 0 ); // should trigger
|
||||||
|
Reveal.slide( 1, 0 ); // should do nothing
|
||||||
|
Reveal.next(); // should trigger
|
||||||
|
Reveal.slide( 3, 0 ); // should trigger
|
||||||
|
Reveal.next(); // should do nothing
|
||||||
|
|
||||||
|
start();
|
||||||
|
|
||||||
|
Reveal.removeEventListener( 'slidechanged', _onEvent );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest( 'paused', function() {
|
||||||
|
expect( 1 );
|
||||||
|
|
||||||
|
var _onEvent = function( event ) {
|
||||||
|
ok( true, 'event fired' );
|
||||||
|
}
|
||||||
|
|
||||||
|
Reveal.addEventListener( 'paused', _onEvent );
|
||||||
|
|
||||||
|
Reveal.togglePause();
|
||||||
|
Reveal.togglePause();
|
||||||
|
|
||||||
|
start();
|
||||||
|
|
||||||
|
Reveal.removeEventListener( 'paused', _onEvent );
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest( 'resumed', function() {
|
||||||
|
expect( 1 );
|
||||||
|
|
||||||
|
var _onEvent = function( event ) {
|
||||||
|
ok( true, 'event fired' );
|
||||||
|
}
|
||||||
|
|
||||||
|
Reveal.addEventListener( 'resumed', _onEvent );
|
||||||
|
|
||||||
|
Reveal.togglePause();
|
||||||
|
Reveal.togglePause();
|
||||||
|
|
||||||
|
start();
|
||||||
|
|
||||||
|
Reveal.removeEventListener( 'resumed', _onEvent );
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
Reveal.initialize();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user