├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── bower.json
├── code-box
├── code-box.html
└── code-example.html
├── css
├── print
│ ├── paper.css
│ └── pdf.css
├── reveal.css
├── reveal.min.css
└── theme
│ ├── README.md
│ ├── firebase.css
│ ├── firebase.css.map
│ ├── font
│ └── Gotham-Thin.otf
│ ├── source
│ └── firebase.scss
│ └── template
│ ├── mixins.scss
│ ├── settings.scss
│ └── theme.scss
├── full-stack-clients.psd
├── full-stack.png
├── full-stack.psd
├── images
├── HTML5.png
├── Realtime-sync-anim.gif
├── angularjs.png
├── api.png
├── auth.png
├── backbonejs.png
├── backend-reqs (1).gif
├── backend-reqs.gif
├── clients.png
├── clients.psd
├── data-box.png
├── data-box.psd
├── database.png
├── docs-site.png
├── emberjs.png
├── fb-arch.png
├── firebase-logo.png
├── full-stack-clients.png
├── full-stack.png
├── gdocs4.gif
├── hosting-box.png
├── iphone.png
├── laptop.png
├── login-box.png
├── nexus.png
├── offline.png
├── platforms.png
├── react.png
├── realtime-api.png
├── security-box.png
├── server.png
└── simple-api.png
├── index.html
├── js
├── .gitignore
└── reveal.js
├── lib
├── css
│ └── zenburn.css
├── font
│ ├── league_gothic-webfont.eot
│ ├── league_gothic-webfont.svg
│ ├── league_gothic-webfont.ttf
│ ├── league_gothic-webfont.woff
│ └── league_gothic_license
└── js
│ ├── classList.js
│ ├── head.min.js
│ └── html5shiv.js
├── package.json
├── plugin
├── highlight
│ └── highlight.js
├── leap
│ └── leap.js
├── markdown
│ ├── example.html
│ ├── example.md
│ ├── markdown.js
│ └── marked.js
├── math
│ └── math.js
├── multiplex
│ ├── client.js
│ ├── index.js
│ └── master.js
├── notes-server
│ ├── client.js
│ ├── index.js
│ └── notes.html
├── notes
│ ├── notes.html
│ └── notes.js
├── postmessage
│ ├── example.html
│ └── postmessage.js
├── print-pdf
│ └── print-pdf.js
├── remotes
│ └── remotes.js
├── search
│ └── search.js
└── zoom-js
│ └── zoom.js
└── test
├── examples
├── assets
│ ├── image1.png
│ └── image2.png
├── barebones.html
├── embedded-media.html
├── math.html
└── slide-backgrounds.html
├── qunit-1.12.0.css
├── qunit-1.12.0.js
├── test-markdown-element-attributes.html
├── test-markdown-element-attributes.js
├── test-markdown-slide-attributes.html
├── test-markdown-slide-attributes.js
├── test-markdown.html
├── test-markdown.js
├── test.html
└── test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .svn
3 | log/*.log
4 | tmp/**
5 | node_modules/
6 | .sass-cache
7 | firebase.json
8 | bower_components
9 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | /* global module:false */
2 | module.exports = function(grunt) {
3 | var port = grunt.option('port') || 8000;
4 | // Project configuration
5 | grunt.initConfig({
6 | pkg: grunt.file.readJSON('package.json'),
7 | meta: {
8 | banner:
9 | '/*!\n' +
10 | ' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
11 | ' * http://lab.hakim.se/reveal-js\n' +
12 | ' * MIT licensed\n' +
13 | ' *\n' +
14 | ' * Copyright (C) 2014 Hakim El Hattab, http://hakim.se\n' +
15 | ' */'
16 | },
17 |
18 | qunit: {
19 | files: [ 'test/*.html' ]
20 | },
21 |
22 | uglify: {
23 | options: {
24 | banner: '<%= meta.banner %>\n'
25 | },
26 | build: {
27 | src: 'js/reveal.js',
28 | dest: 'js/reveal.min.js'
29 | }
30 | },
31 |
32 | cssmin: {
33 | compress: {
34 | files: {
35 | 'css/reveal.min.css': [ 'css/reveal.css' ]
36 | }
37 | }
38 | },
39 |
40 | sass: {
41 | main: {
42 | files: {
43 | 'css/theme/firebase.css': 'css/theme/source/firebase.scss'
44 | }
45 | }
46 | },
47 |
48 | jshint: {
49 | options: {
50 | curly: false,
51 | eqeqeq: true,
52 | immed: true,
53 | latedef: true,
54 | newcap: true,
55 | noarg: true,
56 | sub: true,
57 | undef: true,
58 | eqnull: true,
59 | browser: true,
60 | expr: true,
61 | globals: {
62 | head: false,
63 | module: false,
64 | console: false,
65 | unescape: false
66 | }
67 | },
68 | files: [ 'Gruntfile.js', 'js/reveal.js' ]
69 | },
70 |
71 | connect: {
72 | server: {
73 | options: {
74 | port: port,
75 | base: '.'
76 | }
77 | }
78 | },
79 |
80 | zip: {
81 | 'reveal-js-presentation.zip': [
82 | 'index.html',
83 | 'css/**',
84 | 'js/**',
85 | 'lib/**',
86 | 'images/**',
87 | 'plugin/**'
88 | ]
89 | },
90 |
91 | watch: {
92 | main: {
93 | files: [ 'Gruntfile.js', 'js/reveal.js', 'css/reveal.css' ],
94 | tasks: 'default'
95 | },
96 | theme: {
97 | files: [ 'css/theme/source/*.scss', 'css/theme/template/*.scss' ],
98 | tasks: 'themes'
99 | }
100 | }
101 |
102 | });
103 |
104 | // Dependencies
105 | grunt.loadNpmTasks( 'grunt-contrib-qunit' );
106 | grunt.loadNpmTasks( 'grunt-contrib-jshint' );
107 | grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
108 | grunt.loadNpmTasks( 'grunt-contrib-uglify' );
109 | grunt.loadNpmTasks( 'grunt-contrib-watch' );
110 | grunt.loadNpmTasks( 'grunt-contrib-sass' );
111 | grunt.loadNpmTasks( 'grunt-contrib-connect' );
112 | grunt.loadNpmTasks( 'grunt-zip' );
113 |
114 | // Default task
115 | grunt.registerTask( 'default', [ 'jshint', 'cssmin', 'uglify', 'qunit' ] );
116 |
117 | // Theme task
118 | grunt.registerTask( 'themes', [ 'sass' ] );
119 |
120 | // Package presentation to archive
121 | grunt.registerTask( 'package', [ 'default', 'zip' ] );
122 |
123 | // Serve presentation locally
124 | grunt.registerTask( 'serve', [ 'connect', 'watch' ] );
125 |
126 | // Run tests
127 | grunt.registerTask( 'test', [ 'jshint', 'qunit' ] );
128 |
129 | };
130 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2014 Hakim El Hattab, http://hakim.se
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Status: Archived
2 | This repository has been archived and is no longer maintained.
3 |
4 | 
5 |
6 | # Intro to Firebase
7 |
8 | This slide deck can be customized to give an introductory talk about Firebase. It is powered by [reveal.js](http://lab.hakim.se/reveal-js), a wonderful and powerful framework for creating HTML presentations.
9 |
10 | ### [Boilerplate Site - https://intro-to-firebase.firebaseapp.com/](https://intro-to-firebase.firebaseapp.com/)
11 |
12 | ## Presentations
13 |
14 | Here are some past presentations made with this desk:
15 |
16 | | Presenter | Event | Date | Contact |
17 | | --------- | ----- | ---- | ------- |
18 | | Mike Koss | [Seattle GDG](https://plus.sandbox.google.com/events/cp5b162fccbtrk4l3ah2blb5je8) | April 20, 2015 | koss@firebase.com |
19 | | Jacob Wenger | GDG Leads Summit | May 27, 2015 | jacob@firebase.com |
20 |
21 | If you end up using this deck, please let us know so we can share the presentation here!
22 |
23 | ## Setup
24 |
25 | This repo uses npm and Grunt to install dependencies, build the deck, run tests, and run a local web
26 | server for the content. To get started, run the following commands:
27 |
28 | ```bash
29 | $ git clone git@github.com:firebase/firebase-intro-presentation.git
30 | $ cd firebase-intro-presentation # go to the firebase-intro directory
31 | $ npm install -g grunt-cli # globally install grunt task runner
32 | $ npm install # install local npm build / test dependencies
33 | $ bower install # uses bower for polymer dependency
34 | ```
35 |
36 | To build the slide deck and run the test suite:
37 |
38 | ```bash
39 | $ grunt
40 | ```
41 |
42 | To open the slide deck using a local web server:
43 |
44 | ```bash
45 | $ grunt serve
46 | ```
47 |
48 | ## Deploy
49 |
50 | Ideally, you'll want to run this on a public website for viewers to see after the presentation. You can use [Firebase Hosting](https://www.firebase.com/docs/hosting/) to deploy this presentation for free!
51 |
52 | You can then view the slide deck at [http://localhost:8000](http://localhost:8000).
53 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Firebase-Deck",
3 | "version": "0.0.5",
4 | "homepage": "https://github.com/davideast/firebase-intro",
5 | "authors": [
6 | "David East "
7 | ],
8 | "description": "An introduction to Firebase Deck",
9 | "main": "index.html",
10 | "keywords": [
11 | "Firebase"
12 | ],
13 | "license": "MIT",
14 | "ignore": [
15 | "**/.*",
16 | "node_modules",
17 | "bower_components",
18 | "test",
19 | "tests"
20 | ],
21 | "dependencies": {
22 | "polymer": "Polymer/polymer#^1.0.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/code-box/code-box.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
18 |
19 |
20 |
21 |
22 |
51 |
--------------------------------------------------------------------------------
/code-box/code-example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
38 |
--------------------------------------------------------------------------------
/css/print/paper.css:
--------------------------------------------------------------------------------
1 | /* Default Print Stylesheet Template
2 | by Rob Glazebrook of CSSnewbie.com
3 | Last Updated: June 4, 2008
4 |
5 | Feel free (nay, compelled) to edit, append, and
6 | manipulate this file as you see fit. */
7 |
8 |
9 | /* SECTION 1: Set default width, margin, float, and
10 | background. This prevents elements from extending
11 | beyond the edge of the printed page, and prevents
12 | unnecessary background images from printing */
13 | body {
14 | background: #fff;
15 | font-size: 13pt;
16 | width: auto;
17 | height: auto;
18 | border: 0;
19 | margin: 0 5%;
20 | padding: 0;
21 | float: none !important;
22 | overflow: visible;
23 | }
24 | html {
25 | background: #fff;
26 | width: auto;
27 | height: auto;
28 | overflow: visible;
29 | }
30 |
31 | /* SECTION 2: Remove any elements not needed in print.
32 | This would include navigation, ads, sidebars, etc. */
33 | .nestedarrow,
34 | .controls,
35 | .reveal .progress,
36 | .reveal.overview,
37 | .fork-reveal,
38 | .share-reveal,
39 | .state-background {
40 | display: none !important;
41 | }
42 |
43 | /* SECTION 3: Set body font face, size, and color.
44 | Consider using a serif font for readability. */
45 | body, p, td, li, div, a {
46 | font-size: 16pt!important;
47 | font-family: Georgia, "Times New Roman", Times, serif !important;
48 | color: #000;
49 | }
50 |
51 | /* SECTION 4: Set heading font face, sizes, and color.
52 | Differentiate your headings from your body text.
53 | Perhaps use a large sans-serif for distinction. */
54 | h1,h2,h3,h4,h5,h6 {
55 | color: #000!important;
56 | height: auto;
57 | line-height: normal;
58 | font-family: Georgia, "Times New Roman", Times, serif !important;
59 | text-shadow: 0 0 0 #000 !important;
60 | text-align: left;
61 | letter-spacing: normal;
62 | }
63 | /* Need to reduce the size of the fonts for printing */
64 | h1 { font-size: 26pt !important; }
65 | h2 { font-size: 22pt !important; }
66 | h3 { font-size: 20pt !important; }
67 | h4 { font-size: 20pt !important; font-variant: small-caps; }
68 | h5 { font-size: 19pt !important; }
69 | h6 { font-size: 18pt !important; font-style: italic; }
70 |
71 | /* SECTION 5: Make hyperlinks more usable.
72 | Ensure links are underlined, and consider appending
73 | the URL to the end of the link for usability. */
74 | a:link,
75 | a:visited {
76 | color: #000 !important;
77 | font-weight: bold;
78 | text-decoration: underline;
79 | }
80 | /*
81 | .reveal a:link:after,
82 | .reveal a:visited:after {
83 | content: " (" attr(href) ") ";
84 | color: #222 !important;
85 | font-size: 90%;
86 | }
87 | */
88 |
89 |
90 | /* SECTION 6: more reveal.js specific additions by @skypanther */
91 | ul, ol, div, p {
92 | visibility: visible;
93 | position: static;
94 | width: auto;
95 | height: auto;
96 | display: block;
97 | overflow: visible;
98 | margin: auto;
99 | text-align: left !important;
100 | }
101 | .reveal .slides {
102 | position: static;
103 | width: auto;
104 | height: auto;
105 |
106 | left: auto;
107 | top: auto;
108 | margin-left: auto;
109 | margin-top: auto;
110 | padding: auto;
111 |
112 | overflow: visible;
113 | display: block;
114 |
115 | text-align: center;
116 | -webkit-perspective: none;
117 | -moz-perspective: none;
118 | -ms-perspective: none;
119 | perspective: none;
120 |
121 | -webkit-perspective-origin: 50% 50%; /* there isn't a none/auto value but 50-50 is the default */
122 | -moz-perspective-origin: 50% 50%;
123 | -ms-perspective-origin: 50% 50%;
124 | perspective-origin: 50% 50%;
125 | }
126 | .reveal .slides>section,
127 | .reveal .slides>section>section {
128 |
129 | visibility: visible !important;
130 | position: static !important;
131 | width: 90% !important;
132 | height: auto !important;
133 | display: block !important;
134 | overflow: visible !important;
135 |
136 | left: 0% !important;
137 | top: 0% !important;
138 | margin-left: 0px !important;
139 | margin-top: 0px !important;
140 | padding: 20px 0px !important;
141 |
142 | opacity: 1 !important;
143 |
144 | -webkit-transform-style: flat !important;
145 | -moz-transform-style: flat !important;
146 | -ms-transform-style: flat !important;
147 | transform-style: flat !important;
148 |
149 | -webkit-transform: none !important;
150 | -moz-transform: none !important;
151 | -ms-transform: none !important;
152 | transform: none !important;
153 | }
154 | .reveal section {
155 | page-break-after: always !important;
156 | display: block !important;
157 | }
158 | .reveal section .fragment {
159 | opacity: 1 !important;
160 | visibility: visible !important;
161 |
162 | -webkit-transform: none !important;
163 | -moz-transform: none !important;
164 | -ms-transform: none !important;
165 | transform: none !important;
166 | }
167 | .reveal section:last-of-type {
168 | page-break-after: avoid !important;
169 | }
170 | .reveal section img {
171 | display: block;
172 | margin: 15px 0px;
173 | background: rgba(255,255,255,1);
174 | border: 1px solid #666;
175 | box-shadow: none;
176 | }
--------------------------------------------------------------------------------
/css/print/pdf.css:
--------------------------------------------------------------------------------
1 | /* Default Print Stylesheet Template
2 | by Rob Glazebrook of CSSnewbie.com
3 | Last Updated: June 4, 2008
4 |
5 | Feel free (nay, compelled) to edit, append, and
6 | manipulate this file as you see fit. */
7 |
8 |
9 | /* SECTION 1: Set default width, margin, float, and
10 | background. This prevents elements from extending
11 | beyond the edge of the printed page, and prevents
12 | unnecessary background images from printing */
13 |
14 | * {
15 | -webkit-print-color-adjust: exact;
16 | }
17 |
18 | body {
19 | font-size: 18pt;
20 | width: 297mm;
21 | height: 229mm;
22 | margin: 0 auto !important;
23 | border: 0;
24 | padding: 0;
25 | float: none !important;
26 | overflow: visible;
27 | }
28 |
29 | html {
30 | width: 100%;
31 | height: 100%;
32 | overflow: visible;
33 | }
34 |
35 | @page {
36 | size: letter landscape;
37 | margin: 0;
38 | }
39 |
40 | /* SECTION 2: Remove any elements not needed in print.
41 | This would include navigation, ads, sidebars, etc. */
42 | .nestedarrow,
43 | .controls,
44 | .reveal .progress,
45 | .reveal.overview,
46 | .fork-reveal,
47 | .share-reveal,
48 | .state-background {
49 | display: none !important;
50 | }
51 |
52 | /* SECTION 3: Set body font face, size, and color.
53 | Consider using a serif font for readability. */
54 | body, p, td, li, div {
55 | font-size: 18pt;
56 | }
57 |
58 | /* SECTION 4: Set heading font face, sizes, and color.
59 | Differentiate your headings from your body text.
60 | Perhaps use a large sans-serif for distinction. */
61 | h1,h2,h3,h4,h5,h6 {
62 | text-shadow: 0 0 0 #000 !important;
63 | }
64 |
65 | /* SECTION 5: Make hyperlinks more usable.
66 | Ensure links are underlined, and consider appending
67 | the URL to the end of the link for usability. */
68 | a:link,
69 | a:visited {
70 | font-weight: normal;
71 | text-decoration: underline;
72 | }
73 |
74 | .reveal pre code {
75 | overflow: hidden !important;
76 | font-family: monospace !important;
77 | }
78 |
79 |
80 | /* SECTION 6: more reveal.js specific additions by @skypanther */
81 | ul, ol, div, p {
82 | visibility: visible;
83 | position: static;
84 | width: auto;
85 | height: auto;
86 | display: block;
87 | overflow: visible;
88 | margin: auto;
89 | }
90 | .reveal {
91 | width: auto !important;
92 | height: auto !important;
93 | overflow: hidden !important;
94 | }
95 | .reveal .slides {
96 | position: static;
97 | width: 100%;
98 | height: auto;
99 |
100 | left: auto;
101 | top: auto;
102 | margin: 0 !important;
103 | padding: 0 !important;
104 |
105 | overflow: visible;
106 | display: block;
107 |
108 | text-align: center;
109 |
110 | -webkit-perspective: none;
111 | -moz-perspective: none;
112 | -ms-perspective: none;
113 | perspective: none;
114 |
115 | -webkit-perspective-origin: 50% 50%; /* there isn't a none/auto value but 50-50 is the default */
116 | -moz-perspective-origin: 50% 50%;
117 | -ms-perspective-origin: 50% 50%;
118 | perspective-origin: 50% 50%;
119 | }
120 | .reveal .slides section {
121 |
122 | page-break-after: always !important;
123 |
124 | visibility: visible !important;
125 | position: relative !important;
126 | width: 100% !important;
127 | height: 229mm !important;
128 | min-height: 229mm !important;
129 | display: block !important;
130 | overflow: hidden !important;
131 |
132 | left: 0 !important;
133 | top: 0 !important;
134 | margin: 0 !important;
135 | padding: 2cm 2cm 0 2cm !important;
136 | box-sizing: border-box !important;
137 |
138 | opacity: 1 !important;
139 |
140 | -webkit-transform-style: flat !important;
141 | -moz-transform-style: flat !important;
142 | -ms-transform-style: flat !important;
143 | transform-style: flat !important;
144 |
145 | -webkit-transform: none !important;
146 | -moz-transform: none !important;
147 | -ms-transform: none !important;
148 | transform: none !important;
149 | }
150 | .reveal section.stack {
151 | margin: 0 !important;
152 | padding: 0 !important;
153 | page-break-after: avoid !important;
154 | height: auto !important;
155 | min-height: auto !important;
156 | }
157 | .reveal .absolute-element {
158 | margin-left: 2.2cm;
159 | margin-top: 1.8cm;
160 | }
161 | .reveal section .fragment {
162 | opacity: 1 !important;
163 | visibility: visible !important;
164 |
165 | -webkit-transform: none !important;
166 | -moz-transform: none !important;
167 | -ms-transform: none !important;
168 | transform: none !important;
169 | }
170 | .reveal section .slide-background {
171 | position: absolute;
172 | top: 0;
173 | left: 0;
174 | width: 100%;
175 | z-index: 0;
176 | }
177 | .reveal section>* {
178 | position: relative;
179 | z-index: 1;
180 | }
181 | .reveal img {
182 | box-shadow: none;
183 | }
184 | .reveal .roll {
185 | overflow: visible;
186 | line-height: 1em;
187 | }
188 | .reveal small a {
189 | font-size: 16pt !important;
190 | }
191 |
--------------------------------------------------------------------------------
/css/theme/README.md:
--------------------------------------------------------------------------------
1 | ## Dependencies
2 |
3 | Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment including the Grunt dependencies installed before proceding: https://github.com/hakimel/reveal.js#full-setup
4 |
5 | You also need to install Ruby and then Sass (with `gem install sass`).
6 |
7 | ## Creating a Theme
8 |
9 | To create your own theme, start by duplicating any ```.scss``` file in [/css/theme/source](https://github.com/hakimel/reveal.js/blob/master/css/theme/source) and adding it to the compilation list in the [Gruntfile](https://github.com/hakimel/reveal.js/blob/master/Gruntfile.js).
10 |
11 | Each theme file does four things in the following order:
12 |
13 | 1. **Include [/css/theme/template/mixins.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/mixins.scss)**
14 | Shared utility functions.
15 |
16 | 2. **Include [/css/theme/template/settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss)**
17 | Declares a set of custom variables that the template file (step 4) expects. Can be overridden in step 3.
18 |
19 | 3. **Override**
20 | This is where you override the default theme. Either by specifying variables (see [settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss) for reference) or by adding full selectors with hardcoded styles.
21 |
22 | 4. **Include [/css/theme/template/theme.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/theme.scss)**
23 | The template theme file which will generate final CSS output based on the currently defined variables.
24 |
25 | When you are done, run `grunt themes` to compile the Sass file to CSS and you are ready to use your new theme.
26 |
--------------------------------------------------------------------------------
/css/theme/firebase.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Gotham Thin';
3 | src: url("font/Gotham-Thin.otf") format("opentype"); }
4 | .text-discs {
5 | color: #fec324 !important; }
6 |
7 | .text-tarheel {
8 | color: #50b1ff !important; }
9 |
10 | .text-rebel {
11 | color: #ff6450 !important; }
12 |
13 | .text-cream {
14 | color: #fffbf3 !important; }
15 |
16 | .slides section > h1 {
17 | margin-bottom: 100px; }
18 | .slides section > h2 {
19 | margin-bottom: 80px; }
20 | .slides section > h3 {
21 | margin-bottom: 80px; }
22 | .slides section > h4 {
23 | margin-bottom: 80px; }
24 | .slides section p:nth-child(even) {
25 | color: #fec324; }
26 | .slides section ol li:nth-child(odd) {
27 | color: #fec324; }
28 | .slides section ol li, .slides section p {
29 | font-size: 38px; }
30 | .slides blockquote {
31 | font-style: normal; }
32 | .slides pre {
33 | box-shadow: none !important; }
34 | .slides pre code {
35 | font-size: 20px;
36 | line-height: 30px;
37 | width: 100%; }
38 | .slides .era-point {
39 | margin-bottom: 40px; }
40 | .slides .api-point {
41 | font-family: Menlo, Courier;
42 | color: #fffbf3 !important;
43 | text-align: left; }
44 | .slides #json-graph {
45 | text-align: left; }
46 | .slides #json-graph h4 {
47 | text-align: left; }
48 | .slides #json-graph h4:nth-child(2) {
49 | margin-left: 140px; }
50 | .slides #json-graph h4:nth-child(3) {
51 | margin-left: 540px; }
52 | .slides #json-graph h4:nth-child(4) {
53 | margin-left: 800px; }
54 |
55 | .framework-logo {
56 | height: 24% !important;
57 | width: 24% !important; }
58 |
59 | .text-large {
60 | font-size: 104px !important;
61 | line-height: 208px !important; }
62 |
63 | .text-medium {
64 | font-size: 62px !important;
65 | line-height: 124px !important; }
66 |
67 | .text-small {
68 | font-size: 42px !important; }
69 |
70 | #era {
71 | padding: 15px;
72 | text-transform: uppercase;
73 | font-size: 16px; }
74 |
75 | img.no-style {
76 | background: transparent !important;
77 | border: none !important;
78 | box-shadow: none !important; }
79 |
80 | img.white-bg {
81 | background: #f0f0f0 !important;
82 | padding: 10px !important; }
83 |
84 | .button {
85 | border: none !important;
86 | text-align: left !important;
87 | display: inline-block;
88 | line-height: 32px;
89 | padding: 0 16px;
90 | font-size: 14px;
91 | font-weight: 400;
92 | border-radius: 3px;
93 | text-decoration: none;
94 | text-transform: uppercase;
95 | overflow: hidden; }
96 |
97 | .code-box {
98 | border-radius: 4px;
99 | background: #191919;
100 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
101 | margin-bottom: 8px; }
102 |
103 | .code-box header {
104 | background: #191919;
105 | color: #FFF;
106 | padding: 8px;
107 | border-radius: 4px 4px 0 0;
108 | text-align: left; }
109 |
110 | .code-box nav button {
111 | border: none;
112 | line-height: 24px;
113 | padding: 12px 24px;
114 | margin-right: 8px;
115 | font-size: 16px;
116 | background: #3f3f3f;
117 | color: #DCDCDC;
118 | font-weight: 500;
119 | text-transform: none;
120 | font-family: 'Gotham Thin';
121 | cursor: pointer;
122 | outline: none; }
123 |
124 | .code-box nav button:active {
125 | background: #353535;
126 | color: #DADADA; }
127 |
128 | .code-box nav button.is-selected, .code-box nav button.selected {
129 | background: #353535;
130 | color: #DADADA; }
131 |
132 | .code-box .prettyprint {
133 | box-shadow: none;
134 | margin: 0; }
135 |
136 | .active {
137 | display: block; }
138 |
139 | .code-box-examples pre {
140 | display: none; }
141 |
142 | .code-box-examples pre.isActive {
143 | display: block; }
144 |
145 | code {
146 | display: none;
147 | margin: 8px; }
148 |
149 | .reveal pre {
150 | margin: 0;
151 | width: 99%; }
152 |
153 | .reveal pre code {
154 | max-height: 500px; }
155 |
156 | section.present.hasCode {
157 | height: 500px; }
158 |
159 | pre.code-example.isActive code.code-example {
160 | position: absolute !important;
161 | top: 0 !important; }
162 |
163 | /*********************************************
164 | * GLOBAL STYLES
165 | *********************************************/
166 | body {
167 | background: #322f31;
168 | background-color: #322f31; }
169 |
170 | .reveal {
171 | font-family: "Gotham Thin", Arial;
172 | font-size: 32px;
173 | font-weight: normal;
174 | letter-spacing: -0.02em;
175 | color: #fffbf3; }
176 |
177 | ::selection {
178 | color: #fff;
179 | background: #50b1ff;
180 | text-shadow: none; }
181 |
182 | /*********************************************
183 | * HEADERS
184 | *********************************************/
185 | .reveal h1,
186 | .reveal h2,
187 | .reveal h3,
188 | .reveal h4,
189 | .reveal h5,
190 | .reveal h6 {
191 | margin: 0 0 20px 0;
192 | color: #fffbf3;
193 | font-family: "Gotham Thin", Arial;
194 | line-height: 1em;
195 | letter-spacing: 0.02em;
196 | text-transform: uppercase;
197 | text-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2);
198 | font-weight: bold; }
199 |
200 | .reveal h1 {
201 | text-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2); }
202 |
203 | /*********************************************
204 | * LINKS
205 | *********************************************/
206 | .reveal a:not(.image) {
207 | color: #fec324;
208 | text-decoration: none;
209 | -webkit-transition: color .15s ease;
210 | -moz-transition: color .15s ease;
211 | -ms-transition: color .15s ease;
212 | -o-transition: color .15s ease;
213 | transition: color .15s ease; }
214 |
215 | .reveal a:not(.image):hover {
216 | color: #50b1ff;
217 | text-shadow: none;
218 | border: none; }
219 |
220 | .reveal .roll span:after {
221 | color: #fff;
222 | background: #d59b01; }
223 |
224 | /*********************************************
225 | * IMAGES
226 | *********************************************/
227 | .reveal section img {
228 | margin: 15px 0px;
229 | background: rgba(255, 255, 255, 0.12);
230 | border: 4px solid #fffbf3;
231 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
232 | -webkit-transition: all .2s linear;
233 | -moz-transition: all .2s linear;
234 | -ms-transition: all .2s linear;
235 | -o-transition: all .2s linear;
236 | transition: all .2s linear; }
237 |
238 | .reveal a:hover img {
239 | background: rgba(255, 255, 255, 0.2);
240 | border-color: #fec324;
241 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
242 |
243 | /*********************************************
244 | * NAVIGATION CONTROLS
245 | *********************************************/
246 | .reveal .controls div.navigate-left,
247 | .reveal .controls div.navigate-left.enabled {
248 | border-right-color: #fec324; }
249 |
250 | .reveal .controls div.navigate-right,
251 | .reveal .controls div.navigate-right.enabled {
252 | border-left-color: #fec324; }
253 |
254 | .reveal .controls div.navigate-up,
255 | .reveal .controls div.navigate-up.enabled {
256 | border-bottom-color: #fec324; }
257 |
258 | .reveal .controls div.navigate-down,
259 | .reveal .controls div.navigate-down.enabled {
260 | border-top-color: #fec324; }
261 |
262 | .reveal .controls div.navigate-left.enabled:hover {
263 | border-right-color: #50b1ff; }
264 |
265 | .reveal .controls div.navigate-right.enabled:hover {
266 | border-left-color: #50b1ff; }
267 |
268 | .reveal .controls div.navigate-up.enabled:hover {
269 | border-bottom-color: #50b1ff; }
270 |
271 | .reveal .controls div.navigate-down.enabled:hover {
272 | border-top-color: #50b1ff; }
273 |
274 | /*********************************************
275 | * PROGRESS BAR
276 | *********************************************/
277 | .reveal .progress {
278 | background: rgba(0, 0, 0, 0.2); }
279 |
280 | .reveal .progress span {
281 | background: #fec324;
282 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
283 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
284 | -ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
285 | -o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
286 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
287 |
288 | /*********************************************
289 | * SLIDE NUMBER
290 | *********************************************/
291 | .reveal .slide-number {
292 | color: #fec324; }
293 |
294 | /*# sourceMappingURL=firebase.css.map */
295 |
--------------------------------------------------------------------------------
/css/theme/firebase.css.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "mappings": "AAMA,UAGC;EAFC,WAAW,EAAE,aAAa;EAC1B,GAAG,EAAE,8CAA8C;AAuErD,WAAY;EACV,KAAK,EAAE,kBAAiB;;AAG1B,aAAc;EACZ,KAAK,EAAE,kBAAmB;;AAG5B,WAAY;EACV,KAAK,EAAE,kBAAiB;;AAG1B,WAAY;EACV,KAAK,EAAE,kBAAiB;;AAKtB,oBAAK;EACH,aAAa,EAAE,KAAK;AAEtB,oBAAI;EACF,aAAa,EAAE,IAAI;AAErB,oBAAI;EACF,aAAa,EAAE,IAAI;AAErB,oBAAI;EACF,aAAa,EAAE,IAAI;AAErB,iCAAkB;EAChB,KAAK,EA5CC,OAAM;AA8Cd,oCAAqB;EACnB,KAAK,EA/CC,OAAM;AAiDd,wCAAS;EACP,SAAS,EAAE,IAAI;AAInB,kBAAW;EACT,UAAU,EAAE,MAAM;AAGpB,WAAI;EACF,UAAU,EAAE,eAAe;AAG7B,gBAAS;EACP,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,IAAI;EACjB,KAAK,EAAE,IAAI;AAGb,kBAAW;EACT,aAAa,EAAE,IAAI;AAGrB,kBAAW;EACT,WAAW,EAAE,cAAc;EAC3B,KAAK,EAAE,kBAAiB;EACxB,UAAU,EAAE,IAAI;AAGlB,mBAAY;EACV,UAAU,EAAE,IAAI;EAChB,sBAAG;IACD,UAAU,EAAE,IAAI;EAElB,mCAAgB;IACd,WAAW,EAAE,KAAK;EAEpB,mCAAgB;IACd,WAAW,EAAE,KAAK;EAEpB,mCAAgB;IACd,WAAW,EAAE,KAAK;;AAKxB,eAAgB;EACd,MAAM,EAAE,cAAc;EACtB,KAAK,EAAE,cAAc;;AAGvB,WAAY;EACV,SAAS,EAAE,gBAAgB;EAC3B,WAAW,EAAE,gBAAgB;;AAG/B,YAAa;EACX,SAAS,EAAE,eAAe;EAC1B,WAAW,EAAE,gBAAgB;;AAG/B,WAAY;EACV,SAAS,EAAE,eAAe;;AAG5B,IAAK;EACH,OAAO,EAAE,IAAI;EACb,cAAc,EAAE,SAAS;EACzB,SAAS,EAAE,IAAI;;AAGjB,YAAa;EACX,UAAU,EAAE,sBAAsB;EAClC,MAAM,EAAE,eAAe;EACvB,UAAU,EAAE,eAAe;;AAG7B,YAAa;EACX,UAAU,EAAE,kBAAkB;EAC9B,OAAO,EAAE,eAAe;;AAIxB,OAAQ;EACN,MAAM,EAAE,eAAe;EACvB,UAAU,EAAE,eAAe;EAC3B,OAAO,EAAE,YAAY;EACrB,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,MAAM;EACf,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,GAAG;EAChB,aAAa,EAAE,GAAG;EAClB,eAAe,EAAE,IAAI;EACrB,cAAc,EAAE,SAAS;EACzB,QAAQ,EAAE,MAAM;;AAGpB,SAAU;EACN,aAAa,EAAE,GAAG;EAClB,UAAU,EAAE,OAAO;EACnB,UAAU,EAAE,4BAAyB;EACrC,aAAa,EAAE,GAAG;;AAGtB,gBAAiB;EACb,UAAU,EAAE,OAAO;EACnB,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,GAAG;EACZ,aAAa,EAAE,WAAW;EAC1B,UAAU,EAAE,IAAI;;AAGpB,oBAAqB;EACnB,MAAM,EAAE,IAAI;EACZ,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,SAAS;EAClB,YAAY,EAAE,GAAG;EACjB,SAAS,EAAE,IAAI;EACf,UAAU,EAAE,OAAO;EACnB,KAAK,EAAE,OAAO;EACd,WAAW,EAAE,GAAG;EAChB,cAAc,EAAE,IAAI;EACpB,WAAW,EAAE,aAAa;EAC1B,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,IAAI;;AAGf,2BAA4B;EAC1B,UAAU,EAAE,OAAO;EACnB,KAAK,EAAE,OAAO;;AAGhB,+DAA+D;EAC7D,UAAU,EAAE,OAAO;EACnB,KAAK,EAAE,OAAO;;AAGhB,sBAAuB;EACnB,UAAU,EAAE,IAAI;EAChB,MAAM,EAAE,CAAC;;AAGb,OAAQ;EACN,OAAO,EAAE,KAAK;;AAGhB,sBAAuB;EACrB,OAAO,EAAE,IAAI;;AAGf,+BAAgC;EAC9B,OAAO,EAAE,KAAK;;AAGhB,IAAK;EACH,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,GAAG;;AAGb,WAAY;EACV,MAAM,EAAE,CAAC;EACT,KAAK,EAAE,GAAG;;AAGZ,gBAAiB;EACf,UAAU,EAAE,KAAK;;AAGnB,uBAAwB;EACtB,MAAM,EAAE,KAAK;;AAIb,2CAAkB;EAChB,QAAQ,EAAE,mBAAmB;EAC7B,GAAG,EAAE,YAAY;;;;;AC5RrB,IAAK;EDsEH,UAAU,EA7BM,OAAM;ECvCvB,gBAAgB,EDuCC,OAAM;;ACpCxB,OAAQ;EACP,WAAW,ED4CE,oBAAK;EC3ClB,SAAS,EDsCK,IAAI;ECrClB,WAAW,EAAE,MAAM;EACnB,cAAc,EAAE,OAAO;EACvB,KAAK,EDyCS,OAAM;;ACtCrB,WAAY;EACX,KAAK,EDmDW,IAAI;EClDpB,UAAU,EDiDgB,OAAQ;EChDlC,WAAW,EAAE,IAAI;;;;;AAOlB;;;;;UAKW;EACV,MAAM,EDoBS,UAAU;ECnBzB,KAAK,EDqBS,OAAM;ECnBpB,WAAW,EDkBE,oBAAK;ECjBlB,WAAW,EDmBQ,GAAG;EClBtB,cAAc,EDmBQ,MAAM;ECjB5B,cAAc,EDkBQ,SAAS;ECjB/B,WAAW,EDmBS,8BAAkB;EClBrC,WAAW,EDmBO,IAAI;;AChBxB,UAAW;EACV,WAAW,EDcS,8BAAkB;;;;;ACNvC,qBAAsB;EACrB,KAAK,EDSM,OAAM;ECRjB,eAAe,EAAE,IAAI;EAErB,kBAAkB,EAAE,eAAe;EAChC,eAAe,EAAE,eAAe;EAC/B,cAAc,EAAE,eAAe;EAC9B,aAAa,EAAE,eAAe;EAC3B,UAAU,EAAE,eAAe;;AAEnC,2BAA4B;EAC3B,KAAK,EDGoB,OAAQ;ECDjC,WAAW,EAAE,IAAI;EACjB,MAAM,EAAE,IAAI;;AAGd,wBAAyB;EACxB,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,OAAyB;;;;;AAQtC,mBAAoB;EACnB,MAAM,EAAE,QAAQ;EAChB,UAAU,EAAE,yBAAsB;EAClC,MAAM,EAAE,iBAAoB;EAE5B,UAAU,EAAE,4BAA4B;EAExC,kBAAkB,EAAE,cAAc;EAC/B,eAAe,EAAE,cAAc;EAC9B,cAAc,EAAE,cAAc;EAC7B,aAAa,EAAE,cAAc;EAC1B,UAAU,EAAE,cAAc;;AAGlC,mBAAoB;EACnB,UAAU,EAAE,wBAAqB;EACjC,YAAY,EDjCF,OAAM;ECmChB,UAAU,EAAE,4BAA4B;;;;;AAQ1C;2CAC4C;EAC3C,kBAAkB,ED7CP,OAAM;;ACgDlB;4CAC6C;EAC5C,iBAAiB,EDlDN,OAAM;;ACqDlB;yCAC0C;EACzC,mBAAmB,EDvDR,OAAM;;AC0DlB;2CAC4C;EAC3C,gBAAgB,ED5DL,OAAM;;AC+DlB,iDAAkD;EACjD,kBAAkB,ED5DQ,OAAQ;;AC+DnC,kDAAmD;EAClD,iBAAiB,EDhES,OAAQ;;ACmEnC,+CAAgD;EAC/C,mBAAmB,EDpEO,OAAQ;;ACuEnC,iDAAkD;EACjD,gBAAgB,EDxEU,OAAQ;;;;;ACgFnC,iBAAkB;EACjB,UAAU,EAAE,kBAAe;;AAE3B,sBAAuB;EACtB,UAAU,EDxFA,OAAM;EC0FhB,kBAAkB,EAAE,iDAAoD;EACrE,eAAe,EAAE,iDAAoD;EACpE,cAAc,EAAE,iDAAoD;EACnE,aAAa,EAAE,iDAAoD;EAChE,UAAU,EAAE,iDAAoD;;;;;AAM1E,qBAAsB;EACpB,KAAK,EDrGK,OAAM",
4 | "sources": ["source/firebase.scss","template/theme.scss"],
5 | "names": [],
6 | "file": "firebase.css"
7 | }
8 |
--------------------------------------------------------------------------------
/css/theme/font/Gotham-Thin.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/css/theme/font/Gotham-Thin.otf
--------------------------------------------------------------------------------
/css/theme/source/firebase.scss:
--------------------------------------------------------------------------------
1 |
2 | // Default mixins and settings -----------------
3 | @import "../template/mixins";
4 | @import "../template/settings";
5 | // ---------------------------------------------
6 |
7 | @font-face {
8 | font-family: 'Gotham Thin';
9 | src: url("font/Gotham-Thin.otf") format("opentype");
10 | }
11 |
12 | $white: #ffffff;
13 | $black: #000000;
14 |
15 | $azucar: #185689;
16 | $darkcar: #1b5e96;
17 | $darkercar: #154a75;
18 | $bumble-bee: #ffd641;
19 |
20 | $slate: #322f31;
21 | $shale: #1d1d1e;
22 | $discs: #fec324;
23 | $keylime: #acfd5b;
24 | $tarheel: #50b1ff;
25 | $rebel: #ff6450;
26 | $pride: #b650ff;
27 | $cream: #fffbf3;
28 |
29 | $slate-dark: #154a75;
30 | $bumble-mid: #fedd7b;
31 | $bumble-dark: #c5a530;
32 |
33 |
34 | $font: 'Gotham Thin', Arial;
35 | $mainFont: "proxima-nova",sans-serif;
36 |
37 | $brand-primary: $tarheel;
38 | $brand-warning: $discs;
39 | $brand-danger: $rebel;
40 |
41 | ///////////////////////////////////////////
42 |
43 |
44 | // Base settings for all themes that can optionally be
45 | // overridden by the super-theme
46 |
47 | // Background of the presentation
48 | $backgroundColor: $slate;
49 |
50 | // Primary/body text
51 | $mainFont: $font;
52 | $mainFontSize: 32px;
53 | $mainColor: $cream;
54 |
55 | // Headings
56 | $headingMargin: 0 0 20px 0;
57 | $headingFont: $font;
58 | $headingColor: $cream;
59 | $headingLineHeight: 1em;
60 | $headingLetterSpacing: 0.02em;
61 | $headingTextTransform: uppercase;
62 | $headingTextShadow: 0px 0px 6px rgba(0,0,0,0.2);
63 | $heading1TextShadow: $headingTextShadow;
64 | $headingFontWeight: bold;
65 |
66 | // Links and actions
67 | $linkColor: $discs;
68 | $linkColorHover: $tarheel;
69 |
70 | // Text selection
71 | $selectionBackgroundColor: $tarheel;
72 | $selectionColor: #fff;
73 |
74 | // Generates the presentation background, can be overridden
75 | // to return a background image or gradient
76 | @mixin bodyBackground() {
77 | background: $backgroundColor;
78 | }
79 |
80 | .text-discs {
81 | color: $discs !important;
82 | }
83 |
84 | .text-tarheel {
85 | color: $tarheel !important;
86 | }
87 |
88 | .text-rebel {
89 | color: $rebel !important;
90 | }
91 |
92 | .text-cream {
93 | color: $cream !important;
94 | }
95 |
96 | .slides {
97 | section {
98 | > h1 {
99 | margin-bottom: 100px;
100 | }
101 | >h2 {
102 | margin-bottom: 80px;
103 | }
104 | >h3 {
105 | margin-bottom: 80px;
106 | }
107 | >h4 {
108 | margin-bottom: 80px;
109 | }
110 | p:nth-child(even) {
111 | color: $discs;
112 | }
113 | ol li:nth-child(odd) {
114 | color: $discs;
115 | }
116 | ol li, p {
117 | font-size: 38px;
118 | }
119 | }
120 |
121 | blockquote {
122 | font-style: normal;
123 | }
124 |
125 | pre {
126 | box-shadow: none !important;
127 | }
128 |
129 | pre code {
130 | font-size: 20px;
131 | line-height: 30px;
132 | width: 100%;
133 | }
134 |
135 | .era-point {
136 | margin-bottom: 40px;
137 | }
138 |
139 | .api-point {
140 | font-family: Menlo, Courier;
141 | color: $cream !important;
142 | text-align: left;
143 | }
144 |
145 | #json-graph {
146 | text-align: left;
147 | h4 {
148 | text-align: left;
149 | }
150 | h4:nth-child(2) {
151 | margin-left: 140px;
152 | }
153 | h4:nth-child(3) {
154 | margin-left: 540px;
155 | }
156 | h4:nth-child(4) {
157 | margin-left: 800px;
158 | }
159 | }
160 | }
161 |
162 | .framework-logo {
163 | height: 24% !important;
164 | width: 24% !important;
165 | }
166 |
167 | .text-large {
168 | font-size: 104px !important;
169 | line-height: 208px !important;
170 | }
171 |
172 | .text-medium {
173 | font-size: 62px !important;
174 | line-height: 124px !important;
175 | }
176 |
177 | .text-small {
178 | font-size: 42px !important;
179 | }
180 |
181 | #era {
182 | padding: 15px;
183 | text-transform: uppercase;
184 | font-size: 16px;
185 | }
186 |
187 | img.no-style {
188 | background: transparent !important;
189 | border: none !important;
190 | box-shadow: none !important;
191 | }
192 |
193 | img.white-bg {
194 | background: #f0f0f0 !important;
195 | padding: 10px !important;
196 | }
197 |
198 | // code-box ------------------------------
199 | .button {
200 | border: none !important;
201 | text-align: left !important;
202 | display: inline-block;
203 | line-height: 32px;
204 | padding: 0 16px;
205 | font-size: 14px;
206 | font-weight: 400;
207 | border-radius: 3px;
208 | text-decoration: none;
209 | text-transform: uppercase;
210 | overflow: hidden;
211 | }
212 |
213 | .code-box {
214 | border-radius: 4px;
215 | background: #191919;
216 | box-shadow: 0 2px 5px rgba(0,0,0,0.3);
217 | margin-bottom: 8px;
218 | }
219 |
220 | .code-box header {
221 | background: #191919;
222 | color: #FFF;
223 | padding: 8px;
224 | border-radius: 4px 4px 0 0;
225 | text-align: left;
226 | }
227 |
228 | .code-box nav button {
229 | border: none;
230 | line-height: 24px;
231 | padding: 12px 24px;
232 | margin-right: 8px;
233 | font-size: 16px;
234 | background: #3f3f3f;
235 | color: #DCDCDC;
236 | font-weight: 500;
237 | text-transform: none;
238 | font-family: 'Gotham Thin';
239 | cursor: pointer;
240 | outline: none;
241 | }
242 |
243 | .code-box nav button:active {
244 | background: #353535;
245 | color: #DADADA;
246 | }
247 |
248 | .code-box nav button.is-selected,.code-box nav button.selected {
249 | background: #353535;
250 | color: #DADADA;
251 | }
252 |
253 | .code-box .prettyprint {
254 | box-shadow: none;
255 | margin: 0
256 | }
257 |
258 | .active {
259 | display: block;
260 | }
261 |
262 | .code-box-examples pre {
263 | display: none;
264 | }
265 |
266 | .code-box-examples pre.isActive {
267 | display: block;
268 | }
269 |
270 | code {
271 | display: none;
272 | margin: 8px;
273 | }
274 |
275 | .reveal pre {
276 | margin: 0;
277 | width: 99%;
278 | }
279 |
280 | .reveal pre code {
281 | max-height: 500px;
282 | }
283 |
284 | section.present.hasCode {
285 | height: 500px;
286 | }
287 |
288 | pre.code-example.isActive {
289 | code.code-example {
290 | position: absolute !important;
291 | top: 0 !important;
292 | }
293 | }
294 |
295 | // Theme template ------------------------------
296 | @import "../template/theme";
297 | // ---------------------------------------------
298 |
--------------------------------------------------------------------------------
/css/theme/template/mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin vertical-gradient( $top, $bottom ) {
2 | background: $top;
3 | background: -moz-linear-gradient( top, $top 0%, $bottom 100% );
4 | background: -webkit-gradient( linear, left top, left bottom, color-stop(0%,$top), color-stop(100%,$bottom) );
5 | background: -webkit-linear-gradient( top, $top 0%, $bottom 100% );
6 | background: -o-linear-gradient( top, $top 0%, $bottom 100% );
7 | background: -ms-linear-gradient( top, $top 0%, $bottom 100% );
8 | background: linear-gradient( top, $top 0%, $bottom 100% );
9 | }
10 |
11 | @mixin horizontal-gradient( $top, $bottom ) {
12 | background: $top;
13 | background: -moz-linear-gradient( left, $top 0%, $bottom 100% );
14 | background: -webkit-gradient( linear, left top, right top, color-stop(0%,$top), color-stop(100%,$bottom) );
15 | background: -webkit-linear-gradient( left, $top 0%, $bottom 100% );
16 | background: -o-linear-gradient( left, $top 0%, $bottom 100% );
17 | background: -ms-linear-gradient( left, $top 0%, $bottom 100% );
18 | background: linear-gradient( left, $top 0%, $bottom 100% );
19 | }
20 |
21 | @mixin radial-gradient( $outer, $inner, $type: circle ) {
22 | background: $outer;
23 | background: -moz-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
24 | background: -webkit-gradient( radial, center center, 0px, center center, 100%, color-stop(0%,$inner), color-stop(100%,$outer) );
25 | background: -webkit-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
26 | background: -o-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
27 | background: -ms-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
28 | background: radial-gradient( center, $type cover, $inner 0%, $outer 100% );
29 | }
--------------------------------------------------------------------------------
/css/theme/template/settings.scss:
--------------------------------------------------------------------------------
1 | // Base settings for all themes that can optionally be
2 | // overridden by the super-theme
3 |
4 | // Background of the presentation
5 | $backgroundColor: #2b2b2b;
6 |
7 | // Primary/body text
8 | $mainFont: 'Lato', sans-serif;
9 | $mainFontSize: 36px;
10 | $mainColor: #eee;
11 |
12 | // Headings
13 | $headingMargin: 0 0 20px 0;
14 | $headingFont: 'League Gothic', Impact, sans-serif;
15 | $headingColor: #eee;
16 | $headingLineHeight: 0.9em;
17 | $headingLetterSpacing: 0.02em;
18 | $headingTextTransform: uppercase;
19 | $headingTextShadow: 0px 0px 6px rgba(0,0,0,0.2);
20 | $heading1TextShadow: $headingTextShadow;
21 | $headingFontWeight: normal;
22 |
23 | // Links and actions
24 | $linkColor: #13DAEC;
25 | $linkColorHover: lighten( $linkColor, 20% );
26 |
27 | // Text selection
28 | $selectionBackgroundColor: #FF5E99;
29 | $selectionColor: #fff;
30 |
31 | // Generates the presentation background, can be overridden
32 | // to return a background image or gradient
33 | @mixin bodyBackground() {
34 | background: $backgroundColor;
35 | }
36 |
--------------------------------------------------------------------------------
/css/theme/template/theme.scss:
--------------------------------------------------------------------------------
1 | // Base theme template for reveal.js
2 |
3 | /*********************************************
4 | * GLOBAL STYLES
5 | *********************************************/
6 |
7 | body {
8 | @include bodyBackground();
9 | background-color: $backgroundColor;
10 | }
11 |
12 | .reveal {
13 | font-family: $mainFont;
14 | font-size: $mainFontSize;
15 | font-weight: normal;
16 | letter-spacing: -0.02em;
17 | color: $mainColor;
18 | }
19 |
20 | ::selection {
21 | color: $selectionColor;
22 | background: $selectionBackgroundColor;
23 | text-shadow: none;
24 | }
25 |
26 | /*********************************************
27 | * HEADERS
28 | *********************************************/
29 |
30 | .reveal h1,
31 | .reveal h2,
32 | .reveal h3,
33 | .reveal h4,
34 | .reveal h5,
35 | .reveal h6 {
36 | margin: $headingMargin;
37 | color: $headingColor;
38 |
39 | font-family: $headingFont;
40 | line-height: $headingLineHeight;
41 | letter-spacing: $headingLetterSpacing;
42 |
43 | text-transform: $headingTextTransform;
44 | text-shadow: $headingTextShadow;
45 | font-weight: $headingFontWeight;
46 | }
47 |
48 | .reveal h1 {
49 | text-shadow: $heading1TextShadow;
50 | }
51 |
52 |
53 | /*********************************************
54 | * LINKS
55 | *********************************************/
56 |
57 | .reveal a:not(.image) {
58 | color: $linkColor;
59 | text-decoration: none;
60 |
61 | -webkit-transition: color .15s ease;
62 | -moz-transition: color .15s ease;
63 | -ms-transition: color .15s ease;
64 | -o-transition: color .15s ease;
65 | transition: color .15s ease;
66 | }
67 | .reveal a:not(.image):hover {
68 | color: $linkColorHover;
69 |
70 | text-shadow: none;
71 | border: none;
72 | }
73 |
74 | .reveal .roll span:after {
75 | color: #fff;
76 | background: darken( $linkColor, 15% );
77 | }
78 |
79 |
80 | /*********************************************
81 | * IMAGES
82 | *********************************************/
83 |
84 | .reveal section img {
85 | margin: 15px 0px;
86 | background: rgba(255,255,255,0.12);
87 | border: 4px solid $mainColor;
88 |
89 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
90 |
91 | -webkit-transition: all .2s linear;
92 | -moz-transition: all .2s linear;
93 | -ms-transition: all .2s linear;
94 | -o-transition: all .2s linear;
95 | transition: all .2s linear;
96 | }
97 |
98 | .reveal a:hover img {
99 | background: rgba(255,255,255,0.2);
100 | border-color: $linkColor;
101 |
102 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
103 | }
104 |
105 |
106 | /*********************************************
107 | * NAVIGATION CONTROLS
108 | *********************************************/
109 |
110 | .reveal .controls div.navigate-left,
111 | .reveal .controls div.navigate-left.enabled {
112 | border-right-color: $linkColor;
113 | }
114 |
115 | .reveal .controls div.navigate-right,
116 | .reveal .controls div.navigate-right.enabled {
117 | border-left-color: $linkColor;
118 | }
119 |
120 | .reveal .controls div.navigate-up,
121 | .reveal .controls div.navigate-up.enabled {
122 | border-bottom-color: $linkColor;
123 | }
124 |
125 | .reveal .controls div.navigate-down,
126 | .reveal .controls div.navigate-down.enabled {
127 | border-top-color: $linkColor;
128 | }
129 |
130 | .reveal .controls div.navigate-left.enabled:hover {
131 | border-right-color: $linkColorHover;
132 | }
133 |
134 | .reveal .controls div.navigate-right.enabled:hover {
135 | border-left-color: $linkColorHover;
136 | }
137 |
138 | .reveal .controls div.navigate-up.enabled:hover {
139 | border-bottom-color: $linkColorHover;
140 | }
141 |
142 | .reveal .controls div.navigate-down.enabled:hover {
143 | border-top-color: $linkColorHover;
144 | }
145 |
146 |
147 | /*********************************************
148 | * PROGRESS BAR
149 | *********************************************/
150 |
151 | .reveal .progress {
152 | background: rgba(0,0,0,0.2);
153 | }
154 | .reveal .progress span {
155 | background: $linkColor;
156 |
157 | -webkit-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
158 | -moz-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
159 | -ms-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
160 | -o-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
161 | transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
162 | }
163 |
164 | /*********************************************
165 | * SLIDE NUMBER
166 | *********************************************/
167 | .reveal .slide-number {
168 | color: $linkColor;
169 | }
170 |
--------------------------------------------------------------------------------
/full-stack-clients.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/full-stack-clients.psd
--------------------------------------------------------------------------------
/full-stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/full-stack.png
--------------------------------------------------------------------------------
/full-stack.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/full-stack.psd
--------------------------------------------------------------------------------
/images/HTML5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/HTML5.png
--------------------------------------------------------------------------------
/images/Realtime-sync-anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/Realtime-sync-anim.gif
--------------------------------------------------------------------------------
/images/angularjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/angularjs.png
--------------------------------------------------------------------------------
/images/api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/api.png
--------------------------------------------------------------------------------
/images/auth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/auth.png
--------------------------------------------------------------------------------
/images/backbonejs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/backbonejs.png
--------------------------------------------------------------------------------
/images/backend-reqs (1).gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/backend-reqs (1).gif
--------------------------------------------------------------------------------
/images/backend-reqs.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/backend-reqs.gif
--------------------------------------------------------------------------------
/images/clients.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/clients.png
--------------------------------------------------------------------------------
/images/clients.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/clients.psd
--------------------------------------------------------------------------------
/images/data-box.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/data-box.png
--------------------------------------------------------------------------------
/images/data-box.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/data-box.psd
--------------------------------------------------------------------------------
/images/database.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/database.png
--------------------------------------------------------------------------------
/images/docs-site.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/docs-site.png
--------------------------------------------------------------------------------
/images/emberjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/emberjs.png
--------------------------------------------------------------------------------
/images/fb-arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/fb-arch.png
--------------------------------------------------------------------------------
/images/firebase-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/firebase-logo.png
--------------------------------------------------------------------------------
/images/full-stack-clients.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/full-stack-clients.png
--------------------------------------------------------------------------------
/images/full-stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/full-stack.png
--------------------------------------------------------------------------------
/images/gdocs4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/gdocs4.gif
--------------------------------------------------------------------------------
/images/hosting-box.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/hosting-box.png
--------------------------------------------------------------------------------
/images/iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/iphone.png
--------------------------------------------------------------------------------
/images/laptop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/laptop.png
--------------------------------------------------------------------------------
/images/login-box.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/login-box.png
--------------------------------------------------------------------------------
/images/nexus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/nexus.png
--------------------------------------------------------------------------------
/images/offline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/offline.png
--------------------------------------------------------------------------------
/images/platforms.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/platforms.png
--------------------------------------------------------------------------------
/images/react.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/react.png
--------------------------------------------------------------------------------
/images/realtime-api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/realtime-api.png
--------------------------------------------------------------------------------
/images/security-box.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/security-box.png
--------------------------------------------------------------------------------
/images/server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/server.png
--------------------------------------------------------------------------------
/images/simple-api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/images/simple-api.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Building Realtime Apps with Firebase
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
51 |
52 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
70 |
71 |
72 | Intro to Firebase
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | The Realtime Backend
83 | for your App
84 |
85 |
86 |
87 | Creating an app shouldn't require managing complex infrastructure.
88 |
89 |
90 |
91 | The Full Stack
92 |
93 |
94 |
95 |
96 | The full stack is never really that simple
97 |
98 |
99 |
100 |
101 | ... and neither is the client side
102 |
103 |
104 |
105 |
106 |
107 | The user doesn't care about your backend
108 |
109 |
110 |
111 | The user expects
112 | Speed
113 | Offline
114 | Multi-platform
115 | Simple Authentication
116 |
117 |
118 |
121 |
122 | Firebase
123 |
124 |
125 | The Realtime Backend
126 | for your App
127 |
128 |
129 |
130 | The Firebase Backend
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | Forget the Server
139 | Firebase apps can run on client-side code only
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | Cloud database
150 | NoSQL data-store
151 | Returns JSON from a RESTful API
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | Realtime Data
160 |
161 | Whenever data is updated in Firebase,
162 | it sends the update down to every listening client
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | SDKs
172 |
173 |
174 |
175 |
176 | Store Data
177 |
178 |
179 | var ref = new Firebase("https://<your-firebase-app>.firebaseio.com/message");
180 | ref.set('All the things');
181 |
182 |
183 | let ref = Firebase(url: "https://<your-firebase-app>.firebaseio.com/message")
184 | ref.setValue("All the things")
185 |
186 |
187 | Firebase ref = new Firebase("https://<your-firebase-app>.firebaseio.com/message");
188 | ref.setValue("All the things");
189 |
190 |
191 |
192 |
193 |
194 |
195 | Sync Data
196 |
197 |
198 |
199 | var ref = new Firebase("https://<your-firebase-app>.firebaseio.com/message");
200 | ref.on("value", function(snap) {
201 | console.log(snap.val());
202 | });
203 |
204 |
205 | let ref = Firebase(url: "https://<your-firebase-app>.firebaseio.com/message")
206 | ref.observeEventType(.Value, withBlock: { snap in
207 | println(snap.value)
208 | })
209 |
210 |
211 | Firebase ref = new Firebase("https://<your-firebase-app>.firebaseio.com/message");
212 | ref.addValueEventListener(new ValueEventListener() {
213 | @Override
214 | public void onDataChange(DataSnapshot snapshot) {
215 | System.out.println(snapshot.getValue());
216 | }
217 | @Override public void onCancelled(FirebaseError error) { }
218 | });
219 |
220 |
221 |
222 |
223 |
224 |
225 | Offline
226 |
227 |
228 |
229 |
230 | Intermittent Offline
231 |
232 | What happens when you go through a tunnel?
233 |
234 |
235 | Firebase clients store a local cache of your data. When the user
236 | goes offline, the app still works as expected with the local cache.
237 |
238 |
239 |
240 |
241 |
242 | Extended Offline
243 |
244 | What happens when you go on a flight?
245 |
246 |
247 | On mobile, Firebase persists data to a local store. The app will continue
248 | to work even across app restarts.
249 |
250 |
251 |
252 |
253 |
254 | One line of code
255 |
256 |
257 |
258 | Firebase.defaultConfig().persistenceEnabled = true
259 |
260 |
261 | Firebase.getDefaultConfig().setPersistenceEnabled(true);
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 | Firebase supports several forms of authentication
275 |
276 |
277 |
278 | Email & Password
279 |
280 |
281 |
282 | Google
283 |
284 |
285 |
286 | Twitter
287 |
288 |
289 |
290 | Facebook
291 |
292 |
293 |
294 | Github
295 |
296 |
297 |
298 | Anonymous
299 |
300 |
301 |
302 | ...and even custom backends
303 |
304 |
305 |
306 |
307 |
308 |
309 | Authentication
310 |
311 |
312 |
313 | // Login with Google
314 | ref.authWithOAuthPopup('google', function(error, authData) {
315 | console.log(authData);
316 | });
317 |
318 |
319 |
320 | ref.authWithOAuthProvider("google", token: "<OAuth Token>",
321 | withCompletionBlock: { error, authData in
322 | if error != nil {
323 | // Error authenticating with Firebase with OAuth token
324 | } else {
325 | // User is now logged in!
326 | println("Successfully logged in! \(authData)")
327 | }
328 | })
329 |
330 |
331 |
332 | ref.authWithOAuthToken("google", "<OAuth Token>", new Firebase.AuthResultHandler() {
333 | @Override
334 | public void onAuthenticated(AuthData authData) {
335 | // the Google user is now authenticated with your Firebase app
336 | }
337 |
338 | @Override
339 | public void onAuthenticationError(FirebaseError firebaseError) {
340 | // there was an error
341 | }
342 | });
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 | Authentication
352 |
353 |
354 |
355 | // Listen for authentcated users
356 | ref.onAuth(function(authData) {
357 | if(authData) {
358 | console.log('User is logged in!');
359 | }
360 | });
361 |
362 |
363 |
364 | // Listen for authenticated users
365 | ref.observeAuthEventWithBlock { authData in
366 | if authData != nil {
367 | println("User is logged in! \(authData)")
368 | }
369 | }
370 |
371 |
372 |
373 | // Listen for authentcated users
374 | ref.addAuthStateListener(new Firebase.AuthStateListener() {
375 | @Override
376 | public void onAuthStateChanged(AuthData authData) {
377 | if (authData != null) {
378 | System.out.println("User is logged in!");
379 | }
380 | }
381 | });
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 | Security
394 |
395 | By default everyone can write and read
396 |
397 |
398 |
399 | {
400 | "rules": {
401 | ".read": true,
402 | ".write": true,
403 | }
404 | }
405 |
406 |
407 |
408 |
409 |
410 |
411 | Everyone can read, but no one can write
412 |
413 |
414 |
415 | {
416 | "rules": {
417 | ".read": true,
418 | ".write": false,
419 | }
420 | }
421 |
422 |
423 |
424 |
425 |
426 |
427 | Secure specific parts of your Firebase
428 |
429 |
430 |
431 | {
432 | "rules": {
433 | ".read": true,
434 | ".write": false,
435 | "message": {
436 | ".write": true
437 | }
438 | }
439 | }
440 |
441 |
442 |
443 |
444 |
445 |
446 | Special variables to power authentication
447 |
448 |
449 |
450 | {
451 | "rules": {
452 | ".read": true,
453 | "message": {
454 | ".write": "auth !== null",
455 | ".validate": "!data.exists()"
456 | }
457 | }
458 | }
459 |
460 |
461 |
462 |
463 |
464 |
465 | Security
466 | Use $wildcards as route parameters
467 |
468 |
469 | {
470 | "rules": {
471 | ".read": false,
472 | ".write": false,
473 | "users": {
474 | "$userid": {
475 | ".read": "true",
476 | ".write": "auth.uid === $userid"
477 | }
478 | }
479 | }
480 | }
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 | Hosting
492 | When you're ready to launch
493 |
494 |
495 | firebase init
496 | # select your firebase
497 | firebase deploy
498 | # party time
499 |
500 |
501 |
502 |
503 |
504 | Hosting
505 | Production-grade
506 | Static Asset
507 | Free SSL
508 | CDN cached assets
509 | One click rollbacks
510 |
511 |
512 |
513 | (Optional) Live Coding
514 |
515 |
516 |
517 | Tooling & Integration
518 |
519 |
520 |
521 |
522 | Bindings
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 | AngularFire
531 | A chat app in AngularFire
532 |
533 |
534 | var app = app.module('app', ['firebase']);
535 | app.controller('ChatCtrl', function($scope, $firebaseArray) {
536 | var ref = new Firebase('https://<your-firebase>.firebaseio.com/messages');
537 | $scope.messages = $firebaseArray(ref);
538 | });
539 |
540 |
541 |
542 |
543 | <html>
544 | <body ng-app="app">
545 | <div ng-controller="ChatCtrl">
546 | <p ng-repeat="message in messages">message.text</p>
547 | </div>
548 | </body>
549 | </html>
550 |
551 |
552 |
553 |
554 |
555 | Geofire
556 | Store and query items based on their geographic location in realtime
557 |
558 |
559 |
560 |
566 |
567 |
568 | Firebase meta-data
569 |
570 | 170,000+ registered developers
571 |
572 |
573 | 1M concurrent users on Firebase sites
574 |
575 |
576 | Joined Google October, 2014
577 |
578 |
579 |
580 |
581 | Firebase in Production
582 |
583 | -
584 | Twitch.tv - Notifying users when realtime streams go live
585 |
586 | -
587 | Citrix - Manages presence in GoTo Meeting
588 |
589 | -
590 | CBS - Powers the chat for Big Brother's Live Stream
591 |
592 | -
593 | Warby Parker - Powering pneumatic tubes
594 |
595 |
596 |
597 |
598 |
599 | Focus on your app
600 | The user doesn't care about the backend
601 | What matters is that your app is
602 | fast and enjoyable
603 |
604 |
605 |
606 |
607 | Complete Platform
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 | ASK ME QUESTIONS
616 |
617 |
618 |
619 |
620 |
621 | Assets Used
622 |
623 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
672 |
673 |
693 |
694 |
695 |
--------------------------------------------------------------------------------
/js/.gitignore:
--------------------------------------------------------------------------------
1 | reveal.min.js
2 |
--------------------------------------------------------------------------------
/lib/css/zenburn.css:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Zenburn style from voldmar.ru (c) Vladimir Epifanov
4 | based on dark.css by Ivan Sagalaev
5 |
6 | */
7 |
8 | pre code {
9 | display: block; padding: 0.5em;
10 | background: #3F3F3F;
11 | color: #DCDCDC;
12 | }
13 |
14 | pre .keyword,
15 | pre .tag,
16 | pre .css .class,
17 | pre .css .id,
18 | pre .lisp .title,
19 | pre .nginx .title,
20 | pre .request,
21 | pre .status,
22 | pre .clojure .attribute {
23 | color: #E3CEAB;
24 | }
25 |
26 | pre .django .template_tag,
27 | pre .django .variable,
28 | pre .django .filter .argument {
29 | color: #DCDCDC;
30 | }
31 |
32 | pre .number,
33 | pre .date {
34 | color: #8CD0D3;
35 | }
36 |
37 | pre .dos .envvar,
38 | pre .dos .stream,
39 | pre .variable,
40 | pre .apache .sqbracket {
41 | color: #EFDCBC;
42 | }
43 |
44 | pre .dos .flow,
45 | pre .diff .change,
46 | pre .python .exception,
47 | pre .python .built_in,
48 | pre .literal,
49 | pre .tex .special {
50 | color: #EFEFAF;
51 | }
52 |
53 | pre .diff .chunk,
54 | pre .subst {
55 | color: #8F8F8F;
56 | }
57 |
58 | pre .dos .keyword,
59 | pre .python .decorator,
60 | pre .title,
61 | pre .haskell .type,
62 | pre .diff .header,
63 | pre .ruby .class .parent,
64 | pre .apache .tag,
65 | pre .nginx .built_in,
66 | pre .tex .command,
67 | pre .prompt {
68 | color: #efef8f;
69 | }
70 |
71 | pre .dos .winutils,
72 | pre .ruby .symbol,
73 | pre .ruby .symbol .string,
74 | pre .ruby .string {
75 | color: #DCA3A3;
76 | }
77 |
78 | pre .diff .deletion,
79 | pre .string,
80 | pre .tag .value,
81 | pre .preprocessor,
82 | pre .built_in,
83 | pre .sql .aggregate,
84 | pre .javadoc,
85 | pre .smalltalk .class,
86 | pre .smalltalk .localvars,
87 | pre .smalltalk .array,
88 | pre .css .rules .value,
89 | pre .attr_selector,
90 | pre .pseudo,
91 | pre .apache .cbracket,
92 | pre .tex .formula {
93 | color: #CC9393;
94 | }
95 |
96 | pre .shebang,
97 | pre .diff .addition,
98 | pre .comment,
99 | pre .java .annotation,
100 | pre .template_comment,
101 | pre .pi,
102 | pre .doctype {
103 | color: #7F9F7F;
104 | }
105 |
106 | pre .coffeescript .javascript,
107 | pre .javascript .xml,
108 | pre .tex .formula,
109 | pre .xml .javascript,
110 | pre .xml .vbscript,
111 | pre .xml .css,
112 | pre .xml .cdata {
113 | opacity: 0.5;
114 | }
--------------------------------------------------------------------------------
/lib/font/league_gothic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/lib/font/league_gothic-webfont.eot
--------------------------------------------------------------------------------
/lib/font/league_gothic-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/lib/font/league_gothic-webfont.ttf
--------------------------------------------------------------------------------
/lib/font/league_gothic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/lib/font/league_gothic-webfont.woff
--------------------------------------------------------------------------------
/lib/font/league_gothic_license:
--------------------------------------------------------------------------------
1 | SIL Open Font License (OFL)
2 | http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL
3 |
--------------------------------------------------------------------------------
/lib/js/classList.js:
--------------------------------------------------------------------------------
1 | /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
2 | if(typeof document!=="undefined"&&!("classList" in document.createElement("a"))){(function(j){var a="classList",f="prototype",m=(j.HTMLElement||j.Element)[f],b=Object,k=String[f].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[f].indexOf||function(q){var p=0,o=this.length;for(;p
3 | Copyright Tero Piirainen (tipiirai)
4 | License MIT / http://bit.ly/mit-license
5 | Version 0.96
6 |
7 | http://headjs.com
8 | */(function(a){function z(){d||(d=!0,s(e,function(a){p(a)}))}function y(c,d){var e=a.createElement("script");e.type="text/"+(c.type||"javascript"),e.src=c.src||c,e.async=!1,e.onreadystatechange=e.onload=function(){var a=e.readyState;!d.done&&(!a||/loaded|complete/.test(a))&&(d.done=!0,d())},(a.body||b).appendChild(e)}function x(a,b){if(a.state==o)return b&&b();if(a.state==n)return k.ready(a.name,b);if(a.state==m)return a.onpreload.push(function(){x(a,b)});a.state=n,y(a.url,function(){a.state=o,b&&b(),s(g[a.name],function(a){p(a)}),u()&&d&&s(g.ALL,function(a){p(a)})})}function w(a,b){a.state===undefined&&(a.state=m,a.onpreload=[],y({src:a.url,type:"cache"},function(){v(a)}))}function v(a){a.state=l,s(a.onpreload,function(a){a.call()})}function u(a){a=a||h;var b;for(var c in a){if(a.hasOwnProperty(c)&&a[c].state!=o)return!1;b=!0}return b}function t(a){return Object.prototype.toString.call(a)=="[object Function]"}function s(a,b){if(!!a){typeof a=="object"&&(a=[].slice.call(a));for(var c=0;c (https://www.firebase.com)",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/davideast/firebase-intro.git"
9 | },
10 | "licenses": [
11 | {
12 | "type": "MIT",
13 | "url": "https://github.com/hakimel/reveal.js/blob/master/LICENSE"
14 | }
15 | ],
16 | "dependencies": {
17 | "underscore": "~1.5.1",
18 | "express": "~2.5.9",
19 | "mustache": "~0.7.2",
20 | "socket.io": "~0.9.13"
21 | },
22 | "devDependencies": {
23 | "grunt-contrib-qunit": "~0.2.2",
24 | "grunt-contrib-jshint": "~0.6.4",
25 | "grunt-contrib-cssmin": "~0.4.1",
26 | "grunt-contrib-uglify": "~0.2.4",
27 | "grunt-contrib-watch": "~0.5.3",
28 | "grunt-contrib-sass": "~0.5.0",
29 | "grunt-contrib-connect": "~0.4.1",
30 | "grunt-zip": "~0.7.0",
31 | "grunt": "~0.4.0"
32 | },
33 | "private": true
34 | }
35 |
--------------------------------------------------------------------------------
/plugin/markdown/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Markdown Demo
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
37 |
38 |
39 |
55 |
56 |
57 |
70 |
71 |
72 |
78 |
79 |
80 |
87 |
88 |
89 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/plugin/markdown/example.md:
--------------------------------------------------------------------------------
1 | # Markdown Demo
2 |
3 |
4 |
5 | ## External 1.1
6 |
7 | Content 1.1
8 |
9 | Note: This will only appear in the speaker notes window.
10 |
11 |
12 | ## External 1.2
13 |
14 | Content 1.2
15 |
16 |
17 |
18 | ## External 2
19 |
20 | Content 2.1
21 |
22 |
23 |
24 | ## External 3.1
25 |
26 | Content 3.1
27 |
28 |
29 | ## External 3.2
30 |
31 | Content 3.2
32 |
--------------------------------------------------------------------------------
/plugin/markdown/markdown.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The reveal.js markdown plugin. Handles parsing of
3 | * markdown inside of presentations as well as loading
4 | * of external markdown documents.
5 | */
6 | (function( root, factory ) {
7 | if( typeof exports === 'object' ) {
8 | module.exports = factory( require( './marked' ) );
9 | }
10 | else {
11 | // Browser globals (root is window)
12 | root.RevealMarkdown = factory( root.marked );
13 | root.RevealMarkdown.initialize();
14 | }
15 | }( this, function( marked ) {
16 |
17 | if( typeof marked === 'undefined' ) {
18 | throw 'The reveal.js Markdown plugin requires marked to be loaded';
19 | }
20 |
21 | if( typeof hljs !== 'undefined' ) {
22 | marked.setOptions({
23 | highlight: function( lang, code ) {
24 | return hljs.highlightAuto( lang, code ).value;
25 | }
26 | });
27 | }
28 |
29 | var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$',
30 | DEFAULT_NOTES_SEPARATOR = 'note:',
31 | DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$',
32 | DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$';
33 |
34 |
35 | /**
36 | * Retrieves the markdown contents of a slide section
37 | * element. Normalizes leading tabs/whitespace.
38 | */
39 | function getMarkdownFromSlide( section ) {
40 |
41 | var template = section.querySelector( 'script' );
42 |
43 | // strip leading whitespace so it isn't evaluated as code
44 | var text = ( template || section ).textContent;
45 |
46 | var leadingWs = text.match( /^\n?(\s*)/ )[1].length,
47 | leadingTabs = text.match( /^\n?(\t*)/ )[1].length;
48 |
49 | if( leadingTabs > 0 ) {
50 | text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
51 | }
52 | else if( leadingWs > 1 ) {
53 | text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
54 | }
55 |
56 | return text;
57 |
58 | }
59 |
60 | /**
61 | * Given a markdown slide section element, this will
62 | * return all arguments that aren't related to markdown
63 | * parsing. Used to forward any other user-defined arguments
64 | * to the output markdown slide.
65 | */
66 | function getForwardedAttributes( section ) {
67 |
68 | var attributes = section.attributes;
69 | var result = [];
70 |
71 | for( var i = 0, len = attributes.length; i < len; i++ ) {
72 | var name = attributes[i].name,
73 | value = attributes[i].value;
74 |
75 | // disregard attributes that are used for markdown loading/parsing
76 | if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;
77 |
78 | if( value ) {
79 | result.push( name + '=' + value );
80 | }
81 | else {
82 | result.push( name );
83 | }
84 | }
85 |
86 | return result.join( ' ' );
87 |
88 | }
89 |
90 | /**
91 | * Inspects the given options and fills out default
92 | * values for what's not defined.
93 | */
94 | function getSlidifyOptions( options ) {
95 |
96 | options = options || {};
97 | options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
98 | options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
99 | options.attributes = options.attributes || '';
100 |
101 | return options;
102 |
103 | }
104 |
105 | /**
106 | * Helper function for constructing a markdown slide.
107 | */
108 | function createMarkdownSlide( content, options ) {
109 |
110 | options = getSlidifyOptions( options );
111 |
112 | var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
113 |
114 | if( notesMatch.length === 2 ) {
115 | content = notesMatch[0] + '';
116 | }
117 |
118 | return '';
119 |
120 | }
121 |
122 | /**
123 | * Parses a data string into multiple slides based
124 | * on the passed in separator arguments.
125 | */
126 | function slidify( markdown, options ) {
127 |
128 | options = getSlidifyOptions( options );
129 |
130 | var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
131 | horizontalSeparatorRegex = new RegExp( options.separator );
132 |
133 | var matches,
134 | lastIndex = 0,
135 | isHorizontal,
136 | wasHorizontal = true,
137 | content,
138 | sectionStack = [];
139 |
140 | // iterate until all blocks between separators are stacked up
141 | while( matches = separatorRegex.exec( markdown ) ) {
142 | notes = null;
143 |
144 | // determine direction (horizontal by default)
145 | isHorizontal = horizontalSeparatorRegex.test( matches[0] );
146 |
147 | if( !isHorizontal && wasHorizontal ) {
148 | // create vertical stack
149 | sectionStack.push( [] );
150 | }
151 |
152 | // pluck slide content from markdown input
153 | content = markdown.substring( lastIndex, matches.index );
154 |
155 | if( isHorizontal && wasHorizontal ) {
156 | // add to horizontal stack
157 | sectionStack.push( content );
158 | }
159 | else {
160 | // add to vertical stack
161 | sectionStack[sectionStack.length-1].push( content );
162 | }
163 |
164 | lastIndex = separatorRegex.lastIndex;
165 | wasHorizontal = isHorizontal;
166 | }
167 |
168 | // add the remaining slide
169 | ( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );
170 |
171 | var markdownSections = '';
172 |
173 | // flatten the hierarchical stack, and insert tags
174 | for( var i = 0, len = sectionStack.length; i < len; i++ ) {
175 | // vertical
176 | if( sectionStack[i] instanceof Array ) {
177 | markdownSections += '';
178 |
179 | sectionStack[i].forEach( function( child ) {
180 | markdownSections += '' + createMarkdownSlide( child, options ) + '';
181 | } );
182 |
183 | markdownSections += '';
184 | }
185 | else {
186 | markdownSections += '' + createMarkdownSlide( sectionStack[i], options ) + '';
187 | }
188 | }
189 |
190 | return markdownSections;
191 |
192 | }
193 |
194 | /**
195 | * Parses any current data-markdown slides, splits
196 | * multi-slide markdown into separate sections and
197 | * handles loading of external markdown.
198 | */
199 | function processSlides() {
200 |
201 | var sections = document.querySelectorAll( '[data-markdown]'),
202 | section;
203 |
204 | for( var i = 0, len = sections.length; i < len; i++ ) {
205 |
206 | section = sections[i];
207 |
208 | if( section.getAttribute( 'data-markdown' ).length ) {
209 |
210 | var xhr = new XMLHttpRequest(),
211 | url = section.getAttribute( 'data-markdown' );
212 |
213 | datacharset = section.getAttribute( 'data-charset' );
214 |
215 | // see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
216 | if( datacharset != null && datacharset != '' ) {
217 | xhr.overrideMimeType( 'text/html; charset=' + datacharset );
218 | }
219 |
220 | xhr.onreadystatechange = function() {
221 | if( xhr.readyState === 4 ) {
222 | if ( xhr.status >= 200 && xhr.status < 300 ) {
223 |
224 | section.outerHTML = slidify( xhr.responseText, {
225 | separator: section.getAttribute( 'data-separator' ),
226 | verticalSeparator: section.getAttribute( 'data-vertical' ),
227 | notesSeparator: section.getAttribute( 'data-notes' ),
228 | attributes: getForwardedAttributes( section )
229 | });
230 |
231 | }
232 | else {
233 |
234 | section.outerHTML = '' +
235 | 'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
236 | 'Check your browser\'s JavaScript console for more details.' +
237 | 'Remember that you need to serve the presentation HTML from a HTTP server.
' +
238 | '';
239 |
240 | }
241 | }
242 | };
243 |
244 | xhr.open( 'GET', url, false );
245 |
246 | try {
247 | xhr.send();
248 | }
249 | catch ( e ) {
250 | 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 );
251 | }
252 |
253 | }
254 | else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-vertical' ) || section.getAttribute( 'data-notes' ) ) {
255 |
256 | section.outerHTML = slidify( getMarkdownFromSlide( section ), {
257 | separator: section.getAttribute( 'data-separator' ),
258 | verticalSeparator: section.getAttribute( 'data-vertical' ),
259 | notesSeparator: section.getAttribute( 'data-notes' ),
260 | attributes: getForwardedAttributes( section )
261 | });
262 |
263 | }
264 | else {
265 | section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
266 | }
267 | }
268 |
269 | }
270 |
271 | /**
272 | * Check if a node value has the attributes pattern.
273 | * If yes, extract it and add that value as one or several attributes
274 | * the the terget element.
275 | *
276 | * You need Cache Killer on Chrome to see the effect on any FOM transformation
277 | * directly on refresh (F5)
278 | * http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277
279 | */
280 | function addAttributeInElement( node, elementTarget, separator ) {
281 |
282 | var mardownClassesInElementsRegex = new RegExp( separator, 'mg' );
283 | var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' );
284 | var nodeValue = node.nodeValue;
285 | if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {
286 |
287 | var classes = matches[1];
288 | nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex );
289 | node.nodeValue = nodeValue;
290 | while( matchesClass = mardownClassRegex.exec( classes ) ) {
291 | elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
292 | }
293 | return true;
294 | }
295 | return false;
296 | }
297 |
298 | /**
299 | * Add attributes to the parent element of a text node,
300 | * or the element of an attribute node.
301 | */
302 | function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) {
303 |
304 | if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) {
305 | previousParentElement = element;
306 | for( var i = 0; i < element.childNodes.length; i++ ) {
307 | childElement = element.childNodes[i];
308 | if ( i > 0 ) {
309 | j = i - 1;
310 | while ( j >= 0 ) {
311 | aPreviousChildElement = element.childNodes[j];
312 | if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) {
313 | previousParentElement = aPreviousChildElement;
314 | break;
315 | }
316 | j = j - 1;
317 | }
318 | }
319 | parentSection = section;
320 | if( childElement.nodeName == "section" ) {
321 | parentSection = childElement ;
322 | previousParentElement = childElement ;
323 | }
324 | if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) {
325 | addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes );
326 | }
327 | }
328 | }
329 |
330 | if ( element.nodeType == Node.COMMENT_NODE ) {
331 | if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) {
332 | addAttributeInElement( element, section, separatorSectionAttributes );
333 | }
334 | }
335 | }
336 |
337 | /**
338 | * Converts any current data-markdown slides in the
339 | * DOM to HTML.
340 | */
341 | function convertSlides() {
342 |
343 | var sections = document.querySelectorAll( '[data-markdown]');
344 |
345 | for( var i = 0, len = sections.length; i < len; i++ ) {
346 |
347 | var section = sections[i];
348 |
349 | // Only parse the same slide once
350 | if( !section.getAttribute( 'data-markdown-parsed' ) ) {
351 |
352 | section.setAttribute( 'data-markdown-parsed', true )
353 |
354 | var notes = section.querySelector( 'aside.notes' );
355 | var markdown = getMarkdownFromSlide( section );
356 |
357 | section.innerHTML = marked( markdown );
358 | addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) ||
359 | section.parentNode.getAttribute( 'data-element-attributes' ) ||
360 | DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
361 | section.getAttribute( 'data-attributes' ) ||
362 | section.parentNode.getAttribute( 'data-attributes' ) ||
363 | DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);
364 |
365 | // If there were notes, we need to re-add them after
366 | // having overwritten the section's HTML
367 | if( notes ) {
368 | section.appendChild( notes );
369 | }
370 |
371 | }
372 |
373 | }
374 |
375 | }
376 |
377 | // API
378 | return {
379 |
380 | initialize: function() {
381 | processSlides();
382 | convertSlides();
383 | },
384 |
385 | // TODO: Do these belong in the API?
386 | processSlides: processSlides,
387 | convertSlides: convertSlides,
388 | slidify: slidify
389 |
390 | };
391 |
392 | }));
393 |
--------------------------------------------------------------------------------
/plugin/markdown/marked.js:
--------------------------------------------------------------------------------
1 | /**
2 | * marked - a markdown parser
3 | * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
4 | * https://github.com/chjj/marked
5 | */
6 |
7 | (function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){3,} *\n*/,blockquote:/^( *>[^\n]+(\n[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
8 | text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr",/\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b";block.html=replace(block.html)("comment",/\x3c!--[\s\S]*?--\x3e/)("closed",
9 | /<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1",
10 | "\\2")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm)if(this.options.tables)this.rules=block.tables;else this.rules=block.gfm}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};
11 | Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1)this.tokens.push({type:"space"})}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,
12 | "");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,
13 | "").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);
15 | bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i1&&b.length>1)){src=cap.slice(i+
16 | 1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item[item.length-1]==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:cap[1]==="pre"||cap[1]==="script",text:cap[0]});continue}if(top&&
17 | (cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^\x3c!--[\s\S]*?--\x3e|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
20 | code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
21 | em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;
22 | if(!this.links)throw new Error("Tokens array requires a `links` property.");if(this.options.gfm)if(this.options.breaks)this.rules=inline.breaks;else this.rules=inline.gfm;else if(this.options.pedantic)this.rules=inline.pedantic}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);
23 | out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1][6]===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=''+text+"";continue}if(cap=this.rules.url.exec(src)){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=''+text+"";continue}if(cap=this.rules.tag.exec(src)){src=src.substring(cap[0].length);
24 | out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);out+=this.outputLink(cap,{href:cap[2],title:cap[3]});continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0][0];src=cap[0].substring(1)+src;continue}out+=this.outputLink(cap,link);continue}if(cap=this.rules.strong.exec(src)){src=
25 | src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+"";continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+"";continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=""+escape(cap[2],true)+"
";continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+="
";continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=""+
26 | this.output(cap[1])+"";continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(cap[0]);continue}if(src)throw new Error("Infinite loop on byte: "+src.charCodeAt(0));}return out};InlineLexer.prototype.outputLink=function(cap,link){if(cap[0][0]!=="!")return'"+this.output(cap[1])+"";else return'
"};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"\u2014").replace(/'([^']*)'/g,"\u2018$1\u2019").replace(/"([^"]*)"/g,"\u201c$1\u201d").replace(/\.{3}/g,"\u2026")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i0.5)ch="x"+ch.toString(16);out+=""+ch+";"}return out};function Parser(options){this.tokens=[];this.token=null;
28 | this.options=options||marked.defaults}Parser.parse=function(src,options){var parser=new Parser(options);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options);this.tokens=src.reverse();var out="";while(this.next())out+=this.tok();return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;
29 | while(this.peek().type==="text")body+="\n"+this.next().text;return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case "space":return"";case "hr":return"
\n";case "heading":return""+this.inline.output(this.token.text)+"\n";case "code":if(this.options.highlight){var code=this.options.highlight(this.token.text,this.token.lang);if(code!=null&&code!==this.token.text){this.token.escaped=true;this.token.text=code}}if(!this.token.escaped)this.token.text=
30 | escape(this.token.text,true);return""+this.token.text+"
\n";case "table":var body="",heading,i,row,cell,j;body+="\n\n";for(i=0;i'+heading+"\n":""+heading+" | \n"}body+="
\n\n";body+="\n";for(i=0;i\n";for(j=0;j'+cell+"\n":""+cell+" | \n"}body+="\n"}body+="\n";return"\n";case "blockquote_start":var body="";while(this.next().type!=="blockquote_end")body+=this.tok();return"\n"+body+"
\n";case "list_start":var type=this.token.ordered?"ol":"ul",body="";while(this.next().type!=="list_end")body+=
32 | this.tok();return"<"+type+">\n"+body+""+type+">\n";case "list_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.token.type==="text"?this.parseText():this.tok();return""+body+"\n";case "loose_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.tok();return""+body+"\n";case "html":return!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;case "paragraph":return""+this.inline.output(this.token.text)+
33 | "
\n";case "text":return""+this.parseText()+"
\n"}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=
34 | 1,target,key;for(;iAn error occured:
"+escape(e.message+"",true)+"
";throw e;}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:""};marked.Parser=Parser;marked.parser=Parser.parse;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;
37 | marked.parse=marked;if(typeof exports==="object")module.exports=marked;else if(typeof define==="function"&&define.amd)define(function(){return marked});else this.marked=marked}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
38 |
--------------------------------------------------------------------------------
/plugin/math/math.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A plugin which enables rendering of math equations inside
3 | * of reveal.js slides. Essentially a thin wrapper for MathJax.
4 | *
5 | * @author Hakim El Hattab
6 | */
7 | var RevealMath = window.RevealMath || (function(){
8 |
9 | var options = Reveal.getConfig().math || {};
10 | options.mathjax = options.mathjax || 'http://cdn.mathjax.org/mathjax/latest/MathJax.js';
11 | options.config = options.config || 'TeX-AMS_HTML-full';
12 |
13 | loadScript( options.mathjax + '?config=' + options.config, function() {
14 |
15 | MathJax.Hub.Config({
16 | messageStyle: 'none',
17 | tex2jax: { inlineMath: [['$','$'],['\\(','\\)']] },
18 | skipStartupTypeset: true
19 | });
20 |
21 | // Typeset followed by an immediate reveal.js layout since
22 | // the typesetting process could affect slide height
23 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub ] );
24 | MathJax.Hub.Queue( Reveal.layout );
25 |
26 | // Reprocess equations in slides when they turn visible
27 | Reveal.addEventListener( 'slidechanged', function( event ) {
28 |
29 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] );
30 |
31 | } );
32 |
33 | } );
34 |
35 | function loadScript( url, callback ) {
36 |
37 | var head = document.querySelector( 'head' );
38 | var script = document.createElement( 'script' );
39 | script.type = 'text/javascript';
40 | script.src = url;
41 |
42 | // Wrapper for callback to make sure it only fires once
43 | var finish = function() {
44 | if( typeof callback === 'function' ) {
45 | callback.call();
46 | callback = null;
47 | }
48 | }
49 |
50 | script.onload = finish;
51 |
52 | // IE
53 | script.onreadystatechange = function() {
54 | if ( this.readyState === 'loaded' ) {
55 | finish();
56 | }
57 | }
58 |
59 | // Normal browsers
60 | head.appendChild( script );
61 |
62 | }
63 |
64 | })();
65 |
--------------------------------------------------------------------------------
/plugin/multiplex/client.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var multiplex = Reveal.getConfig().multiplex;
3 | var socketId = multiplex.id;
4 | var socket = io.connect(multiplex.url);
5 |
6 | socket.on(multiplex.id, function(data) {
7 | // ignore data from sockets that aren't ours
8 | if (data.socketId !== socketId) { return; }
9 | if( window.location.host === 'localhost:1947' ) return;
10 |
11 | Reveal.slide(data.indexh, data.indexv, data.indexf, 'remote');
12 | });
13 | }());
14 |
--------------------------------------------------------------------------------
/plugin/multiplex/index.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var fs = require('fs');
3 | var io = require('socket.io');
4 | var crypto = require('crypto');
5 |
6 | var app = express.createServer();
7 | var staticDir = express.static;
8 |
9 | io = io.listen(app);
10 |
11 | var opts = {
12 | port: 1948,
13 | baseDir : __dirname + '/../../'
14 | };
15 |
16 | io.sockets.on('connection', function(socket) {
17 | socket.on('slidechanged', function(slideData) {
18 | if (typeof slideData.secret == 'undefined' || slideData.secret == null || slideData.secret === '') return;
19 | if (createHash(slideData.secret) === slideData.socketId) {
20 | slideData.secret = null;
21 | socket.broadcast.emit(slideData.socketId, slideData);
22 | };
23 | });
24 | });
25 |
26 | app.configure(function() {
27 | [ 'css', 'js', 'plugin', 'lib' ].forEach(function(dir) {
28 | app.use('/' + dir, staticDir(opts.baseDir + dir));
29 | });
30 | });
31 |
32 | app.get("/", function(req, res) {
33 | res.writeHead(200, {'Content-Type': 'text/html'});
34 | fs.createReadStream(opts.baseDir + '/index.html').pipe(res);
35 | });
36 |
37 | app.get("/token", function(req,res) {
38 | var ts = new Date().getTime();
39 | var rand = Math.floor(Math.random()*9999999);
40 | var secret = ts.toString() + rand.toString();
41 | res.send({secret: secret, socketId: createHash(secret)});
42 | });
43 |
44 | var createHash = function(secret) {
45 | var cipher = crypto.createCipher('blowfish', secret);
46 | return(cipher.final('hex'));
47 | };
48 |
49 | // Actually listen
50 | app.listen(opts.port || null);
51 |
52 | var brown = '\033[33m',
53 | green = '\033[32m',
54 | reset = '\033[0m';
55 |
56 | console.log( brown + "reveal.js:" + reset + " Multiplex running on port " + green + opts.port + reset );
--------------------------------------------------------------------------------
/plugin/multiplex/master.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | // Don't emit events from inside of notes windows
3 | if ( window.location.search.match( /receiver/gi ) ) { return; }
4 |
5 | var multiplex = Reveal.getConfig().multiplex;
6 |
7 | var socket = io.connect(multiplex.url);
8 |
9 | var notify = function( slideElement, indexh, indexv, origin ) {
10 | if( typeof origin === 'undefined' && origin !== 'remote' ) {
11 | var nextindexh;
12 | var nextindexv;
13 |
14 | var fragmentindex = Reveal.getIndices().f;
15 | if (typeof fragmentindex == 'undefined') {
16 | fragmentindex = 0;
17 | }
18 |
19 | if (slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION') {
20 | nextindexh = indexh;
21 | nextindexv = indexv + 1;
22 | } else {
23 | nextindexh = indexh + 1;
24 | nextindexv = 0;
25 | }
26 |
27 | var slideData = {
28 | indexh : indexh,
29 | indexv : indexv,
30 | indexf : fragmentindex,
31 | nextindexh : nextindexh,
32 | nextindexv : nextindexv,
33 | secret: multiplex.secret,
34 | socketId : multiplex.id
35 | };
36 |
37 | socket.emit('slidechanged', slideData);
38 | }
39 | }
40 |
41 | Reveal.addEventListener( 'slidechanged', function( event ) {
42 | notify( event.currentSlide, event.indexh, event.indexv, event.origin );
43 | } );
44 |
45 | var fragmentNotify = function( event ) {
46 | notify( Reveal.getCurrentSlide(), Reveal.getIndices().h, Reveal.getIndices().v, event.origin );
47 | };
48 |
49 | Reveal.addEventListener( 'fragmentshown', fragmentNotify );
50 | Reveal.addEventListener( 'fragmenthidden', fragmentNotify );
51 | }());
--------------------------------------------------------------------------------
/plugin/notes-server/client.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | // don't emit events from inside the previews themselves
3 | if ( window.location.search.match( /receiver/gi ) ) { return; }
4 |
5 | var socket = io.connect(window.location.origin);
6 | var socketId = Math.random().toString().slice(2);
7 |
8 | console.log('View slide notes at ' + window.location.origin + '/notes/' + socketId);
9 | window.open(window.location.origin + '/notes/' + socketId, 'notes-' + socketId);
10 |
11 | // Fires when a fragment is shown
12 | Reveal.addEventListener( 'fragmentshown', function( event ) {
13 | var fragmentData = {
14 | fragment : 'next',
15 | socketId : socketId
16 | };
17 | socket.emit('fragmentchanged', fragmentData);
18 | } );
19 |
20 | // Fires when a fragment is hidden
21 | Reveal.addEventListener( 'fragmenthidden', function( event ) {
22 | var fragmentData = {
23 | fragment : 'previous',
24 | socketId : socketId
25 | };
26 | socket.emit('fragmentchanged', fragmentData);
27 | } );
28 |
29 | // Fires when slide is changed
30 | Reveal.addEventListener( 'slidechanged', function( event ) {
31 | var nextindexh;
32 | var nextindexv;
33 | var slideElement = event.currentSlide;
34 |
35 | if (slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION') {
36 | nextindexh = event.indexh;
37 | nextindexv = event.indexv + 1;
38 | } else {
39 | nextindexh = event.indexh + 1;
40 | nextindexv = 0;
41 | }
42 |
43 | var notes = slideElement.querySelector('aside.notes');
44 | var slideData = {
45 | notes : notes ? notes.innerHTML : '',
46 | indexh : event.indexh,
47 | indexv : event.indexv,
48 | nextindexh : nextindexh,
49 | nextindexv : nextindexv,
50 | socketId : socketId,
51 | markdown : notes ? typeof notes.getAttribute('data-markdown') === 'string' : false
52 |
53 | };
54 |
55 | socket.emit('slidechanged', slideData);
56 | } );
57 | }());
58 |
--------------------------------------------------------------------------------
/plugin/notes-server/index.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var fs = require('fs');
3 | var io = require('socket.io');
4 | var _ = require('underscore');
5 | var Mustache = require('mustache');
6 |
7 | var app = express.createServer();
8 | var staticDir = express.static;
9 |
10 | io = io.listen(app);
11 |
12 | var opts = {
13 | port : 1947,
14 | baseDir : __dirname + '/../../'
15 | };
16 |
17 | io.sockets.on('connection', function(socket) {
18 | socket.on('slidechanged', function(slideData) {
19 | socket.broadcast.emit('slidedata', slideData);
20 | });
21 | socket.on('fragmentchanged', function(fragmentData) {
22 | socket.broadcast.emit('fragmentdata', fragmentData);
23 | });
24 | });
25 |
26 | app.configure(function() {
27 | [ 'css', 'js', 'images', 'plugin', 'lib' ].forEach(function(dir) {
28 | app.use('/' + dir, staticDir(opts.baseDir + dir));
29 | });
30 | });
31 |
32 | app.get("/", function(req, res) {
33 | res.writeHead(200, {'Content-Type': 'text/html'});
34 | fs.createReadStream(opts.baseDir + '/index.html').pipe(res);
35 | });
36 |
37 | app.get("/notes/:socketId", function(req, res) {
38 |
39 | fs.readFile(opts.baseDir + 'plugin/notes-server/notes.html', function(err, data) {
40 | res.send(Mustache.to_html(data.toString(), {
41 | socketId : req.params.socketId
42 | }));
43 | });
44 | // fs.createReadStream(opts.baseDir + 'notes-server/notes.html').pipe(res);
45 | });
46 |
47 | // Actually listen
48 | app.listen(opts.port || null);
49 |
50 | var brown = '\033[33m',
51 | green = '\033[32m',
52 | reset = '\033[0m';
53 |
54 | var slidesLocation = "http://localhost" + ( opts.port ? ( ':' + opts.port ) : '' );
55 |
56 | console.log( brown + "reveal.js - Speaker Notes" + reset );
57 | console.log( "1. Open the slides at " + green + slidesLocation + reset );
58 | console.log( "2. Click on the link your JS console to go to the notes page" );
59 | console.log( "3. Advance through your slides and your notes will advance automatically" );
60 |
--------------------------------------------------------------------------------
/plugin/notes-server/notes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | reveal.js - Slide Notes
9 |
10 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | UPCOMING:
101 |
102 |
103 |
104 |
105 |
106 |
107 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/plugin/notes/notes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | reveal.js - Slide Notes
7 |
8 |
137 |
138 |
139 |
140 |
141 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 | UPCOMING:
156 |
157 |
158 |
159 |
160 |
Time
161 | 0:00:00 AM
162 |
163 |
164 |
Elapsed
165 | 00:00:00
166 |
167 |
168 |
169 |
170 |
171 |
172 |
266 |
267 |
268 |
--------------------------------------------------------------------------------
/plugin/notes/notes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Handles opening of and synchronization with the reveal.js
3 | * notes window.
4 | */
5 | var RevealNotes = (function() {
6 |
7 | function openNotes() {
8 | var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path
9 | jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path
10 | var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1120,height=850' );
11 |
12 | // Fires when slide is changed
13 | Reveal.addEventListener( 'slidechanged', post );
14 |
15 | // Fires when a fragment is shown
16 | Reveal.addEventListener( 'fragmentshown', post );
17 |
18 | // Fires when a fragment is hidden
19 | Reveal.addEventListener( 'fragmenthidden', post );
20 |
21 | /**
22 | * Posts the current slide data to the notes window
23 | */
24 | function post() {
25 | var slideElement = Reveal.getCurrentSlide(),
26 | slideIndices = Reveal.getIndices(),
27 | messageData;
28 |
29 | var notes = slideElement.querySelector( 'aside.notes' ),
30 | nextindexh,
31 | nextindexv;
32 |
33 | if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) {
34 | nextindexh = slideIndices.h;
35 | nextindexv = slideIndices.v + 1;
36 | } else {
37 | nextindexh = slideIndices.h + 1;
38 | nextindexv = 0;
39 | }
40 |
41 | messageData = {
42 | notes : notes ? notes.innerHTML : '',
43 | indexh : slideIndices.h,
44 | indexv : slideIndices.v,
45 | indexf : slideIndices.f,
46 | nextindexh : nextindexh,
47 | nextindexv : nextindexv,
48 | markdown : notes ? typeof notes.getAttribute( 'data-markdown' ) === 'string' : false
49 | };
50 |
51 | notesPopup.postMessage( JSON.stringify( messageData ), '*' );
52 | }
53 |
54 | // Navigate to the current slide when the notes are loaded
55 | notesPopup.addEventListener( 'load', function( event ) {
56 | post();
57 | }, false );
58 | }
59 |
60 | // If the there's a 'notes' query set, open directly
61 | if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
62 | openNotes();
63 | }
64 |
65 | // Open the notes when the 's' key is hit
66 | document.addEventListener( 'keydown', function( event ) {
67 | // Disregard the event if the target is editable or a
68 | // modifier is present
69 | if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;
70 |
71 | if( event.keyCode === 83 ) {
72 | event.preventDefault();
73 | openNotes();
74 | }
75 | }, false );
76 |
77 | return { open: openNotes };
78 | })();
79 |
--------------------------------------------------------------------------------
/plugin/postmessage/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/plugin/postmessage/postmessage.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | simple postmessage plugin
4 |
5 | Useful when a reveal slideshow is inside an iframe.
6 | It allows to call reveal methods from outside.
7 |
8 | Example:
9 | var reveal = window.frames[0];
10 |
11 | // Reveal.prev();
12 | reveal.postMessage(JSON.stringify({method: 'prev', args: []}), '*');
13 | // Reveal.next();
14 | reveal.postMessage(JSON.stringify({method: 'next', args: []}), '*');
15 | // Reveal.slide(2, 2);
16 | reveal.postMessage(JSON.stringify({method: 'slide', args: [2,2]}), '*');
17 |
18 | Add to the slideshow:
19 |
20 | dependencies: [
21 | ...
22 | { src: 'plugin/postmessage/postmessage.js', async: true, condition: function() { return !!document.body.classList; } }
23 | ]
24 |
25 | */
26 |
27 | (function (){
28 |
29 | window.addEventListener( "message", function ( event ) {
30 | var data = JSON.parse( event.data ),
31 | method = data.method,
32 | args = data.args;
33 |
34 | if( typeof Reveal[method] === 'function' ) {
35 | Reveal[method].apply( Reveal, data.args );
36 | }
37 | }, false);
38 |
39 | }());
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/plugin/print-pdf/print-pdf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * phantomjs script for printing presentations to PDF.
3 | *
4 | * Example:
5 | * phantomjs print-pdf.js "http://lab.hakim.se/reveal-js?print-pdf" reveal-demo.pdf
6 | *
7 | * By Manuel Bieh (https://github.com/manuelbieh)
8 | */
9 |
10 | // html2pdf.js
11 | var page = new WebPage();
12 | var system = require( 'system' );
13 |
14 | page.viewportSize = {
15 | width: 1024,
16 | height: 768
17 | };
18 |
19 | page.paperSize = {
20 | format: 'letter',
21 | orientation: 'landscape',
22 | margin: {
23 | left: '0',
24 | right: '0',
25 | top: '0',
26 | bottom: '0'
27 | }
28 | };
29 |
30 | var revealFile = system.args[1] || 'index.html?print-pdf';
31 | var slideFile = system.args[2] || 'slides.pdf';
32 |
33 | if( slideFile.match( /\.pdf$/gi ) === null ) {
34 | slideFile += '.pdf';
35 | }
36 |
37 | console.log( 'Printing PDF...' );
38 |
39 | page.open( revealFile, function( status ) {
40 | console.log( 'Printed succesfully' );
41 | page.render( slideFile );
42 | phantom.exit();
43 | } );
44 |
45 |
--------------------------------------------------------------------------------
/plugin/remotes/remotes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Touch-based remote controller for your presentation courtesy
3 | * of the folks at http://remotes.io
4 | */
5 |
6 | (function(window){
7 |
8 | /**
9 | * Detects if we are dealing with a touch enabled device (with some false positives)
10 | * Borrowed from modernizr: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touch.js
11 | */
12 | var hasTouch = (function(){
13 | return ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
14 | })();
15 |
16 | /**
17 | * Detects if notes are enable and the current page is opened inside an /iframe
18 | * this prevents loading Remotes.io several times
19 | */
20 | var isNotesAndIframe = (function(){
21 | return window.RevealNotes && !(self == top);
22 | })();
23 |
24 | if(!hasTouch && !isNotesAndIframe){
25 | head.ready( 'remotes.ne.min.js', function() {
26 | new Remotes("preview")
27 | .on("swipe-left", function(e){ Reveal.right(); })
28 | .on("swipe-right", function(e){ Reveal.left(); })
29 | .on("swipe-up", function(e){ Reveal.down(); })
30 | .on("swipe-down", function(e){ Reveal.up(); })
31 | .on("tap", function(e){ Reveal.next(); })
32 | .on("zoom-out", function(e){ Reveal.toggleOverview(true); })
33 | .on("zoom-in", function(e){ Reveal.toggleOverview(false); })
34 | ;
35 | } );
36 |
37 | head.js('https://hakim-static.s3.amazonaws.com/reveal-js/remotes.ne.min.js');
38 | }
39 | })(window);
--------------------------------------------------------------------------------
/plugin/search/search.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Handles finding a text string anywhere in the slides and showing the next occurrence to the user
3 | * by navigatating to that slide and highlighting it.
4 | *
5 | * By Jon Snyder , February 2013
6 | */
7 |
8 | var RevealSearch = (function() {
9 |
10 | var matchedSlides;
11 | var currentMatchedIndex;
12 | var searchboxDirty;
13 | var myHilitor;
14 |
15 | // Original JavaScript code by Chirp Internet: www.chirp.com.au
16 | // Please acknowledge use of this code by including this header.
17 | // 2/2013 jon: modified regex to display any match, not restricted to word boundaries.
18 |
19 | function Hilitor(id, tag)
20 | {
21 |
22 | var targetNode = document.getElementById(id) || document.body;
23 | var hiliteTag = tag || "EM";
24 | var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM|SPAN)$");
25 | var colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"];
26 | var wordColor = [];
27 | var colorIdx = 0;
28 | var matchRegex = "";
29 | var matchingSlides = [];
30 |
31 | this.setRegex = function(input)
32 | {
33 | input = input.replace(/^[^\w]+|[^\w]+$/g, "").replace(/[^\w'-]+/g, "|");
34 | matchRegex = new RegExp("(" + input + ")","i");
35 | }
36 |
37 | this.getRegex = function()
38 | {
39 | return matchRegex.toString().replace(/^\/\\b\(|\)\\b\/i$/g, "").replace(/\|/g, " ");
40 | }
41 |
42 | // recursively apply word highlighting
43 | this.hiliteWords = function(node)
44 | {
45 | if(node == undefined || !node) return;
46 | if(!matchRegex) return;
47 | if(skipTags.test(node.nodeName)) return;
48 |
49 | if(node.hasChildNodes()) {
50 | for(var i=0; i < node.childNodes.length; i++)
51 | this.hiliteWords(node.childNodes[i]);
52 | }
53 | if(node.nodeType == 3) { // NODE_TEXT
54 | if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) {
55 | //find the slide's section element and save it in our list of matching slides
56 | var secnode = node.parentNode;
57 | while (secnode.nodeName != 'SECTION') {
58 | secnode = secnode.parentNode;
59 | }
60 |
61 | var slideIndex = Reveal.getIndices(secnode);
62 | var slidelen = matchingSlides.length;
63 | var alreadyAdded = false;
64 | for (var i=0; i < slidelen; i++) {
65 | if ( (matchingSlides[i].h === slideIndex.h) && (matchingSlides[i].v === slideIndex.v) ) {
66 | alreadyAdded = true;
67 | }
68 | }
69 | if (! alreadyAdded) {
70 | matchingSlides.push(slideIndex);
71 | }
72 |
73 | if(!wordColor[regs[0].toLowerCase()]) {
74 | wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length];
75 | }
76 |
77 | var match = document.createElement(hiliteTag);
78 | match.appendChild(document.createTextNode(regs[0]));
79 | match.style.backgroundColor = wordColor[regs[0].toLowerCase()];
80 | match.style.fontStyle = "inherit";
81 | match.style.color = "#000";
82 |
83 | var after = node.splitText(regs.index);
84 | after.nodeValue = after.nodeValue.substring(regs[0].length);
85 | node.parentNode.insertBefore(match, after);
86 | }
87 | }
88 | };
89 |
90 | // remove highlighting
91 | this.remove = function()
92 | {
93 | var arr = document.getElementsByTagName(hiliteTag);
94 | while(arr.length && (el = arr[0])) {
95 | el.parentNode.replaceChild(el.firstChild, el);
96 | }
97 | };
98 |
99 | // start highlighting at target node
100 | this.apply = function(input)
101 | {
102 | if(input == undefined || !input) return;
103 | this.remove();
104 | this.setRegex(input);
105 | this.hiliteWords(targetNode);
106 | return matchingSlides;
107 | };
108 |
109 | }
110 |
111 | function openSearch() {
112 | //ensure the search term input dialog is visible and has focus:
113 | var inputbox = document.getElementById("searchinput");
114 | inputbox.style.display = "inline";
115 | inputbox.focus();
116 | inputbox.select();
117 | }
118 |
119 | function toggleSearch() {
120 | var inputbox = document.getElementById("searchinput");
121 | if (inputbox.style.display !== "inline") {
122 | openSearch();
123 | }
124 | else {
125 | inputbox.style.display = "none";
126 | myHilitor.remove();
127 | }
128 | }
129 |
130 | function doSearch() {
131 | //if there's been a change in the search term, perform a new search:
132 | if (searchboxDirty) {
133 | var searchstring = document.getElementById("searchinput").value;
134 |
135 | //find the keyword amongst the slides
136 | myHilitor = new Hilitor("slidecontent");
137 | matchedSlides = myHilitor.apply(searchstring);
138 | currentMatchedIndex = 0;
139 | }
140 |
141 | //navigate to the next slide that has the keyword, wrapping to the first if necessary
142 | if (matchedSlides.length && (matchedSlides.length <= currentMatchedIndex)) {
143 | currentMatchedIndex = 0;
144 | }
145 | if (matchedSlides.length > currentMatchedIndex) {
146 | Reveal.slide(matchedSlides[currentMatchedIndex].h, matchedSlides[currentMatchedIndex].v);
147 | currentMatchedIndex++;
148 | }
149 | }
150 |
151 | var dom = {};
152 | dom.wrapper = document.querySelector( '.reveal' );
153 |
154 | if( !dom.wrapper.querySelector( '.searchbox' ) ) {
155 | var searchElement = document.createElement( 'div' );
156 | searchElement.id = "searchinputdiv";
157 | searchElement.classList.add( 'searchdiv' );
158 | searchElement.style.position = 'absolute';
159 | searchElement.style.top = '10px';
160 | searchElement.style.left = '10px';
161 | //embedded base64 search icon Designed by Sketchdock - http://www.sketchdock.com/:
162 | searchElement.innerHTML = '
';
163 | dom.wrapper.appendChild( searchElement );
164 | }
165 |
166 | document.getElementById("searchbutton").addEventListener( 'click', function(event) {
167 | doSearch();
168 | }, false );
169 |
170 | document.getElementById("searchinput").addEventListener( 'keyup', function( event ) {
171 | switch (event.keyCode) {
172 | case 13:
173 | event.preventDefault();
174 | doSearch();
175 | searchboxDirty = false;
176 | break;
177 | default:
178 | searchboxDirty = true;
179 | }
180 | }, false );
181 |
182 | // Open the search when the 's' key is hit (yes, this conflicts with the notes plugin, disabling for now)
183 | /*
184 | document.addEventListener( 'keydown', function( event ) {
185 | // Disregard the event if the target is editable or a
186 | // modifier is present
187 | if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;
188 |
189 | if( event.keyCode === 83 ) {
190 | event.preventDefault();
191 | openSearch();
192 | }
193 | }, false );
194 | */
195 | return { open: openSearch };
196 | })();
197 |
--------------------------------------------------------------------------------
/plugin/zoom-js/zoom.js:
--------------------------------------------------------------------------------
1 | // Custom reveal.js integration
2 | (function(){
3 | var isEnabled = true;
4 |
5 | document.querySelector( '.reveal' ).addEventListener( 'mousedown', function( event ) {
6 | var modifier = ( Reveal.getConfig().zoomKey ? Reveal.getConfig().zoomKey : 'alt' ) + 'Key';
7 |
8 | if( event[ modifier ] && isEnabled ) {
9 | event.preventDefault();
10 | zoom.to({ element: event.target, pan: false });
11 | }
12 | } );
13 |
14 | Reveal.addEventListener( 'overviewshown', function() { isEnabled = false; } );
15 | Reveal.addEventListener( 'overviewhidden', function() { isEnabled = true; } );
16 | })();
17 |
18 | /*!
19 | * zoom.js 0.2 (modified version for use with reveal.js)
20 | * http://lab.hakim.se/zoom-js
21 | * MIT licensed
22 | *
23 | * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
24 | */
25 | var zoom = (function(){
26 |
27 | // The current zoom level (scale)
28 | var level = 1;
29 |
30 | // The current mouse position, used for panning
31 | var mouseX = 0,
32 | mouseY = 0;
33 |
34 | // Timeout before pan is activated
35 | var panEngageTimeout = -1,
36 | panUpdateInterval = -1;
37 |
38 | var currentOptions = null;
39 |
40 | // Check for transform support so that we can fallback otherwise
41 | var supportsTransforms = 'WebkitTransform' in document.body.style ||
42 | 'MozTransform' in document.body.style ||
43 | 'msTransform' in document.body.style ||
44 | 'OTransform' in document.body.style ||
45 | 'transform' in document.body.style;
46 |
47 | if( supportsTransforms ) {
48 | // The easing that will be applied when we zoom in/out
49 | document.body.style.transition = 'transform 0.8s ease';
50 | document.body.style.OTransition = '-o-transform 0.8s ease';
51 | document.body.style.msTransition = '-ms-transform 0.8s ease';
52 | document.body.style.MozTransition = '-moz-transform 0.8s ease';
53 | document.body.style.WebkitTransition = '-webkit-transform 0.8s ease';
54 | }
55 |
56 | // Zoom out if the user hits escape
57 | document.addEventListener( 'keyup', function( event ) {
58 | if( level !== 1 && event.keyCode === 27 ) {
59 | zoom.out();
60 | }
61 | }, false );
62 |
63 | // Monitor mouse movement for panning
64 | document.addEventListener( 'mousemove', function( event ) {
65 | if( level !== 1 ) {
66 | mouseX = event.clientX;
67 | mouseY = event.clientY;
68 | }
69 | }, false );
70 |
71 | /**
72 | * Applies the CSS required to zoom in, prioritizes use of CSS3
73 | * transforms but falls back on zoom for IE.
74 | *
75 | * @param {Number} pageOffsetX
76 | * @param {Number} pageOffsetY
77 | * @param {Number} elementOffsetX
78 | * @param {Number} elementOffsetY
79 | * @param {Number} scale
80 | */
81 | function magnify( pageOffsetX, pageOffsetY, elementOffsetX, elementOffsetY, scale ) {
82 |
83 | if( supportsTransforms ) {
84 | var origin = pageOffsetX +'px '+ pageOffsetY +'px',
85 | transform = 'translate('+ -elementOffsetX +'px,'+ -elementOffsetY +'px) scale('+ scale +')';
86 |
87 | document.body.style.transformOrigin = origin;
88 | document.body.style.OTransformOrigin = origin;
89 | document.body.style.msTransformOrigin = origin;
90 | document.body.style.MozTransformOrigin = origin;
91 | document.body.style.WebkitTransformOrigin = origin;
92 |
93 | document.body.style.transform = transform;
94 | document.body.style.OTransform = transform;
95 | document.body.style.msTransform = transform;
96 | document.body.style.MozTransform = transform;
97 | document.body.style.WebkitTransform = transform;
98 | }
99 | else {
100 | // Reset all values
101 | if( scale === 1 ) {
102 | document.body.style.position = '';
103 | document.body.style.left = '';
104 | document.body.style.top = '';
105 | document.body.style.width = '';
106 | document.body.style.height = '';
107 | document.body.style.zoom = '';
108 | }
109 | // Apply scale
110 | else {
111 | document.body.style.position = 'relative';
112 | document.body.style.left = ( - ( pageOffsetX + elementOffsetX ) / scale ) + 'px';
113 | document.body.style.top = ( - ( pageOffsetY + elementOffsetY ) / scale ) + 'px';
114 | document.body.style.width = ( scale * 100 ) + '%';
115 | document.body.style.height = ( scale * 100 ) + '%';
116 | document.body.style.zoom = scale;
117 | }
118 | }
119 |
120 | level = scale;
121 |
122 | if( level !== 1 && document.documentElement.classList ) {
123 | document.documentElement.classList.add( 'zoomed' );
124 | }
125 | else {
126 | document.documentElement.classList.remove( 'zoomed' );
127 | }
128 | }
129 |
130 | /**
131 | * Pan the document when the mosue cursor approaches the edges
132 | * of the window.
133 | */
134 | function pan() {
135 | var range = 0.12,
136 | rangeX = window.innerWidth * range,
137 | rangeY = window.innerHeight * range,
138 | scrollOffset = getScrollOffset();
139 |
140 | // Up
141 | if( mouseY < rangeY ) {
142 | window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) );
143 | }
144 | // Down
145 | else if( mouseY > window.innerHeight - rangeY ) {
146 | window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) );
147 | }
148 |
149 | // Left
150 | if( mouseX < rangeX ) {
151 | window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y );
152 | }
153 | // Right
154 | else if( mouseX > window.innerWidth - rangeX ) {
155 | window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y );
156 | }
157 | }
158 |
159 | function getScrollOffset() {
160 | return {
161 | x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset,
162 | y: window.scrollY !== undefined ? window.scrollY : window.pageXYffset
163 | }
164 | }
165 |
166 | return {
167 | /**
168 | * Zooms in on either a rectangle or HTML element.
169 | *
170 | * @param {Object} options
171 | * - element: HTML element to zoom in on
172 | * OR
173 | * - x/y: coordinates in non-transformed space to zoom in on
174 | * - width/height: the portion of the screen to zoom in on
175 | * - scale: can be used instead of width/height to explicitly set scale
176 | */
177 | to: function( options ) {
178 | // Due to an implementation limitation we can't zoom in
179 | // to another element without zooming out first
180 | if( level !== 1 ) {
181 | zoom.out();
182 | }
183 | else {
184 | options.x = options.x || 0;
185 | options.y = options.y || 0;
186 |
187 | // If an element is set, that takes precedence
188 | if( !!options.element ) {
189 | // Space around the zoomed in element to leave on screen
190 | var padding = 20;
191 |
192 | options.width = options.element.getBoundingClientRect().width + ( padding * 2 );
193 | options.height = options.element.getBoundingClientRect().height + ( padding * 2 );
194 | options.x = options.element.getBoundingClientRect().left - padding;
195 | options.y = options.element.getBoundingClientRect().top - padding;
196 | }
197 |
198 | // If width/height values are set, calculate scale from those values
199 | if( options.width !== undefined && options.height !== undefined ) {
200 | options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 );
201 | }
202 |
203 | if( options.scale > 1 ) {
204 | options.x *= options.scale;
205 | options.y *= options.scale;
206 |
207 | var scrollOffset = getScrollOffset();
208 |
209 | if( options.element ) {
210 | scrollOffset.x -= ( window.innerWidth - ( options.width * options.scale ) ) / 2;
211 | }
212 |
213 | magnify( scrollOffset.x, scrollOffset.y, options.x, options.y, options.scale );
214 |
215 | if( options.pan !== false ) {
216 |
217 | // Wait with engaging panning as it may conflict with the
218 | // zoom transition
219 | panEngageTimeout = setTimeout( function() {
220 | panUpdateInterval = setInterval( pan, 1000 / 60 );
221 | }, 800 );
222 |
223 | }
224 | }
225 |
226 | currentOptions = options;
227 | }
228 | },
229 |
230 | /**
231 | * Resets the document zoom state to its default.
232 | */
233 | out: function() {
234 | clearTimeout( panEngageTimeout );
235 | clearInterval( panUpdateInterval );
236 |
237 | var scrollOffset = getScrollOffset();
238 |
239 | if( currentOptions && currentOptions.element ) {
240 | scrollOffset.x -= ( window.innerWidth - ( currentOptions.width * currentOptions.scale ) ) / 2;
241 | }
242 |
243 | magnify( scrollOffset.x, scrollOffset.y, 0, 0, 1 );
244 |
245 | level = 1;
246 | },
247 |
248 | // Alias
249 | magnify: function( options ) { this.to( options ) },
250 | reset: function() { this.out() },
251 |
252 | zoomLevel: function() {
253 | return level;
254 | }
255 | }
256 |
257 | })();
258 |
259 |
--------------------------------------------------------------------------------
/test/examples/assets/image1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/test/examples/assets/image1.png
--------------------------------------------------------------------------------
/test/examples/assets/image2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlearchive/firebase-intro-presentation/c7ffb50207bcfedf9b29ed5c2db63ca9e5aac1b9/test/examples/assets/image2.png
--------------------------------------------------------------------------------
/test/examples/barebones.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Barebones
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Barebones Presentation
20 | This example contains the bare minimum includes and markup required to run a reveal.js presentation.
21 |
22 |
23 |
24 | No Theme
25 | There's no theme included, so it will fall back on browser defaults.
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/test/examples/embedded-media.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Embedded Media
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Embedded Media Test
23 |
24 |
25 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/test/examples/math.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Math Plugin
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | reveal.js Math Plugin
23 | A thin wrapper for MathJax
24 |
25 |
26 |
27 | The Lorenz Equations
28 |
29 | \[\begin{aligned}
30 | \dot{x} & = \sigma(y-x) \\
31 | \dot{y} & = \rho x - y - xz \\
32 | \dot{z} & = -\beta z + xy
33 | \end{aligned} \]
34 |
35 |
36 |
37 | The Cauchy-Schwarz Inequality
38 |
39 |
42 |
43 |
44 |
45 | A Cross Product Formula
46 |
47 | \[\mathbf{V}_1 \times \mathbf{V}_2 = \begin{vmatrix}
48 | \mathbf{i} & \mathbf{j} & \mathbf{k} \\
49 | \frac{\partial X}{\partial u} & \frac{\partial Y}{\partial u} & 0 \\
50 | \frac{\partial X}{\partial v} & \frac{\partial Y}{\partial v} & 0
51 | \end{vmatrix} \]
52 |
53 |
54 |
55 | The probability of getting \(k\) heads when flipping \(n\) coins is
56 |
57 | \[P(E) = {n \choose k} p^k (1-p)^{ n-k} \]
58 |
59 |
60 |
61 | An Identity of Ramanujan
62 |
63 | \[ \frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}-\phi\Bigr) e^{\frac25 \pi}} =
64 | 1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}}
65 | {1+\frac{e^{-8\pi}} {1+\ldots} } } } \]
66 |
67 |
68 |
69 | A Rogers-Ramanujan Identity
70 |
71 | \[ 1 + \frac{q^2}{(1-q)}+\frac{q^6}{(1-q)(1-q^2)}+\cdots =
72 | \prod_{j=0}^{\infty}\frac{1}{(1-q^{5j+2})(1-q^{5j+3})}\]
73 |
74 |
75 |
76 | Maxwell’s Equations
77 |
78 | \[ \begin{aligned}
79 | \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 \\
80 | \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
81 | \nabla \cdot \vec{\mathbf{B}} & = 0 \end{aligned}
82 | \]
83 |
84 |
85 |
86 |
87 | The Lorenz Equations
88 |
89 |
90 | \[\begin{aligned}
91 | \dot{x} & = \sigma(y-x) \\
92 | \dot{y} & = \rho x - y - xz \\
93 | \dot{z} & = -\beta z + xy
94 | \end{aligned} \]
95 |
96 |
97 |
98 |
99 | The Cauchy-Schwarz Inequality
100 |
101 |
102 | \[ \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) \]
103 |
104 |
105 |
106 |
107 | A Cross Product Formula
108 |
109 |
110 | \[\mathbf{V}_1 \times \mathbf{V}_2 = \begin{vmatrix}
111 | \mathbf{i} & \mathbf{j} & \mathbf{k} \\
112 | \frac{\partial X}{\partial u} & \frac{\partial Y}{\partial u} & 0 \\
113 | \frac{\partial X}{\partial v} & \frac{\partial Y}{\partial v} & 0
114 | \end{vmatrix} \]
115 |
116 |
117 |
118 |
119 | The probability of getting \(k\) heads when flipping \(n\) coins is
120 |
121 |
122 | \[P(E) = {n \choose k} p^k (1-p)^{ n-k} \]
123 |
124 |
125 |
126 |
127 | An Identity of Ramanujan
128 |
129 |
130 | \[ \frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}-\phi\Bigr) e^{\frac25 \pi}} =
131 | 1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}}
132 | {1+\frac{e^{-8\pi}} {1+\ldots} } } } \]
133 |
134 |
135 |
136 |
137 | A Rogers-Ramanujan Identity
138 |
139 |
140 | \[ 1 + \frac{q^2}{(1-q)}+\frac{q^6}{(1-q)(1-q^2)}+\cdots =
141 | \prod_{j=0}^{\infty}\frac{1}{(1-q^{5j+2})(1-q^{5j+3})}\]
142 |
143 |
144 |
145 |
146 | Maxwell’s Equations
147 |
148 |
149 | \[ \begin{aligned}
150 | \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 \\
151 | \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
152 | \nabla \cdot \vec{\mathbf{B}} & = 0 \end{aligned}
153 | \]
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/test/examples/slide-backgrounds.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Slide Backgrounds
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | data-background: #00ffff
23 |
24 |
25 |
26 | data-background: #bb00bb
27 |
28 |
29 |
30 |
31 | data-background: #ff0000
32 |
33 |
34 | data-background: rgba(0, 0, 0, 0.2)
35 |
36 |
37 | data-background: salmon
38 |
39 |
40 |
41 |
42 |
43 | Background applied to stack
44 |
45 |
46 | Background applied to stack
47 |
48 |
49 | Background applied to slide inside of stack
50 |
51 |
52 |
53 |
54 | Background image
55 |
56 |
57 |
58 |
59 | Background image
60 |
61 |
62 | Background image
63 |
64 |
65 |
66 |
67 | Background image
68 | data-background-size="100px" data-background-repeat="repeat" data-background-color="#111"
69 |
70 |
71 |
72 | Same background twice (1/2)
73 |
74 |
75 | Same background twice (2/2)
76 |
77 |
78 |
79 |
80 | Same background twice vertical (1/2)
81 |
82 |
83 | Same background twice vertical (2/2)
84 |
85 |
86 |
87 |
88 | Same background from horizontal to vertical (1/3)
89 |
90 |
91 |
92 | Same background from horizontal to vertical (2/3)
93 |
94 |
95 | Same background from horizontal to vertical (3/3)
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/test/qunit-1.12.0.css:
--------------------------------------------------------------------------------
1 | /**
2 | * QUnit v1.12.0 - A JavaScript Unit Testing Framework
3 | *
4 | * http://qunitjs.com
5 | *
6 | * Copyright 2012 jQuery Foundation and other contributors
7 | * Released under the MIT license.
8 | * http://jquery.org/license
9 | */
10 |
11 | /** Font Family and Sizes */
12 |
13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
15 | }
16 |
17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
18 | #qunit-tests { font-size: smaller; }
19 |
20 |
21 | /** Resets */
22 |
23 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
24 | margin: 0;
25 | padding: 0;
26 | }
27 |
28 |
29 | /** Header */
30 |
31 | #qunit-header {
32 | padding: 0.5em 0 0.5em 1em;
33 |
34 | color: #8699a4;
35 | background-color: #0d3349;
36 |
37 | font-size: 1.5em;
38 | line-height: 1em;
39 | font-weight: normal;
40 |
41 | border-radius: 5px 5px 0 0;
42 | -moz-border-radius: 5px 5px 0 0;
43 | -webkit-border-top-right-radius: 5px;
44 | -webkit-border-top-left-radius: 5px;
45 | }
46 |
47 | #qunit-header a {
48 | text-decoration: none;
49 | color: #c2ccd1;
50 | }
51 |
52 | #qunit-header a:hover,
53 | #qunit-header a:focus {
54 | color: #fff;
55 | }
56 |
57 | #qunit-testrunner-toolbar label {
58 | display: inline-block;
59 | padding: 0 .5em 0 .1em;
60 | }
61 |
62 | #qunit-banner {
63 | height: 5px;
64 | }
65 |
66 | #qunit-testrunner-toolbar {
67 | padding: 0.5em 0 0.5em 2em;
68 | color: #5E740B;
69 | background-color: #eee;
70 | overflow: hidden;
71 | }
72 |
73 | #qunit-userAgent {
74 | padding: 0.5em 0 0.5em 2.5em;
75 | background-color: #2b81af;
76 | color: #fff;
77 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
78 | }
79 |
80 | #qunit-modulefilter-container {
81 | float: right;
82 | }
83 |
84 | /** Tests: Pass/Fail */
85 |
86 | #qunit-tests {
87 | list-style-position: inside;
88 | }
89 |
90 | #qunit-tests li {
91 | padding: 0.4em 0.5em 0.4em 2.5em;
92 | border-bottom: 1px solid #fff;
93 | list-style-position: inside;
94 | }
95 |
96 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
97 | display: none;
98 | }
99 |
100 | #qunit-tests li strong {
101 | cursor: pointer;
102 | }
103 |
104 | #qunit-tests li a {
105 | padding: 0.5em;
106 | color: #c2ccd1;
107 | text-decoration: none;
108 | }
109 | #qunit-tests li a:hover,
110 | #qunit-tests li a:focus {
111 | color: #000;
112 | }
113 |
114 | #qunit-tests li .runtime {
115 | float: right;
116 | font-size: smaller;
117 | }
118 |
119 | .qunit-assert-list {
120 | margin-top: 0.5em;
121 | padding: 0.5em;
122 |
123 | background-color: #fff;
124 |
125 | border-radius: 5px;
126 | -moz-border-radius: 5px;
127 | -webkit-border-radius: 5px;
128 | }
129 |
130 | .qunit-collapsed {
131 | display: none;
132 | }
133 |
134 | #qunit-tests table {
135 | border-collapse: collapse;
136 | margin-top: .2em;
137 | }
138 |
139 | #qunit-tests th {
140 | text-align: right;
141 | vertical-align: top;
142 | padding: 0 .5em 0 0;
143 | }
144 |
145 | #qunit-tests td {
146 | vertical-align: top;
147 | }
148 |
149 | #qunit-tests pre {
150 | margin: 0;
151 | white-space: pre-wrap;
152 | word-wrap: break-word;
153 | }
154 |
155 | #qunit-tests del {
156 | background-color: #e0f2be;
157 | color: #374e0c;
158 | text-decoration: none;
159 | }
160 |
161 | #qunit-tests ins {
162 | background-color: #ffcaca;
163 | color: #500;
164 | text-decoration: none;
165 | }
166 |
167 | /*** Test Counts */
168 |
169 | #qunit-tests b.counts { color: black; }
170 | #qunit-tests b.passed { color: #5E740B; }
171 | #qunit-tests b.failed { color: #710909; }
172 |
173 | #qunit-tests li li {
174 | padding: 5px;
175 | background-color: #fff;
176 | border-bottom: none;
177 | list-style-position: inside;
178 | }
179 |
180 | /*** Passing Styles */
181 |
182 | #qunit-tests li li.pass {
183 | color: #3c510c;
184 | background-color: #fff;
185 | border-left: 10px solid #C6E746;
186 | }
187 |
188 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
189 | #qunit-tests .pass .test-name { color: #366097; }
190 |
191 | #qunit-tests .pass .test-actual,
192 | #qunit-tests .pass .test-expected { color: #999999; }
193 |
194 | #qunit-banner.qunit-pass { background-color: #C6E746; }
195 |
196 | /*** Failing Styles */
197 |
198 | #qunit-tests li li.fail {
199 | color: #710909;
200 | background-color: #fff;
201 | border-left: 10px solid #EE5757;
202 | white-space: pre;
203 | }
204 |
205 | #qunit-tests > li:last-child {
206 | border-radius: 0 0 5px 5px;
207 | -moz-border-radius: 0 0 5px 5px;
208 | -webkit-border-bottom-right-radius: 5px;
209 | -webkit-border-bottom-left-radius: 5px;
210 | }
211 |
212 | #qunit-tests .fail { color: #000000; background-color: #EE5757; }
213 | #qunit-tests .fail .test-name,
214 | #qunit-tests .fail .module-name { color: #000000; }
215 |
216 | #qunit-tests .fail .test-actual { color: #EE5757; }
217 | #qunit-tests .fail .test-expected { color: green; }
218 |
219 | #qunit-banner.qunit-fail { background-color: #EE5757; }
220 |
221 |
222 | /** Result */
223 |
224 | #qunit-testresult {
225 | padding: 0.5em 0.5em 0.5em 2.5em;
226 |
227 | color: #2b81af;
228 | background-color: #D2E0E6;
229 |
230 | border-bottom: 1px solid white;
231 | }
232 | #qunit-testresult .module-name {
233 | font-weight: bold;
234 | }
235 |
236 | /** Fixture */
237 |
238 | #qunit-fixture {
239 | position: absolute;
240 | top: -10000px;
241 | left: -10000px;
242 | width: 1000px;
243 | height: 1000px;
244 | }
--------------------------------------------------------------------------------
/test/test-markdown-element-attributes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Test Markdown Element Attributes
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
74 |
75 |
76 |
77 |
91 |
92 |
99 |
100 |
109 |
110 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/test/test-markdown-element-attributes.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | Reveal.addEventListener( 'ready', function() {
4 |
5 | QUnit.module( 'Markdown' );
6 |
7 | test( 'Vertical separator', function() {
8 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section' ).length, 4, 'found four slides' );
9 | });
10 |
11 |
12 | test( 'Attributes on element header in vertical slides', function() {
13 | strictEqual( document.querySelectorAll( '.reveal .slides section>section h2.fragment.fade-out' ).length, 1, 'found one vertical slide with class fragment.fade-out on header' );
14 | strictEqual( document.querySelectorAll( '.reveal .slides section>section h2.fragment.shrink' ).length, 1, 'found one vertical slide with class fragment.shrink on header' );
15 | });
16 |
17 | test( 'Attributes on element paragraphs in vertical slides', function() {
18 | strictEqual( document.querySelectorAll( '.reveal .slides section>section p.fragment.grow' ).length, 2, 'found a vertical slide with two paragraphs with class fragment.grow' );
19 | });
20 |
21 | test( 'Attributes on element list items in vertical slides', function() {
22 | strictEqual( document.querySelectorAll( '.reveal .slides section>section li.fragment.roll-in' ).length, 3, 'found a vertical slide with three list items with class fragment.roll-in' );
23 | });
24 |
25 | test( 'Attributes on element paragraphs in horizontal slides', function() {
26 | strictEqual( document.querySelectorAll( '.reveal .slides section p.fragment.highlight-red' ).length, 4, 'found a horizontal slide with four paragraphs with class fragment.grow' );
27 | });
28 | test( 'Attributes on element list items in horizontal slides', function() {
29 | strictEqual( document.querySelectorAll( '.reveal .slides section li.fragment.highlight-green' ).length, 5, 'found a horizontal slide with five list items with class fragment.roll-in' );
30 | });
31 | test( 'Attributes on element list items in horizontal slides', function() {
32 | strictEqual( document.querySelectorAll( '.reveal .slides section img.reveal.stretch' ).length, 1, 'found a horizontal slide with stretched image, class img.reveal.stretch' );
33 | });
34 |
35 | test( 'Attributes on elements in vertical slides with default element attribute separator', function() {
36 | strictEqual( document.querySelectorAll( '.reveal .slides section h2.fragment.highlight-red' ).length, 2, 'found two h2 titles with fragment highlight-red in vertical slides with default element attribute separator' );
37 | });
38 |
39 | test( 'Attributes on elements in single slides with default element attribute separator', function() {
40 | strictEqual( document.querySelectorAll( '.reveal .slides section p.fragment.highlight-blue' ).length, 3, 'found three elements with fragment highlight-blue in single slide with default element attribute separator' );
41 | });
42 |
43 | } );
44 |
45 | Reveal.initialize();
46 |
47 |
--------------------------------------------------------------------------------
/test/test-markdown-slide-attributes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Test Markdown Attributes
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
57 |
58 |
89 |
90 |
96 |
97 |
103 |
104 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/test/test-markdown-slide-attributes.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | Reveal.addEventListener( 'ready', function() {
4 |
5 | QUnit.module( 'Markdown' );
6 |
7 | test( 'Vertical separator', function() {
8 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section' ).length, 6, 'found six vertical slides' );
9 | });
10 |
11 | test( 'Id on slide', function() {
12 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section#slide2' ).length, 1, 'found one slide with id slide2' );
13 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section a[href="#/slide2"]' ).length, 1, 'found one slide with a link to slide2' );
14 | });
15 |
16 | test( 'data-background attributes', function() {
17 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section[data-background="#A0C66B"]' ).length, 1, 'found one vertical slide with data-background="#A0C66B"' );
18 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section[data-background="#ff0000"]' ).length, 1, 'found one vertical slide with data-background="#ff0000"' );
19 | strictEqual( document.querySelectorAll( '.reveal .slides>section[data-background="#C6916B"]' ).length, 1, 'found one slide with data-background="#C6916B"' );
20 | });
21 |
22 | test( 'data-transition attributes', function() {
23 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section[data-transition="zoom"]' ).length, 1, 'found one vertical slide with data-transition="zoom"' );
24 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section[data-transition="fade"]' ).length, 1, 'found one vertical slide with data-transition="fade"' );
25 | strictEqual( document.querySelectorAll( '.reveal .slides section [data-transition="zoom"]' ).length, 1, 'found one slide with data-transition="zoom"' );
26 | });
27 |
28 | test( 'data-background attributes with default separator', function() {
29 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section[data-background="#A7C66B"]' ).length, 1, 'found one vertical slide with data-background="#A0C66B"' );
30 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section[data-background="#f70000"]' ).length, 1, 'found one vertical slide with data-background="#ff0000"' );
31 | strictEqual( document.querySelectorAll( '.reveal .slides>section[data-background="#C7916B"]' ).length, 1, 'found one slide with data-background="#C6916B"' );
32 | });
33 |
34 | test( 'data-transition attributes with default separator', function() {
35 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section[data-transition="concave"]' ).length, 1, 'found one vertical slide with data-transition="zoom"' );
36 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section[data-transition="page"]' ).length, 1, 'found one vertical slide with data-transition="fade"' );
37 | strictEqual( document.querySelectorAll( '.reveal .slides section [data-transition="concave"]' ).length, 1, 'found one slide with data-transition="zoom"' );
38 | });
39 |
40 | test( 'data-transition attributes with inline content', function() {
41 | strictEqual( document.querySelectorAll( '.reveal .slides>section[data-background="#ff0000"]' ).length, 3, 'found three horizontal slides with data-background="#ff0000"' );
42 | });
43 |
44 | } );
45 |
46 | Reveal.initialize();
47 |
48 |
--------------------------------------------------------------------------------
/test/test-markdown.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Test Markdown
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/test/test-markdown.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | Reveal.addEventListener( 'ready', function() {
4 |
5 | QUnit.module( 'Markdown' );
6 |
7 | test( 'Vertical separator', function() {
8 | strictEqual( document.querySelectorAll( '.reveal .slides>section>section' ).length, 2, 'found two slides' );
9 | });
10 |
11 |
12 | } );
13 |
14 | Reveal.initialize();
15 |
16 |
--------------------------------------------------------------------------------
/test/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Tests
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
26 |
37 |
38 |
39 |
40 | 3.1
41 |
42 | - 4.1
43 | - 4.2
44 | - 4.3
45 |
46 |
47 |
48 |
55 |
56 |
57 | 3.3
58 |
59 | - 3.3.1
60 | - 3.3.2
61 | - 3.3.3
62 |
63 |
64 |
65 |
66 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 |
2 | // These tests expect the DOM to contain a presentation
3 | // with the following slide structure:
4 | //
5 | // 1
6 | // 2 - Three sub-slides
7 | // 3 - Three fragment elements
8 | // 3 - Two fragments with same data-fragment-index
9 | // 4
10 |
11 |
12 | Reveal.addEventListener( 'ready', function() {
13 |
14 | // ---------------------------------------------------------------
15 | // DOM TESTS
16 |
17 | QUnit.module( 'DOM' );
18 |
19 | test( 'Initial slides classes', function() {
20 | var horizontalSlides = document.querySelectorAll( '.reveal .slides>section' )
21 |
22 | strictEqual( document.querySelectorAll( '.reveal .slides section.past' ).length, 0, 'no .past slides' );
23 | strictEqual( document.querySelectorAll( '.reveal .slides section.present' ).length, 1, 'one .present slide' );
24 | strictEqual( document.querySelectorAll( '.reveal .slides>section.future' ).length, horizontalSlides.length - 1, 'remaining horizontal slides are .future' );
25 |
26 | strictEqual( document.querySelectorAll( '.reveal .slides section.stack' ).length, 2, 'two .stacks' );
27 |
28 | ok( document.querySelectorAll( '.reveal .slides section.stack' )[0].querySelectorAll( '.future' ).length > 0, 'vertical slides are given .future' );
29 | });
30 |
31 | // ---------------------------------------------------------------
32 | // API TESTS
33 |
34 | QUnit.module( 'API' );
35 |
36 | test( 'Reveal.isReady', function() {
37 | strictEqual( Reveal.isReady(), true, 'returns true' );
38 | });
39 |
40 | test( 'Reveal.isOverview', function() {
41 | strictEqual( Reveal.isOverview(), false, 'false by default' );
42 |
43 | Reveal.toggleOverview();
44 | strictEqual( Reveal.isOverview(), true, 'true after toggling on' );
45 |
46 | Reveal.toggleOverview();
47 | strictEqual( Reveal.isOverview(), false, 'false after toggling off' );
48 | });
49 |
50 | test( 'Reveal.isPaused', function() {
51 | strictEqual( Reveal.isPaused(), false, 'false by default' );
52 |
53 | Reveal.togglePause();
54 | strictEqual( Reveal.isPaused(), true, 'true after pausing' );
55 |
56 | Reveal.togglePause();
57 | strictEqual( Reveal.isPaused(), false, 'false after resuming' );
58 | });
59 |
60 | test( 'Reveal.isFirstSlide', function() {
61 | Reveal.slide( 0, 0 );
62 | strictEqual( Reveal.isFirstSlide(), true, 'true after Reveal.slide( 0, 0 )' );
63 |
64 | Reveal.slide( 1, 0 );
65 | strictEqual( Reveal.isFirstSlide(), false, 'false after Reveal.slide( 1, 0 )' );
66 |
67 | Reveal.slide( 0, 0 );
68 | strictEqual( Reveal.isFirstSlide(), true, 'true after Reveal.slide( 0, 0 )' );
69 | });
70 |
71 | test( 'Reveal.isLastSlide', function() {
72 | Reveal.slide( 0, 0 );
73 | strictEqual( Reveal.isLastSlide(), false, 'false after Reveal.slide( 0, 0 )' );
74 |
75 | var lastSlideIndex = document.querySelectorAll( '.reveal .slides>section' ).length - 1;
76 |
77 | Reveal.slide( lastSlideIndex, 0 );
78 | strictEqual( Reveal.isLastSlide(), true, 'true after Reveal.slide( ', 0+ lastSlideIndex +' )' );
79 |
80 | Reveal.slide( 0, 0 );
81 | strictEqual( Reveal.isLastSlide(), false, 'false after Reveal.slide( 0, 0 )' );
82 | });
83 |
84 | test( 'Reveal.getIndices', function() {
85 | var indices = Reveal.getIndices();
86 |
87 | ok( typeof indices.hasOwnProperty( 'h' ), 'h exists' );
88 | ok( typeof indices.hasOwnProperty( 'v' ), 'v exists' );
89 | ok( typeof indices.hasOwnProperty( 'f' ), 'f exists' );
90 |
91 | Reveal.slide( 1, 0 );
92 | ok( Reveal.getIndices().h === 1 && Reveal.getIndices().v === 0, 'h 1, v 0' );
93 |
94 | Reveal.slide( 1, 2 );
95 | ok( Reveal.getIndices().h === 1 && Reveal.getIndices().v === 2, 'h 1, v 2' );
96 |
97 | Reveal.slide( 0, 0 );
98 | });
99 |
100 | test( 'Reveal.getSlide', function() {
101 | var firstSlide = document.querySelector( '.reveal .slides>section:first-child' );
102 |
103 | equal( Reveal.getSlide( 0 ), firstSlide, 'gets correct first slide' );
104 |
105 | strictEqual( Reveal.getSlide( 100 ), undefined, 'returns undefined when slide can\'t be found' );
106 | });
107 |
108 | test( 'Reveal.getPreviousSlide/getCurrentSlide', function() {
109 | Reveal.slide( 0, 0 );
110 | Reveal.slide( 1, 0 );
111 |
112 | var firstSlide = document.querySelector( '.reveal .slides>section:first-child' );
113 | var secondSlide = document.querySelector( '.reveal .slides>section:nth-child(2)>section' );
114 |
115 | equal( Reveal.getPreviousSlide(), firstSlide, 'previous is slide #0' );
116 | equal( Reveal.getCurrentSlide(), secondSlide, 'current is slide #1' );
117 | });
118 |
119 | test( 'Reveal.getScale', function() {
120 | ok( typeof Reveal.getScale() === 'number', 'has scale' );
121 | });
122 |
123 | test( 'Reveal.getConfig', function() {
124 | ok( typeof Reveal.getConfig() === 'object', 'has config' );
125 | });
126 |
127 | test( 'Reveal.configure', function() {
128 | strictEqual( Reveal.getConfig().loop, false, '"loop" is false to start with' );
129 |
130 | Reveal.configure({ loop: true });
131 | strictEqual( Reveal.getConfig().loop, true, '"loop" has changed to true' );
132 |
133 | Reveal.configure({ loop: false, customTestValue: 1 });
134 | strictEqual( Reveal.getConfig().customTestValue, 1, 'supports custom values' );
135 | });
136 |
137 | test( 'Reveal.availableRoutes', function() {
138 | Reveal.slide( 0, 0 );
139 | deepEqual( Reveal.availableRoutes(), { left: false, up: false, down: false, right: true }, 'correct for first slide' );
140 |
141 | Reveal.slide( 1, 0 );
142 | deepEqual( Reveal.availableRoutes(), { left: true, up: false, down: true, right: true }, 'correct for vertical slide' );
143 | });
144 |
145 | test( 'Reveal.next', function() {
146 | Reveal.slide( 0, 0 );
147 |
148 | // Step through vertical child slides
149 | Reveal.next();
150 | deepEqual( Reveal.getIndices(), { h: 1, v: 0, f: undefined } );
151 |
152 | Reveal.next();
153 | deepEqual( Reveal.getIndices(), { h: 1, v: 1, f: undefined } );
154 |
155 | Reveal.next();
156 | deepEqual( Reveal.getIndices(), { h: 1, v: 2, f: undefined } );
157 |
158 | // Step through fragments
159 | Reveal.next();
160 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: -1 } );
161 |
162 | Reveal.next();
163 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 0 } );
164 |
165 | Reveal.next();
166 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 1 } );
167 |
168 | Reveal.next();
169 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 2 } );
170 | });
171 |
172 | test( 'Reveal.next at end', function() {
173 | Reveal.slide( 3 );
174 |
175 | // We're at the end, this should have no effect
176 | Reveal.next();
177 | deepEqual( Reveal.getIndices(), { h: 3, v: 0, f: undefined } );
178 |
179 | Reveal.next();
180 | deepEqual( Reveal.getIndices(), { h: 3, v: 0, f: undefined } );
181 | });
182 |
183 |
184 | // ---------------------------------------------------------------
185 | // FRAGMENT TESTS
186 |
187 | QUnit.module( 'Fragments' );
188 |
189 | test( 'Sliding to fragments', function() {
190 | Reveal.slide( 2, 0, -1 );
191 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: -1 }, 'Reveal.slide( 2, 0, -1 )' );
192 |
193 | Reveal.slide( 2, 0, 0 );
194 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 0 }, 'Reveal.slide( 2, 0, 0 )' );
195 |
196 | Reveal.slide( 2, 0, 2 );
197 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 2 }, 'Reveal.slide( 2, 0, 2 )' );
198 |
199 | Reveal.slide( 2, 0, 1 );
200 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 1 }, 'Reveal.slide( 2, 0, 1 )' );
201 | });
202 |
203 | test( 'Hiding all fragments', function() {
204 | var fragmentSlide = document.querySelector( '#fragment-slides>section:nth-child(1)' );
205 |
206 | Reveal.slide( 2, 0, 0 );
207 | strictEqual( fragmentSlide.querySelectorAll( '.fragment.visible' ).length, 1, 'one fragment visible when index is 0' );
208 |
209 | Reveal.slide( 2, 0, -1 );
210 | strictEqual( fragmentSlide.querySelectorAll( '.fragment.visible' ).length, 0, 'no fragments visible when index is -1' );
211 | });
212 |
213 | test( 'Current fragment', function() {
214 | var fragmentSlide = document.querySelector( '#fragment-slides>section:nth-child(1)' );
215 |
216 | Reveal.slide( 2, 0 );
217 | strictEqual( fragmentSlide.querySelectorAll( '.fragment.current-fragment' ).length, 0, 'no current fragment at index -1' );
218 |
219 | Reveal.slide( 2, 0, 0 );
220 | strictEqual( fragmentSlide.querySelectorAll( '.fragment.current-fragment' ).length, 1, 'one current fragment at index 0' );
221 |
222 | Reveal.slide( 1, 0, 0 );
223 | strictEqual( fragmentSlide.querySelectorAll( '.fragment.current-fragment' ).length, 0, 'no current fragment when navigating to previous slide' );
224 |
225 | Reveal.slide( 3, 0, 0 );
226 | strictEqual( fragmentSlide.querySelectorAll( '.fragment.current-fragment' ).length, 0, 'no current fragment when navigating to next slide' );
227 | });
228 |
229 | test( 'Stepping through fragments', function() {
230 | Reveal.slide( 2, 0, -1 );
231 |
232 | // forwards:
233 |
234 | Reveal.next();
235 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 0 }, 'next() goes to next fragment' );
236 |
237 | Reveal.right();
238 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 1 }, 'right() goes to next fragment' );
239 |
240 | Reveal.down();
241 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 2 }, 'down() goes to next fragment' );
242 |
243 | Reveal.down(); // moves to f #3
244 |
245 | // backwards:
246 |
247 | Reveal.prev();
248 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 2 }, 'prev() goes to prev fragment' );
249 |
250 | Reveal.left();
251 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 1 }, 'left() goes to prev fragment' );
252 |
253 | Reveal.up();
254 | deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 0 }, 'up() goes to prev fragment' );
255 | });
256 |
257 | test( 'Stepping past fragments', function() {
258 | var fragmentSlide = document.querySelector( '#fragment-slides>section:nth-child(1)' );
259 |
260 | Reveal.slide( 0, 0, 0 );
261 | equal( fragmentSlide.querySelectorAll( '.fragment.visible' ).length, 0, 'no fragments visible when on previous slide' );
262 |
263 | Reveal.slide( 3, 0, 0 );
264 | equal( fragmentSlide.querySelectorAll( '.fragment.visible' ).length, 3, 'all fragments visible when on future slide' );
265 | });
266 |
267 | test( 'Fragment indices', function() {
268 | var fragmentSlide = document.querySelector( '#fragment-slides>section:nth-child(2)' );
269 |
270 | Reveal.slide( 3, 0, 0 );
271 | equal( fragmentSlide.querySelectorAll( '.fragment.visible' ).length, 2, 'both fragments of same index are shown' );
272 | });
273 |
274 | test( 'Index generation', function() {
275 | var fragmentSlide = document.querySelector( '#fragment-slides>section:nth-child(1)' );
276 |
277 | // These have no indices defined to start with
278 | equal( fragmentSlide.querySelectorAll( '.fragment' )[0].getAttribute( 'data-fragment-index' ), '0' );
279 | equal( fragmentSlide.querySelectorAll( '.fragment' )[1].getAttribute( 'data-fragment-index' ), '1' );
280 | equal( fragmentSlide.querySelectorAll( '.fragment' )[2].getAttribute( 'data-fragment-index' ), '2' );
281 | });
282 |
283 | test( 'Index normalization', function() {
284 | var fragmentSlide = document.querySelector( '#fragment-slides>section:nth-child(3)' );
285 |
286 | // These start out as 1-4-4 and should normalize to 0-1-1
287 | equal( fragmentSlide.querySelectorAll( '.fragment' )[0].getAttribute( 'data-fragment-index' ), '0' );
288 | equal( fragmentSlide.querySelectorAll( '.fragment' )[1].getAttribute( 'data-fragment-index' ), '1' );
289 | equal( fragmentSlide.querySelectorAll( '.fragment' )[2].getAttribute( 'data-fragment-index' ), '1' );
290 | });
291 |
292 | asyncTest( 'fragmentshown event', function() {
293 | expect( 2 );
294 |
295 | var _onEvent = function( event ) {
296 | ok( true, 'event fired' );
297 | }
298 |
299 | Reveal.addEventListener( 'fragmentshown', _onEvent );
300 |
301 | Reveal.slide( 2, 0 );
302 | Reveal.slide( 2, 0 ); // should do nothing
303 | Reveal.slide( 2, 0, 0 ); // should do nothing
304 | Reveal.next();
305 | Reveal.next();
306 | Reveal.prev(); // shouldn't fire fragmentshown
307 |
308 | start();
309 |
310 | Reveal.removeEventListener( 'fragmentshown', _onEvent );
311 | });
312 |
313 | asyncTest( 'fragmenthidden event', function() {
314 | expect( 2 );
315 |
316 | var _onEvent = function( event ) {
317 | ok( true, 'event fired' );
318 | }
319 |
320 | Reveal.addEventListener( 'fragmenthidden', _onEvent );
321 |
322 | Reveal.slide( 2, 0, 2 );
323 | Reveal.slide( 2, 0, 2 ); // should do nothing
324 | Reveal.prev();
325 | Reveal.prev();
326 | Reveal.next(); // shouldn't fire fragmenthidden
327 |
328 | start();
329 |
330 | Reveal.removeEventListener( 'fragmenthidden', _onEvent );
331 | });
332 |
333 |
334 | // ---------------------------------------------------------------
335 | // CONFIGURATION VALUES
336 |
337 | QUnit.module( 'Configuration' );
338 |
339 | test( 'Controls', function() {
340 | var controlsElement = document.querySelector( '.reveal>.controls' );
341 |
342 | Reveal.configure({ controls: false });
343 | equal( controlsElement.style.display, 'none', 'controls are hidden' );
344 |
345 | Reveal.configure({ controls: true });
346 | equal( controlsElement.style.display, 'block', 'controls are visible' );
347 | });
348 |
349 | test( 'Progress', function() {
350 | var progressElement = document.querySelector( '.reveal>.progress' );
351 |
352 | Reveal.configure({ progress: false });
353 | equal( progressElement.style.display, 'none', 'progress are hidden' );
354 |
355 | Reveal.configure({ progress: true });
356 | equal( progressElement.style.display, 'block', 'progress are visible' );
357 | });
358 |
359 | test( 'Loop', function() {
360 | Reveal.configure({ loop: true });
361 |
362 | Reveal.slide( 0, 0 );
363 |
364 | Reveal.left();
365 | notEqual( Reveal.getIndices().h, 0, 'looped from start to end' );
366 |
367 | Reveal.right();
368 | equal( Reveal.getIndices().h, 0, 'looped from end to start' );
369 |
370 | Reveal.configure({ loop: false });
371 | });
372 |
373 |
374 | // ---------------------------------------------------------------
375 | // EVENT TESTS
376 |
377 | QUnit.module( 'Events' );
378 |
379 | asyncTest( 'slidechanged', function() {
380 | expect( 3 );
381 |
382 | var _onEvent = function( event ) {
383 | ok( true, 'event fired' );
384 | }
385 |
386 | Reveal.addEventListener( 'slidechanged', _onEvent );
387 |
388 | Reveal.slide( 1, 0 ); // should trigger
389 | Reveal.slide( 1, 0 ); // should do nothing
390 | Reveal.next(); // should trigger
391 | Reveal.slide( 3, 0 ); // should trigger
392 | Reveal.next(); // should do nothing
393 |
394 | start();
395 |
396 | Reveal.removeEventListener( 'slidechanged', _onEvent );
397 |
398 | });
399 |
400 | asyncTest( 'paused', function() {
401 | expect( 1 );
402 |
403 | var _onEvent = function( event ) {
404 | ok( true, 'event fired' );
405 | }
406 |
407 | Reveal.addEventListener( 'paused', _onEvent );
408 |
409 | Reveal.togglePause();
410 | Reveal.togglePause();
411 |
412 | start();
413 |
414 | Reveal.removeEventListener( 'paused', _onEvent );
415 | });
416 |
417 | asyncTest( 'resumed', function() {
418 | expect( 1 );
419 |
420 | var _onEvent = function( event ) {
421 | ok( true, 'event fired' );
422 | }
423 |
424 | Reveal.addEventListener( 'resumed', _onEvent );
425 |
426 | Reveal.togglePause();
427 | Reveal.togglePause();
428 |
429 | start();
430 |
431 | Reveal.removeEventListener( 'resumed', _onEvent );
432 | });
433 |
434 |
435 | } );
436 |
437 | Reveal.initialize();
438 |
439 |
--------------------------------------------------------------------------------