diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index f22e7ce..0000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,30 +0,0 @@ -Issues ------- - -If you've found a bug or have a great idea for a new feature that will help **all users** of impress.js, let us know by [adding your suggestion] -(https://github.com/bartaz/impress.js/issues/new) to the [issue tracker](https://github.com/bartaz/impress.js/issues). - -Guidelines: - -* If reporting a bug, please provide a [simplified example](https://sscce.org/) on [Pastebin](https://pastebin.com/) or [JsFiddle](https://jsfiddle.net/). - -Pull Requests -------------- - -[Pull Requests](https://help.github.com/articles/using-pull-requests/) should be opened against the [master branch] -(https://github.com/bartaz/impress.js/tree/master). But remember that the team will only accept code that fits the purpose of impress.js. - -Guidelines: - -* If proposing a feature, make sure to discuss that as an issue first. -* Create a new [topic branch](https://github.com/dchelimsky/rspec/wiki/Topic-Branches) for every separate change you make. -* Execute `npm run lint && npm test` to make sure the tests pass and the code is consistent with the project standards. - -Manual release steps --------------------- - -* Bump version in `package.json` -* Bump version in `src/impress.js` -* Create commit with the message "Release version x.x.x" -* Create Github tag and release -* Publish on npm: `git fetch && npm publish ./` \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index d13b3c5..0000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,5 +0,0 @@ -**Make sure these boxes are checked before submitting your issue, thank you!** - -- [ ] I have read and complied with the [Issues Contributing Guidelines](https://github.com/impress/impress.js/blob/master/.github/CONTRIBUTING.md#issues). -- [ ] If am reporting a bug, I have a [simplified example](http://www.sscce.org/) on [Pastebin](https://pastebin.com/) or [JsFiddle](https://jsfiddle.net/) that reproduces the issue. -- [ ] I have used the [Search Tool](https://github.com/impress/impress.js/search) to make sure someone haven't already reported my issue or feature request. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 47fe6dc..0000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,6 +0,0 @@ -**Make sure these boxes are checked before submitting your Pull Request, thank you!** - -- [ ] I have read and complied with the [Pull Request Contributing Guidelines](https://github.com/impress/impress.js/blob/master/CONTRIBUTING.md#pull-requests). -- [ ] I checked if an [an issue](https://github.com/impress/impress.js/issues) is necessary for my Pull Request and made sure it exists. -- [ ] I have created a [topic branch](https://github.com/dchelimsky/rspec/wiki/Topic-Branches). -- [ ] I have used the [Search Tool](https://github.com/impress/impress.js/search?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen&type=Issues) to make sure there are no open Pull Requests fixing the same thing. \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7a3a95d..b27ac9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +/js/impress.min.js /node_modules /npm-debug.log diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..43df993 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "extras"] + path = extras + url = https://github.com/impress/impress-extras diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..576f754 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,5 @@ +{ + "preset": "jquery", + // Since we check quotemarks already in jshint, this can be turned off + "validateQuoteMarks": false +} diff --git a/.jshintrc b/.jshintrc index 8f8436d..24eaf85 100644 --- a/.jshintrc +++ b/.jshintrc @@ -3,7 +3,9 @@ "module": true }, "boss": true, + "browser": true, "curly": true, + "esversion": 6, "eqeqeq": true, "eqnull": true, "expr": true, diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 2d396b4..d8e17e7 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -82,6 +82,11 @@ Define the pixel based position in which the **center** of the [Step Element](#s ``` +**Note:** The introduction of the [rel](src/plugins/rel/README.md) plugin includes a slight backward incompatible change. +Previously the default value for `data-x`, `data-y` and `data-z` was zero. The `rel` plugin changes the default to inherit +the value of the previous slide. This means, you need to explicitly set these values to zero, if they ever were non-zero. + + #### 3D Rotation (data-rotate-x, data-rotate-y, data-rotate-z) You can not only position a [Step Element](#step-element) in 3D, but also rotate it around any axis. @@ -106,6 +111,13 @@ You can of course rotate it around Z axis with `data-rotate-z` - it has exactly ``` +#### 3D Rotation Order (data-rotate-order) + +The order in which the CSS `rotateX(), rotateY(), rotateZ()` transforms are applied matters. This is because each rotation is relative to the then current position of the element. + +By default the rotation order is `data-rotate-order="xyz"`. For some advanced uses you may need to change it. The demo presentation [3D rotations](examples/3D-rotations/index.html) sets this attribute to rotate some steps into positions that are impossible to reach with the default order. + + ## CSS ### 4D States (.past, .present and .future classes) @@ -189,6 +201,11 @@ It is recommended to add the class manually to the `body` element though, becaus } ``` +## Plugins + +Many new features are implemented as plugins. The [Plugins documentation](src/plugins/README.md) is the starting place to learn about those, as well as the README.md of [each plugin](src/plugins/). + + ## JavaScript ### impress( [ id ] ) @@ -229,6 +246,21 @@ rootElement.addEventListener( "impress:init", function() { impress().init(); ``` +#### .tear() + +Resets the DOM to its original state, as it was before `init()` was called. + +This can be used to "unload" impress.js. A particular use case for this is, if you want to do +dynamic changes to the presentation, you can do a teardown, apply changes, then call `init()` +again. (In most cases, this will not cause flickering or other visible effects to the user, +beyond the intended dynamic changes.) + +**Example:** + +```JavaScript +impress().tear(); +``` + #### .next() Navigates to the next step of the presentation using the [`goto()` function](#impressgotostepindexstepelementidstepelement-duration). @@ -300,8 +332,8 @@ Triggers the `impress:stepenter` event in the [Root Element](#root-element) when ```JavaScript var rootElement = document.getElementById( "impress" ); -rootElement.addEventListener( "impress:stepenter", function() { - var currentStep = document.querySelector( ".present" ); +rootElement.addEventListener( "impress:stepenter", function(event) { + var currentStep = event.target; console.log( "Entered the Step Element '" + currentStep.id + "'" ); }); ``` @@ -312,8 +344,9 @@ Triggers the `impress:stepleave` event in the [Root Element](#root-element) when ```JavaScript var rootElement = document.getElementById( "impress" ); rootElement.addEventListener( "impress:stepleave", function(event) { - var currentStep = event.target - console.log( "Left the Step Element '" + currentStep.id + "'" ); + var currentStep = event.target; + var nextStep = event.detail.next; + console.log( "Left the Step Element '" + currentStep.id + "' and about to enter '" + nextStep.id ); }); ``` diff --git a/README.md b/README.md index 4866f52..2399b75 100644 --- a/README.md +++ b/README.md @@ -14,15 +14,19 @@ impress.js may not help you if you have nothing interesting to say ;) HOW TO USE IT --------------- -[Use the source](index.html), Luke ;) +### Checking out and initializing the git repository -The [HTML source code](index.html) serves as a good example usage and contains comments explaning various features of impress.js. For more information about styling you can look into [CSS code](css/impress-demo.css) which shows how classes provided by impress.js can be used. Last but not least [JavaScript code of impress.js](js/impress.js) has some useful comments if you are interested in how everything works. Feel free to explore! + git clone --recursive https://github.com/impress/impress.js.git + cd impress.js -If you want more straightforward reference documentation of all impress.js features and API you can find it in [DOCUMENTATION.md](DOCUMENTATION.md). +Note: For a minimal checkout, omit the `--recursive` option. This will leave out extra plugins. + +### Documentation -EXAMPLES AND OTHER LEARNING RESOURCES ---------------------------------------- +Reference documentation of core impress.js features and API you can find it in [DOCUMENTATION.md](DOCUMENTATION.md). + +The [HTML source code](index.html) of the official [impress.js demo](http://impress.github.io/impress.js/) serves as a good example usage and contains comments explaning various features of impress.js. For more information about styling you can look into [CSS code](css/impress-demo.css) which shows how classes provided by impress.js can be used. Last but not least [JavaScript code of impress.js](js/impress.js) has some useful comments if you are interested in how everything works. Feel free to explore! ### Official demo @@ -30,6 +34,8 @@ EXAMPLES AND OTHER LEARNING RESOURCES ### Examples and demos +The [Classic Slides](http://impress.github.io/impress.js/examples/classic-slides/) demo is targeted towards beginners, or can be used as a template for presentations that look like the traditional PowerPoint slide deck. Over time, it also grew into the example presentation that uses most of the features and addons available. + More examples and demos can be found on [Examples and demos wiki page](http://github.com/impress/impress.js/wiki/Examples-and-demos). Feel free to add your own example presentations (or websites) there. @@ -41,20 +47,48 @@ on the wiki, too. There is also a book available about [Building impressive presentations with impress.js](http://www.packtpub.com/building-impressive-presentations-with-impressjs/book) by Rakhitha Nimesh Ratnayake. +You may want to check out the sibling project [Impressionist|https://github.com/henrikingo/impressionist]: a 3D GUI editor that can help you in creating impress.js presentations. + +### Mailing list + +You're welcome to ask impress.js related questions on the [impressionist-presentations](https://groups.google.com/forum/#!forum/impressionist-presentations) mailing list. + + +REPOSITORY STRUCTURE +-------------------- + +* [index.html](index.html): This is the official impress.js demo, showcasing all of the features of the original impress.js, as well as some new plugins as we add them. + * As already mentioned, this file is well commented and acts as the official tutorial. +* [examples/](examples/): Contains several demos showcasing additional features available. + * [Classic Slides](examples/classic-slides/index.html) is a simple demo that that you can use as template if you want to create very simple, rectangular, PowerPoint-like presentations. +* [src/](src/): The main file is [src/impress.js](src/impress.js). Additional functionality is implemented as plugins in [src/plugins/](src/plugins/). + * See [src/plugins/README.md](src/plugins/README.md) for information about the plugin API and how to write plugins. +* [test/](test/): Contains QUnit and Syn libraries that we use for writing tests, as well as some test coverage for core functionality. (Yes, more tests are much welcome.) Tests for plugins are in the directory of each plugin. +* [js/](js/): Contains [js/impress.js](js/impress.js), which contains a concatenation of the core `src/impress.js` and all the plugins. Traditionally this is the file that you'll link to in a browser. In fact both the demo and test files do exactly that. +* [css/](css/]: Contains a CSS file used by the demo. This file is **not required for using impress.js** in your own presentations. Impress.js creates the CSS it needs dynamically. +* [extras/](extras/) contains plugins that for various reasons aren't enabled by default. You have to explicitly add them with their own `script` element to use them. +* [build.js](build.js): Simple build file that creates `js/impress.js`. It also creates a minified version `impress.min.js`, but that one is not included in the github repository. +* [package.json](build.js): An NPM package specification. This was mainly added so you can easily install [buildify](https://www.npmjs.com/package/buildify) and run `node build.js`. Other than the build process, which is really just doing roughly `cat src/impress.js src/plugins/*/*.js > js/impress.js`, and testing, `impress.js` itself doesn't depend on Node or any NPM modules. +* [bower.json](bower.json): A Bower package file. We also don't depend on Bower, but provide this file if you want to use it. WANT TO CONTRIBUTE? --------------------- -Please, read the [contributing guidelines](.github/CONTRIBUTING.md) on how to create [Issues](.github/CONTRIBUTING.md#issues) and [Pull Requests](.github/CONTRIBUTING.md#pull-requests). +For developers, once you've made changes to the code, you should run these commands for testing: -**Note:** The team has changed, so there will be many changes in the upcoming versions. -If you need informations about versions, check the [changelog](CHANGELOG.md). + npm run build + npm run test + npm run lint + +Note that running `firefox qunit_test_runner.html` is usually more informative than running `karma` with `npm run test`. They both run the same tests. + +More info about the [src/](src/) directory can be found in [src/plugins/README.md](src/plugins/README.md). ABOUT THE NAME ---------------- -impress.js name in [courtesy of @skuzniak](http://twitter.com/skuzniak/status/143627215165333504). +impress.js name is [courtesy of @skuzniak](http://twitter.com/skuzniak/status/143627215165333504). It's an (un)fortunate coincidence that a Open/LibreOffice presentation tool is called Impress ;) @@ -66,11 +100,21 @@ See the [Reference API](DOCUMENTATION.md) BROWSER SUPPORT ----------------- -This project supports only the major [evergreen](http://eisenbergeffect.bluespire.com/evergreen-browsers/) desktop browsers that have implemented: +The design goal for impress.js has been to showcase awesome CSS3 features as found in modern browser versions. We also use some new DOM functionality, and specifically do not use jQuery or any other JavaScript libraries, nor our own functions, to support older browsers. In general, recent versions of Firefox and Chrome are known to work well. Reportedly IE now works too. + +The typical use case for impress.js is to create presentations that you present from your own laptop, with a browser version you know works well. Some people also use impress.js successfully to embed animations or presentations in a web page, however, be aware that in this some of your visitors may not see the presentation correctly, or at all. + +In particular, impress.js makes use of the following JS and CSS features: * [DataSet API](http://caniuse.com/#search=dataset) * [ClassList API](http://caniuse.com/#search=classlist) * [CSS 3D Transforms](http://caniuse.com/#search=css%203d) * [CSS Transitions](http://caniuse.com/#search=css%20transition) -Copyright 2011-2016 Bartek Szopka - Released under the MIT [License](LICENSE) +COPYRIGHT AND LICENSE +--------------------- + +Copyright 2011-2016 Bartek Szopka +Copyright 2015-2017 Henrik Ingo + +Released under the MIT [License](LICENSE) diff --git a/build.js b/build.js new file mode 100644 index 0000000..8b43a96 --- /dev/null +++ b/build.js @@ -0,0 +1,56 @@ +var buildify = require('buildify'); + + +buildify() + .load('src/impress.js') + // Libraries from src/lib + .concat(['src/lib/gc.js']) + .concat(['src/lib/util.js']) + // Plugins from src/plugins + .concat(['src/plugins/autoplay/autoplay.js', + 'src/plugins/blackout/blackout.js', + 'src/plugins/extras/extras.js', + 'src/plugins/form/form.js', + 'src/plugins/goto/goto.js', + 'src/plugins/help/help.js', + 'src/plugins/impressConsole/impressConsole.js', + 'src/plugins/mobile/mobile.js', + 'src/plugins/mouse-timeout/mouse-timeout.js', + 'src/plugins/navigation/navigation.js', + 'src/plugins/navigation-ui/navigation-ui.js', + 'src/plugins/progress/progress.js', + 'src/plugins/rel/rel.js', + 'src/plugins/resize/resize.js', + 'src/plugins/skip/skip.js', + 'src/plugins/stop/stop.js', + 'src/plugins/substep/substep.js', + 'src/plugins/touch/touch.js', + 'src/plugins/toolbar/toolbar.js']) + .save('js/impress.js'); +/* + * Disabled until uglify supports ES6: https://github.com/mishoo/UglifyJS2/issues/448 + .uglify() + .save('js/impress.min.js'); +*/ + + +/* Auto generate an index.html that lists all the directories under examples/ + * This is useful for gh-pages, so you can link to http://impress.github.io/impress.js/examples + */ +var ls = require('ls'); +var fs = require('fs'); +var path = require('path'); + +var html_list = '\n' + +var html = '\n\nExample presentations\n\n' +html += '

Example presentations

\n' + html_list +html += '\n' + +var filename = path.resolve(__dirname, 'examples', 'index.html'); +fs.writeFileSync(filename, html); +console.log(filename); diff --git a/css/impress-demo.css b/css/impress-demo.css index fb97f04..e478573 100644 --- a/css/impress-demo.css +++ b/css/impress-demo.css @@ -268,7 +268,7 @@ a:focus { } #title h1 { - font-size: 190px; + font-size: 180px; -webkit-transform: translateZ(50px); -moz-transform: translateZ(50px); @@ -294,6 +294,7 @@ a:focus { line-height: 1; } +#big strong, #big b { display: block; font-size: 250px; @@ -527,6 +528,35 @@ a:focus { cursor: pointer; } +/* + This version of impress.js supports plugins, and in particular, a UI toolbar + plugin that allows easy navigation between steps and autoplay. +*/ +.impress-enabled div#impress-toolbar { + position: fixed; + right: 1px; + bottom: 1px; + opacity: 0.6; +} +.impress-enabled div#impress-toolbar > span { + margin-right: 10px; +} + +/* + With help from the mouse-timeout plugin, we can hide the toolbar and + have it show only when you move/click/touch the mouse. +*/ +body.impress-mouse-timeout div#impress-toolbar { + display: none; +} + +/* + In fact, we can hide the mouse cursor itself too, when mouse isn't used. +*/ +body.impress-mouse-timeout { + cursor: none; +} + /* Now, when we have all the steps styled let's give users a hint how to navigate @@ -682,9 +712,9 @@ a:focus { So use it wisely ... or don't use at all. */ -.impress-enabled { pointer-events: none } -.impress-enabled #impress { pointer-events: auto } - +.impress-enabled { pointer-events: none } +.impress-enabled #impress { pointer-events: auto } +.impress-enabled #impress-toolbar { pointer-events: auto } /* There is one funny thing I just realized. diff --git a/examples/2D-navigation/css/fonts.css b/examples/2D-navigation/css/fonts.css new file mode 100644 index 0000000..8e9d8f7 --- /dev/null +++ b/examples/2D-navigation/css/fonts.css @@ -0,0 +1,497 @@ +/* latin-ext */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQSYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQY4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSq-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSpX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNShWV49_lSm1NYrwo-zkhivY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSqaRobkAwv3vxw3jMhVENGA.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSv8zf_FOSsgRmwsS7Aa9k2w.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSj0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSugdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBkbcKLIaa1LC45dFaAfauRA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBmo_sUJ8uO4YLWRInS22T3Y.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBr6up8jxqWt8HVA3mDhkV_0.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBiYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBo4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxmgpAmOCqD37_tyH_8Ri5MM.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxsPNMTLbnS9uQzHQlYieHUU.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxgyhumQnPMBCoGYhRaNxyyY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxhUVAXEdVvYDDqrz3aeR0Yc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxlf4y_3s5bcYyyLIFUSWYUU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxnywqdtBbUHn3VPgzuFrCy8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxl2umOyRU7PgRiv8DXcgJjk.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/JX7MlXqjSJNjQvI4heMMGvY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/vtwNVMP8y9C17vLvIBNZI_Y6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/9kaD4V2pNPMMeUVBHayd7vY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/ATKpv8nLYAKUYexo8iqqrg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/kTYfCWJhlldPf5LnG4ZnHCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/g46X4VH_KHOWAAa-HpnGPiEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/hpORcvLZtemlH8gI-1S-7iEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/0XxGQsSc1g4rdRdjJKZrNPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/GpWpM_6S4VQLPNAQ3iWvVRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/7dSh6BcuqDLzS2qAASIeuhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/DVKQJxMmC9WF_oplMzlQqRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/PIPMHY90P7jtyjpXuZ2cLFtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkK-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkJX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkD0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkOgdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/5hX15RUpPERmeybVlLQEWBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/fU0HAfLiPHGlZhZpY6M7dBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/CPRt--GVMETgA6YEaoGitxTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/I-OtoJZa3TeyH6D9oli3ifesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpCYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpI4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/O_WhD9hODL16N4KLHLX7xSEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/3Nwg9VzlwLXPq3fNKwVRMCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/b31S45a_TNgaBApZhTgE6CEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/03aPdn7fFF3H6ngCgAlQzPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9ede9INZm0R8ZMJUtfOsxrw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9bpHcMS0zZe4mIYvDKG2oeM.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9RHJTnCUrjaAm2S9z52xC3Y.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9YWiMMZ7xLd792ULpGE4W_Y.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} + diff --git a/examples/2D-navigation/css/presentation.css b/examples/2D-navigation/css/presentation.css new file mode 100644 index 0000000..8a03a7e --- /dev/null +++ b/examples/2D-navigation/css/presentation.css @@ -0,0 +1,340 @@ +/* + A common approach is to use googleapis.com to generate css for the webfonts you want to use. + The downside of this approach is that you have to be online. So below I have simply saved + the output of the googleapis url into a file. Then you of course also have to make sure + the webfonts are locally installed to make offline usage work. For Ubuntu (or Debian) I + successfully used the script from here to do that: + http://www.webupd8.org/2011/01/automatically-install-all-google-web.html +*/ + +/* @import url(http://fonts.googleapis.com/css?family=Open+Sans:regular,semibold,italic,italicsemibold|PT+Sans:400,700,400italic,700italic|PT+Serif:400,700,400italic,700italic|Cutive+Mono); */ +@import url(fonts.css); + + + +/* + We display a fallback message for users with browsers that don't support + all the features required by it. All of the content will be still fully + accessible for them, but some more advanced effects would be missing. + When impress.js detects that browser supports all necessary CSS3 features, + the fallback-message style is hidden. +*/ + +.fallback-message { + font-family: sans-serif; + line-height: 1.3; + + width: 780px; + padding: 10px 10px 0; + margin: 20px auto; + + border: 1px solid #E4C652; + border-radius: 10px; + background: #EEDC94; +} + +.fallback-message p { + margin-bottom: 10px; +} + +.impress-supported .fallback-message { + display: none; +} + + +/* + The body background is the bacgkround of "everything". Many + impress.js tools call it the "surface". It could also be a + picture or pattern, but we leave it as light gray. +*/ + +body { + font-family: 'PT Sans', sans-serif; + min-height: 740px; + + background: #aaccbb; + color: #ff4466; +} + +/* + Now let's style the presentation steps. +*/ + +.step { + position: relative; + display: block; + + width: 900px; + height: 700px; + margin: 20px auto; + padding: 40px 60px; + + text-shadow: 0 2px 2px rgba(0, 10, 0, .5); + + font-family: 'Open Sans', Arial, sans-serif; + font-size: 30px; + letter-spacing: -1px; + +} +/* + Make inactive steps a little bit transparent. +*/ +.impress-enabled .step { + margin: 0; + opacity: 0.3; + transition: opacity 1s; +} + +.impress-enabled .step.active { opacity: 1 } + +/* + Speaker notes allow you to write comments within the steps, that will not + be displayed as part of the presentation. However, they will be picked up + and displayed by impressConsole.js when integrated. +*/ + +.notes { + display: none; +} + +h1, +h2, +h3 { + margin-bottom: 0.5em; + margin-top: 0.5em; + text-align: center; +} + +p { + text-align: center; + margin: 0.7em; +} + +li { + margin: 0.2em; +} + +/* Highlight.js used for coloring pre > code blocks. */ +pre > code { + font-size: 14px; + text-shadow: 0 0 0 rgba(0, 0, 0, 0); +} + +/* Inline code, no Highlight.js */ +code { + font-family: "Cutive mono","Courier New", monospace; +} + + +a { + color: inherit; + text-decoration: none; + padding: 0 0.1em; + background: rgba(200,200,200,0.3); + text-shadow: -1px 1px 2px rgba(100,100,100,0.9); + border-radius: 0.2em; + border-bottom: 1px solid rgba(100,100,100,0.4); + border-left: 1px solid rgba(100,100,100,0.4); + + transition: 0.5s; +} +a:hover, +a:focus { + background: rgba(200,200,200,1); + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +blockquote { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; +} + +em { + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strong { + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +q { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strike { + opacity: 0.7; +} + +small { + font-size: 0.4em; +} + +img { + width: 300px +} + +/****************** Background images **********************************************/ + + +img.bg { + position: fixed; + z-index: -100; + opacity: 0; + height: 50%; + width: auto; + transition: opacity 2s; +} + +#applepie-image { + left: 0px; + bottom: 0px; +} + +body.impress-on-applepie #applepie-image, +body.impress-on-applepie-pro #applepie-image, +body.impress-on-applepie-con #applepie-image, +body.impress-on-conclusion #applepie-image, +body.impress-on-overview #applepie-image { + opacity: 0.7; + transition: opacity 2s; +} + +#icecream-image { + right: 0px; + top: 0px; +} + +body.impress-on-icecream #icecream-image, +body.impress-on-icecream-pro #icecream-image, +body.impress-on-icecream-con #icecream-image, +body.impress-on-conclusion #icecream-image, +body.impress-on-overview #icecream-image { + opacity: 0.7; + transition: opacity 2s; +} + +#crisps-image { + right: 0px; + bottom: 0px; +} + +body.impress-on-crisps #crisps-image, +body.impress-on-crisps-pro #crisps-image, +body.impress-on-crisps-con #crisps-image, +body.impress-on-conclusion #crisps-image, +body.impress-on-overview #crisps-image { + opacity: 0.7; + transition: opacity 2s; +} + + +/*************** Slide specific things ****************************/ + +#image-credits { + color: #779988; +} + + + + + + + + + +/******************* PLUGINS *************************************************************/ +/* + This version of impress.js supports plugins, and in particular, a UI toolbar + plugin that allows easy navigation between steps and autoplay. +*/ +.impress-enabled div#impress-toolbar { + position: fixed; + right: 1px; + bottom: 1px; + opacity: 0.6; + z-index: 10; +} +.impress-enabled div#impress-toolbar > span { + margin-right: 10px; +} + +/* + With help from the mouse-timeout plugin, we can hide the toolbar and + have it show only when you move/click/touch the mouse. +*/ +body.impress-mouse-timeout div#impress-toolbar { + display: none; +} + +/* + In fact, we can hide the mouse cursor itself too, when mouse isn't used. +*/ +body.impress-mouse-timeout { + cursor: none; +} + + + +/* Progress bar */ +.impress-progressbar { + position: absolute; + right: 118px; + bottom: 1px; + left: 118px; + border-radius: 7px; + border: 2px solid rgba(100, 100, 100, 0.2); +} +.impress-progressbar DIV { + width: 0; + height: 2px; + border-radius: 5px; + background: rgba(75, 75, 75, 0.4); + transition: width 1s linear; +} +.impress-progress { + position: absolute; + left: 59px; + bottom: 1px; + text-align: left; + font-size: 10pt; + opacity: 0.6; +} + +/* Help popup plugin */ +.impress-enabled #impress-help { + background: none repeat scroll 0 0 rgba(0, 0, 0, 0.5); + color: #EEEEEE; + font-size: 80%; + position: fixed; + left: 2em; + bottom: 2em; + width: 24em; + border-radius: 1em; + padding: 1em; + text-align: center; + z-index: 100; + font-family: Verdana, Arial, Sans; +} +.impress-enabled #impress-help td { + padding-left: 1em; + padding-right: 1em; +} + +/* Substep plugin */ + +#impress .step .substep { + opacity: 0; +} + +#impress .step .substep.substep-visible { + opacity: 1; + transition: opacity 1s; +} + +.impress-enabled { pointer-events: none } +.impress-enabled #impress { pointer-events: auto } +.impress-enabled #impress-toolbar { pointer-events: auto } diff --git a/examples/2D-navigation/images/35535918670_f1d12627ff_o.png b/examples/2D-navigation/images/35535918670_f1d12627ff_o.png new file mode 100644 index 0000000..dfec93e Binary files /dev/null and b/examples/2D-navigation/images/35535918670_f1d12627ff_o.png differ diff --git a/examples/2D-navigation/images/6296334551_b3d5c27823_b.png b/examples/2D-navigation/images/6296334551_b3d5c27823_b.png new file mode 100644 index 0000000..6e3a232 Binary files /dev/null and b/examples/2D-navigation/images/6296334551_b3d5c27823_b.png differ diff --git a/examples/2D-navigation/images/6636957665_5e7c4a79de_o.png b/examples/2D-navigation/images/6636957665_5e7c4a79de_o.png new file mode 100644 index 0000000..2faca9b Binary files /dev/null and b/examples/2D-navigation/images/6636957665_5e7c4a79de_o.png differ diff --git a/examples/2D-navigation/index.html b/examples/2D-navigation/index.html new file mode 100644 index 0000000..0cdf634 --- /dev/null +++ b/examples/2D-navigation/index.html @@ -0,0 +1,203 @@ + + + + + Desserts (2D navigation demo) + + + + + +
+

Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

+

For the best experience please use the latest Chrome, Safari or Firefox browser.

+
+ + + + + + + + +
+ +
+

2D navigation

+ + +
+ +
+

Choosing a treat

+ + +
+ + +
+

Ice cream

+ + +
+ +
+

Ice cream: Pro's

+ + +
+ + +
+

Ice cream: Con's

+ + +
+ + + +
+

Crisps

+ + +
+ +
+

Crisps: Pro's

+ + +
+ + +
+

Crisps: Con's

+ + +
+ + + +
+

Apple pie

+ + +
+ +
+

Apple pie: Pro's

+ + +
+ + +
+

Apple pie: Con's

+ + +
+ + +
+

Conclusion

+ +

Can I choose all three ;-)

+ +

Image credits: reimagingerica@Flickr, + mixedmolly@Flickr, + stevepj2009@Flickr

+
+ +
+
+
+ +
+ +
+
+ +
+ + + + + + diff --git a/examples/3D-rotations/css/3D-rotations.css b/examples/3D-rotations/css/3D-rotations.css new file mode 100644 index 0000000..c8fadb8 --- /dev/null +++ b/examples/3D-rotations/css/3D-rotations.css @@ -0,0 +1,279 @@ +@import url(fonts.css); + + + +/* Fallback message */ + +.fallback-message { + font-family: sans-serif; + line-height: 1.3; + + width: 780px; + padding: 10px 10px 0; + margin: 20px auto; + + border: 1px solid #E4C652; + border-radius: 10px; + background: #EEDC94; +} + +.fallback-message p { + margin-bottom: 10px; +} + +.impress-supported .fallback-message { + display: none; +} + + +/* Body & steps */ +body { + font-family: 'PT Sans', sans-serif; + min-height: 740px; + + background: #00000f; + color: rgb(102, 102, 102); +} + +.step { + position: relative; + width: 700px; + height: 700px; + padding: 40px 60px; + margin: 20px auto; + + box-sizing: border-box; + + line-height: 1.5; + + background-color: white; + border-radius: 10px; + box-shadow: 0 2px 6px rgba(0, 0, 0, .1); + + text-shadow: 0 2px 2px rgba(0, 0, 0, .1); + + font-family: 'Open Sans', Arial, sans-serif; + font-size: 40pt; + letter-spacing: -1px; + +} + +.notes { + display: none; +} + +/* Overview step has no background or border */ + +.overview { + background-color: transparent; + border: none; + box-shadow: none; + pointer-events: none; + display: none; +} +.overview.active { + display: block; + pointer-events: auto; +} + +/* + Make inactive steps a little bit transparent. +*/ +.impress-enabled .step { + margin: 0; + opacity: 0.1; + transition: opacity 1s; +} + +.impress-enabled .step.active { opacity: 1 } + + +/* Content */ + +h1, +h2, +h3 { + margin-bottom: 0.5em; + margin-top: 0.5em; + text-align: center; +} + +p { + margin: 0.7em; +} + +li { + margin: 0.2em; +} + +/* Highlight.js used for coloring pre > code blocks. */ +pre > code { + font-size: 14px; + text-shadow: 0 0 0 rgba(0, 0, 0, 0); +} + +/* Inline code, no Highlight.js */ +code { + font-family: "Cutive mono","Courier New", monospace; +} + + +a { + color: inherit; + text-decoration: none; + padding: 0 0.1em; + background: rgba(200,200,200,0.2); + text-shadow: -1px 1px 2px rgba(100,100,100,0.9); + border-radius: 0.2em; + border-bottom: 1px solid rgba(100,100,100,0.2); + border-left: 1px solid rgba(100,100,100,0.2); + + transition: 0.5s; +} +a:hover, +a:focus { + background: rgba(200,200,200,1); + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +blockquote { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; +} + +em { + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strong { + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +q { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strike { + opacity: 0.7; +} + +small { + font-size: 0.4em; +} + + +/* + This version of impress.js supports plugins, and in particular, a UI toolbar + plugin that allows easy navigation between steps and autoplay. +*/ +.impress-enabled div#impress-toolbar { + position: fixed; + right: 1px; + bottom: 1px; + opacity: 0.6; + z-index: 10; +} +.impress-enabled div#impress-toolbar > span { + margin-right: 10px; +} + +/* + With help from the mouse-timeout plugin, we can hide the toolbar and + have it show only when you move/click/touch the mouse. +*/ +body.impress-mouse-timeout div#impress-toolbar { + display: none; +} + +/* + In fact, we can hide the mouse cursor itself too, when mouse isn't used. +*/ +body.impress-mouse-timeout { + cursor: none; +} + + + +/* Progress bar */ +.impress-progressbar { + position: absolute; + right: 118px; + bottom: 1px; + left: 118px; + border-radius: 7px; + border: 2px solid rgba(100, 100, 100, 0.2); +} +.impress-progressbar DIV { + width: 0; + height: 2px; + border-radius: 5px; + background: rgba(75, 75, 75, 0.4); + transition: width 1s linear; +} +.impress-progress { + position: absolute; + left: 59px; + bottom: 1px; + text-align: left; + font-size: 10pt; + opacity: 0.6; +} + +/* Help popup plugin */ +.impress-enabled #impress-help { + background: none repeat scroll 0 0 rgba(0, 0, 0, 0.5); + color: #EEEEEE; + font-size: 80%; + position: fixed; + left: 2em; + bottom: 2em; + width: 24em; + border-radius: 1em; + padding: 1em; + text-align: center; + z-index: 100; + font-family: Verdana, Arial, Sans; +} +.impress-enabled #impress-help td { + padding-left: 1em; + padding-right: 1em; +} + + +/* Styles specific to each step */ + +#overview2 { + font-size: 20pt; + padding-left: 200px; + text-align: right; +} + + +/* + And as the last thing there is a workaround for quite strange bug. + It happens a lot in Chrome. I don't remember if I've seen it in Firefox. + + Sometimes the element positioned in 3D (especially when it's moved back + along Z axis) is not clickable, because it falls 'behind' the + element. + + To prevent this, I decided to make non clickable by setting + pointer-events property to `none` value. + Value if this property is inherited, so to make everything else clickable + I bring it back on the #impress element. + + If you want to know more about `pointer-events` here are some docs: + https://developer.mozilla.org/en/CSS/pointer-events + + There is one very important thing to notice about this workaround - it makes + everything 'unclickable' except what's in #impress element. + + So use it wisely ... or don't use at all. +*/ +.impress-enabled { pointer-events: none } +.impress-enabled #impress { pointer-events: auto } +.impress-enabled #impress-toolbar { pointer-events: auto } diff --git a/examples/3D-rotations/css/fonts.css b/examples/3D-rotations/css/fonts.css new file mode 100644 index 0000000..8e9d8f7 --- /dev/null +++ b/examples/3D-rotations/css/fonts.css @@ -0,0 +1,497 @@ +/* latin-ext */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQSYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQY4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSq-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSpX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNShWV49_lSm1NYrwo-zkhivY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSqaRobkAwv3vxw3jMhVENGA.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSv8zf_FOSsgRmwsS7Aa9k2w.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSj0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSugdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBkbcKLIaa1LC45dFaAfauRA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBmo_sUJ8uO4YLWRInS22T3Y.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBr6up8jxqWt8HVA3mDhkV_0.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBiYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBo4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxmgpAmOCqD37_tyH_8Ri5MM.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxsPNMTLbnS9uQzHQlYieHUU.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxgyhumQnPMBCoGYhRaNxyyY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxhUVAXEdVvYDDqrz3aeR0Yc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxlf4y_3s5bcYyyLIFUSWYUU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxnywqdtBbUHn3VPgzuFrCy8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxl2umOyRU7PgRiv8DXcgJjk.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/JX7MlXqjSJNjQvI4heMMGvY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/vtwNVMP8y9C17vLvIBNZI_Y6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/9kaD4V2pNPMMeUVBHayd7vY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/ATKpv8nLYAKUYexo8iqqrg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/kTYfCWJhlldPf5LnG4ZnHCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/g46X4VH_KHOWAAa-HpnGPiEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/hpORcvLZtemlH8gI-1S-7iEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/0XxGQsSc1g4rdRdjJKZrNPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/GpWpM_6S4VQLPNAQ3iWvVRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/7dSh6BcuqDLzS2qAASIeuhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/DVKQJxMmC9WF_oplMzlQqRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/PIPMHY90P7jtyjpXuZ2cLFtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkK-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkJX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkD0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkOgdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/5hX15RUpPERmeybVlLQEWBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/fU0HAfLiPHGlZhZpY6M7dBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/CPRt--GVMETgA6YEaoGitxTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/I-OtoJZa3TeyH6D9oli3ifesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpCYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpI4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/O_WhD9hODL16N4KLHLX7xSEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/3Nwg9VzlwLXPq3fNKwVRMCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/b31S45a_TNgaBApZhTgE6CEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/03aPdn7fFF3H6ngCgAlQzPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9ede9INZm0R8ZMJUtfOsxrw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9bpHcMS0zZe4mIYvDKG2oeM.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9RHJTnCUrjaAm2S9z52xC3Y.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9YWiMMZ7xLd792ULpGE4W_Y.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} + diff --git a/examples/3D-rotations/index.html b/examples/3D-rotations/index.html new file mode 100644 index 0000000..ce1ed83 --- /dev/null +++ b/examples/3D-rotations/index.html @@ -0,0 +1,89 @@ + + + + + + + + A Study in 3D Rotations| by Henrik Ingo @henrikingo + + + + + + +
+

Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

+

For the best experience please use the latest Chrome, Safari or Firefox browser.

+
+ +
+ + +
+

A Study in 3D Rotations

+
+
+

Unlike the x/y/z coordinates (aka translations), the rotate-x/y/z rotations are applied in a + specific order, and order matters. This demo presentation exhibits the use of the new data-rotate- order attribute. + Instead of the default "xyz" order, the steps use the reversed "zyx" order in applying rotations around each axis. + Some of the steps (3 & 7), are in positions that are not possible with the default "xyz" order.

+
+ +
+

Slide one

+
+ +
+

Slide two

+
+ +
+

Slide three

+
+ +
+

Slide four

+
+ +
+

Slide five

+
+ +
+

Slide six

+
+ +
+

Slide seven

+
+ +
+

Slide eight

+
+
+ +
+
+ + + + + + diff --git a/examples/classic-slides/css/classic-slides.css b/examples/classic-slides/css/classic-slides.css new file mode 100644 index 0000000..b491cf0 --- /dev/null +++ b/examples/classic-slides/css/classic-slides.css @@ -0,0 +1,464 @@ +/* + A common approach is to use googleapis.com to generate css for the webfonts you want to use. + The downside of this approach is that you have to be online. So below I have simply saved + the output of the googleapis url into a file. Then you of course also have to make sure + the webfonts are locally installed to make offline usage work. For Ubuntu (or Debian) I + successfully used the script from here to do that: + http://www.webupd8.org/2011/01/automatically-install-all-google-web.html +*/ + +/* @import url(http://fonts.googleapis.com/css?family=Open+Sans:regular,semibold,italic,italicsemibold|PT+Sans:400,700,400italic,700italic|PT+Serif:400,700,400italic,700italic|Cutive+Mono); */ +@import url(fonts.css); + + + +/* + We display a fallback message for users with browsers that don't support + all the features required by it. All of the content will be still fully + accessible for them, but some more advanced effects would be missing. + When impress.js detects that browser supports all necessary CSS3 features, + the fallback-message style is hidden. +*/ + +.fallback-message { + font-family: sans-serif; + line-height: 1.3; + + width: 780px; + padding: 10px 10px 0; + margin: 20px auto; + + border: 1px solid #E4C652; + border-radius: 10px; + background: #EEDC94; +} + +.fallback-message p { + margin-bottom: 10px; +} + +.impress-supported .fallback-message { + display: none; +} + + +/* + The body background is the bacgkround of "everything". Many + impress.js tools call it the "surface". It could also be a + picture or pattern, but we leave it as light gray. +*/ + +body { + font-family: 'PT Sans', sans-serif; + min-height: 740px; + + background: rgb(215, 215, 215); + color: rgb(102, 102, 102); +} + +/* + Now let's style the presentation steps. +*/ + +.step { + position: relative; + width: 900px; + padding: 40px; + margin: 20px auto; + + box-sizing: border-box; + + font-family: 'PT Serif', georgia, serif; + font-size: 48px; + line-height: 1.5; +} +/* + Make inactive steps a little bit transparent. +*/ +.impress-enabled .step { + margin: 0; + opacity: 0.3; + transition: opacity 1s; +} + +.impress-enabled .step.active { opacity: 1 } + +/* + Speaker notes allow you to write comments within the steps, that will not + be displayed as part of the presentation. However, they will be picked up + and displayed by impressConsole.js when integrated. +*/ + +.notes { + display: none; +} + +/* + These 'slide' step styles were heavily inspired by HTML5 Slides: + http://html5slides.googlecode.com/svn/trunk/styles.css + + Note that we also use a background image, again just to facilitate a common + feature from PowerPoint and LibreOffice worlds. In this case the background + image is just the impress.js favicon - as if it were a company logo or something. + +*/ +.slide { + display: block; + + width: 900px; + height: 700px; + padding: 40px 60px; + + background-image: url(../images/background.png); + background-color: white; + border: 1px solid rgba(0, 0, 0, .3); + border-radius: 10px; + box-shadow: 0 2px 6px rgba(0, 0, 0, .1); + + text-shadow: 0 2px 2px rgba(0, 0, 0, .1); + + font-family: 'Open Sans', Arial, sans-serif; + font-size: 30px; + letter-spacing: -1px; +} + + +.slide h1, +.slide h2, +.slide h3 { + margin-bottom: 0.5em; + margin-top: 0.5em; + text-align: center; +} + +.slide p { + text-align: center; + margin: 0.7em; +} + +.slide li { + margin: 0.2em; +} + +/* Highlight.js used for coloring pre > code blocks. */ +.slide pre > code { + font-size: 14px; + text-shadow: 0 0 0 rgba(0, 0, 0, 0); +} + +/* Inline code, no Highlight.js */ +code { + font-family: "Cutive mono","Courier New", monospace; +} + + +a { + color: inherit; + text-decoration: none; + padding: 0 0.1em; + background: rgba(200,200,200,0.2); + text-shadow: -1px 1px 2px rgba(100,100,100,0.9); + border-radius: 0.2em; + border-bottom: 1px solid rgba(100,100,100,0.2); + border-left: 1px solid rgba(100,100,100,0.2); + + transition: 0.5s; +} +a:hover, +a:focus { + background: rgba(200,200,200,1); + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +blockquote { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; +} + +em { + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strong { + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +q { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strike { + opacity: 0.7; +} + +small { + font-size: 0.4em; +} + +img { + width: 300px +} + +.slide .right { + float: right; + margin-left: 40px; + margin-right: 0px; + margin-top: 20px; + margin-bottom: 20px; +} +.slide .left { + float: left; + margin-right: 40px; + margin-left: 0px; + margin-top: 20px; + margin-bottom: 20px; +} +.slide .top { + position: absolute; + top: 20px; + margin-bottom: 20px; + margin-top: 0px; +} +.slide .bottom { + position: absolute; + bottom: 20px; + margin-bottom: 0px; + margin-top: 20px; +} + +/* + Specific styles for: .title slides +*/ + +.title { + background-image: url(../images/background-title.png); +} + +.title h1, +.title h2, +.title h3 { + position: absolute; + left: 45px; /* slide width is 900px, so this is like a 5% margin on both sides */ + width: 90%; + text-align: center; +} +.title h1 { top: 50px; } +.title h2 { top: 400px; } +.title h3 { top: 500px; } + + + +/* Styles for animating the contents of a slide, such as a img, p, li or span element. ********/ + +/* + fly-in class starts from a position outside the slide, then flies into it's correct position. +*/ +.future .fly-in { + transform: translateY(-700px); + opacity: 0.0; /* Make it invisible, just so it doesn't clutter some other slide that might be in the position where we moved it */ +} +.present .fly-in { + transform: translateY(0px); + opacity: 1.0; + transition: 2s; +} +.past .fly-out { + transform: translateY(700px); + opacity: 0.0; + transition: 2s; +} + +/* + Fade-in/out is a straightforward fade. Give it enough seconds that all browsers render it clearly. +*/ +.future .fade-in { + opacity: 0.0; +} +.present .fade-in { + opacity: 1.0; + transition: 3s; +} +.past .fade-out { + opacity: 0.0; + transition: 3s; +} +/* + Zoom-in. +*/ +.future .zoom-in { + transform: scale(10); + opacity: 0.0; +} +.present .zoom-in { + transform: scale(1); + opacity: 1.0; + transition: 3s; +} +.past .zoom-out { + transform: scale(10); + opacity: 0.0; +} + +/* + This version of impress.js supports plugins, and in particular, a UI toolbar + plugin that allows easy navigation between steps and autoplay. +*/ +.impress-enabled div#impress-toolbar { + position: fixed; + right: 1px; + bottom: 1px; + opacity: 0.6; + z-index: 10; +} +.impress-enabled div#impress-toolbar > span { + margin-right: 10px; +} + +/* + With help from the mouse-timeout plugin, we can hide the toolbar and + have it show only when you move/click/touch the mouse. +*/ +body.impress-mouse-timeout div#impress-toolbar { + display: none; +} + +/* + In fact, we can hide the mouse cursor itself too, when mouse isn't used. +*/ +body.impress-mouse-timeout { + cursor: none; +} + + + +/* Progress bar */ +.impress-progressbar { + position: absolute; + right: 118px; + bottom: 1px; + left: 118px; + border-radius: 7px; + border: 2px solid rgba(100, 100, 100, 0.2); +} +.impress-progressbar DIV { + width: 0; + height: 2px; + border-radius: 5px; + background: rgba(75, 75, 75, 0.4); + transition: width 1s linear; +} +.impress-progress { + position: absolute; + left: 59px; + bottom: 1px; + text-align: left; + font-size: 10pt; + opacity: 0.6; +} + +/* Help popup plugin */ +.impress-enabled #impress-help { + background: none repeat scroll 0 0 rgba(0, 0, 0, 0.5); + color: #EEEEEE; + font-size: 80%; + position: fixed; + left: 2em; + bottom: 2em; + width: 24em; + border-radius: 1em; + padding: 1em; + text-align: center; + z-index: 100; + font-family: Verdana, Arial, Sans; +} +.impress-enabled #impress-help td { + padding-left: 1em; + padding-right: 1em; +} + +/* Substep plugin */ + +#impress .step .substep { + opacity: 0; +} + +#impress .step .substep.substep-visible { + opacity: 1; + transition: opacity 1s; +} + +/* + Styles for specific slides. +*/ + +/* The bar graph for Acme Inc profits */ + +#acme-graph-bottom { + position: absolute; + bottom: 100px; + left: 440px; + background-color: black; + width: 410px; + height: 2px; +} + +/* height: is set from javascript */ +#acme-graph-q1, +#acme-graph-q2, +#acme-graph-q3, +#acme-graph-q4 { + border: solid 1px black; + width: 70px; + margin-left: 10px; + position: absolute; + bottom: 100px; +} + +#acme-graph-q1 { + background-color: red; + left: 450px; +} + +#acme-graph-q2 { + background-color: blue; + left: 550px; +} + +#acme-graph-q3 { + background-color: green; + left: 650px; +} + +#acme-graph-q4 { + background-color: purple; + left: 750px; +} + +/* + And as the last thing there is a workaround for quite strange bug. + It happens a lot in Chrome. I don't remember if I've seen it in Firefox. + + Sometimes the element positioned in 3D (especially when it's moved back + along Z axis) is not clickable, because it falls 'behind' the + element. + + To prevent this, I decided to make non clickable by setting + pointer-events property to `none` value. + Value if this property is inherited, so to make everything else clickable + I bring it back on the #impress element. + + If you want to know more about `pointer-events` here are some docs: + https://developer.mozilla.org/en/CSS/pointer-events + + There is one very important thing to notice about this workaround - it makes + everything 'unclickable' except what's in #impress element. + + So use it wisely ... or don't use at all. +*/ +.impress-enabled { pointer-events: none } +.impress-enabled #impress { pointer-events: auto } +.impress-enabled #impress-toolbar { pointer-events: auto } diff --git a/examples/classic-slides/css/fonts.css b/examples/classic-slides/css/fonts.css new file mode 100644 index 0000000..8e9d8f7 --- /dev/null +++ b/examples/classic-slides/css/fonts.css @@ -0,0 +1,497 @@ +/* latin-ext */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQSYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQY4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSq-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSpX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNShWV49_lSm1NYrwo-zkhivY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSqaRobkAwv3vxw3jMhVENGA.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSv8zf_FOSsgRmwsS7Aa9k2w.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSj0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSugdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBkbcKLIaa1LC45dFaAfauRA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBmo_sUJ8uO4YLWRInS22T3Y.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBr6up8jxqWt8HVA3mDhkV_0.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBiYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBo4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxmgpAmOCqD37_tyH_8Ri5MM.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxsPNMTLbnS9uQzHQlYieHUU.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxgyhumQnPMBCoGYhRaNxyyY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxhUVAXEdVvYDDqrz3aeR0Yc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxlf4y_3s5bcYyyLIFUSWYUU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxnywqdtBbUHn3VPgzuFrCy8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxl2umOyRU7PgRiv8DXcgJjk.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/JX7MlXqjSJNjQvI4heMMGvY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/vtwNVMP8y9C17vLvIBNZI_Y6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/9kaD4V2pNPMMeUVBHayd7vY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/ATKpv8nLYAKUYexo8iqqrg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/kTYfCWJhlldPf5LnG4ZnHCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/g46X4VH_KHOWAAa-HpnGPiEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/hpORcvLZtemlH8gI-1S-7iEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/0XxGQsSc1g4rdRdjJKZrNPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/GpWpM_6S4VQLPNAQ3iWvVRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/7dSh6BcuqDLzS2qAASIeuhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/DVKQJxMmC9WF_oplMzlQqRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/PIPMHY90P7jtyjpXuZ2cLFtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkK-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkJX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkD0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkOgdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/5hX15RUpPERmeybVlLQEWBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/fU0HAfLiPHGlZhZpY6M7dBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/CPRt--GVMETgA6YEaoGitxTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/I-OtoJZa3TeyH6D9oli3ifesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpCYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpI4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/O_WhD9hODL16N4KLHLX7xSEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/3Nwg9VzlwLXPq3fNKwVRMCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/b31S45a_TNgaBApZhTgE6CEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/03aPdn7fFF3H6ngCgAlQzPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9ede9INZm0R8ZMJUtfOsxrw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9bpHcMS0zZe4mIYvDKG2oeM.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9RHJTnCUrjaAm2S9z52xC3Y.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9YWiMMZ7xLd792ULpGE4W_Y.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} + diff --git a/examples/classic-slides/images/3476636111_c551295ca4_b.jpg b/examples/classic-slides/images/3476636111_c551295ca4_b.jpg new file mode 100644 index 0000000..0488bf2 Binary files /dev/null and b/examples/classic-slides/images/3476636111_c551295ca4_b.jpg differ diff --git a/examples/classic-slides/images/background-title.png b/examples/classic-slides/images/background-title.png new file mode 100644 index 0000000..4a3ec21 Binary files /dev/null and b/examples/classic-slides/images/background-title.png differ diff --git a/examples/classic-slides/images/background-title.svg b/examples/classic-slides/images/background-title.svg new file mode 100644 index 0000000..1672a2a --- /dev/null +++ b/examples/classic-slides/images/background-title.svg @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + impress.js + + diff --git a/examples/classic-slides/images/background.png b/examples/classic-slides/images/background.png new file mode 100644 index 0000000..d109c0c Binary files /dev/null and b/examples/classic-slides/images/background.png differ diff --git a/examples/classic-slides/images/background.svg b/examples/classic-slides/images/background.svg new file mode 100644 index 0000000..653e5a7 --- /dev/null +++ b/examples/classic-slides/images/background.svg @@ -0,0 +1,323 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/classic-slides/index.html b/examples/classic-slides/index.html new file mode 100644 index 0000000..3de0c92 --- /dev/null +++ b/examples/classic-slides/index.html @@ -0,0 +1,463 @@ + + + + + + + + Classic Slides with impress.js | Simple example impress.js slide show | by Henrik Ingo @henrikingo + + + + + + + + + + + + + + + + +
+

Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

+

For the best experience please use the latest Chrome, Safari or Firefox browser.

+
+ + +
+ + +
+

Example Presentation:
+ Classic Slides

+

Henrik Ingo

+

2015

+ +
+ Any element with the class="notes" will not be displayed. This can + be used for speaker notes. In fact, the impressConsole plugin will + show it in the speaker console! +
+
+ +
+

Table of Contents

+ + +
+

Table of Contents, with links to other slides of this same presentation.

+ +

Note that instead of absolute positioning we use relative positioning, + with the data-rel-x and data-rel-y attributes. This means the step is + positioned relative to the foregoing step. In other words, this is + equivalent to data-x="0" data-y="-1500".

+
+
+ +
+

A slide with text

+

This slide has a few paragraphs
(p element) of normal text.

+

Personally I like centered or even justified text, as it looks less boring. This can of course be set in the css file.

+

I really like the style on links in these presentations. I modified the border to be beveled, but it's mostly from @bartaz' original demo. @bartaz is the creator of impress.js.

+ +
+ In this slide, we don't even specify the relative position, rather + that too is inherited. So this slide will again be 1000px to the + right of the previous one. +
+
+ +
+

Bullet points

+ + +
+
+
+ + +
+

A blockquote & image

+ Mother Teresa holding a newborn baby +
+ Spread love everywhere you go.
Let no one ever come to you without leaving happier. +

Mother Teresa

+

Image credit: Peta_de_Aztlan@Flickr. CC-BY 2.0

+
+ +
+
+
+ +
+

More text styles

+

As usual, use em to emphasize,
+ strong for strong, u for underline,
+ strike for strikethrough and q for inline quotations.

+ +

If you're a software engineer like me, you will often use the + <code> tag for monospaced inline text.

+ +
+
+
+ +
+

Motion effects 101

+

Items on the slide can

+

Fly in

+

Fade in

+

And zoom in

+ +

...just like in PowerPoint. Yeah, I know I'm being lame, but it was fun to learn to do this in CSS3.

+ +
+

This step here doesn't introduce anything new when it comes to data attributes, but you + should notice in the demo that some words of this text are being animated. + It's a very basic CSS transition that is applied to the elements when this step element is + reached. +

+ At the very beginning of the presentation all step elements are given the class of `future`. + It means that they haven't been visited yet. +

+ When the presentation moves to given step `future` is changed to `present` class name. + That's how animation on this step works - text moves when the step has `present` class. +

+ Finally when the step is left the `present` class is removed from the element and `past` + class is added. +

+ So basically every step element has one of three classes: `future`, `present` and `past`. + Only one current step has the `present` class. +

+
+
+ +
+

Add-ons

+
+

This version of impress.js includes several add-ons, striving to make this a + full featured presentation app.

+
+
+ +
+

Impress.js plugins

+ +
+

This presentation also uses speaker notes. They are not visible in the presentation, but shown in the impress console.

+ +

If you pressed P only now, this is the first time you see these notes. In fact, there has been notes on preceding slides as well. + You can use the navigation controls at the bottom of the impress console to browse back to them.

+ +

And did you notice how those bullet points appear one by one as you press space/arrow? That's another plugin, called substeps.

+
+
+ +
+

Highlight.js

+

+        // `init` API function that initializes (and runs) the presentation.
+        var init = function () {
+            if (initialized) { return; }
+            execPreInitPlugins();
+            
+            // First we set up the viewport for mobile devices.
+            // For some reason iPad goes nuts when it is not done properly.
+            var meta = $("meta[name='viewport']") || document.createElement("meta");
+            meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no";
+            if (meta.parentNode !== document.head) {
+                meta.name = 'viewport';
+                document.head.appendChild(meta);
+            }        
+        
+
+

The Highlight.js library provides really nice color coding of source code. + It automatically applies to any code inside a <pre><code> element.

+

Highlight.js is found under the extras/ + directory, since it is an independent third party plugin, not really an impress.js plugin. You have + to include it via it's own <link> and <script> tags.

+
+
+ +
+

Mermaid.js

+
+ %% This is a comment in mermaid markup + graph LR + A(Support for
diagrams) + B[Provided by
mermaid.js] + C{Already
know
mermaid?} + D(Tutorial) + E(Great, hope you enjoy!) + A-->B + B-->C + C--No-->D + C--Yes-->E + classDef startEnd fill:#fcc,stroke:#353,stroke-width:2px; + class A,D,E startEnd; +
+ +

MathJax.js

+

Use \(\LaTeX\), MathML or AsciiMath to properly show mathematical formula.

+
+ Mermaid.js, likewise in a href="https://github.com/impress/impress.js/tree/master/extras">extras/ + directory, draws SVG diagrams from a MarkDown-like syntax. To learn + more about it read the fine manual. +
+
+ +
+# Markdown.js + +* [Markdown.js](https://github.com/evilstreak/markdown-js) integration: for authors in a hurry! + * ...or lazy ;-) +* Jot down bullet points in *Markdown* + * ...have it automatically converted to HTML + * Markdown is converted into a presentation client side, in the browser. This is unlike + existing tools like [Hovercraft](https://github.com/regebro/hovercraft) and + [markdown-impress](http://binbinliao.com/markdown-impress/) where you generate a new + html file on the command line. +* [A more advanced Markdown presentation is here.](../markdown/) +
+ +
+ +

Acme Inc Quarterly Profits

+ + +
+
+
+
+
+
+
+
+
+ + + + + + +
Q1234€
Q2255€
Q3€ (insert here)
Q4€
+
+
+
+ + + +
+

More info

+ + +
+
+
+ + +
+
+
+ + +
+ +
+
+ +
+ + + + + + + + + + + + diff --git a/examples/cube/css/cube.css b/examples/cube/css/cube.css new file mode 100644 index 0000000..931113e --- /dev/null +++ b/examples/cube/css/cube.css @@ -0,0 +1,256 @@ +@import url(fonts.css); + + + +/* Fallback message */ + +.fallback-message { + font-family: sans-serif; + line-height: 1.3; + + width: 780px; + padding: 10px 10px 0; + margin: 20px auto; + + border: 1px solid #E4C652; + border-radius: 10px; + background: #EEDC94; +} + +.fallback-message p { + margin-bottom: 10px; +} + +.impress-supported .fallback-message { + display: none; +} + + +/* Body & steps */ +body { + font-family: 'PT Sans', sans-serif; + min-height: 740px; + + background: #00000f; + color: rgb(102, 102, 102); +} + +.step { + position: relative; + width: 700px; + height: 700px; + padding: 40px 60px; + margin: 20px auto; + + box-sizing: border-box; + + line-height: 1.5; + + background-color: white; + border-radius: 10px; + box-shadow: 0 2px 6px rgba(0, 0, 0, .1); + + text-shadow: 0 2px 2px rgba(0, 0, 0, .1); + font-family: 'Open Sans', Arial, sans-serif; + font-size: 30px; + letter-spacing: -1px; + +} + +#overview { + background-color: transparent; + border: none; + box-shadow: none; +} +/* + Make inactive steps a little bit transparent. +*/ +.impress-enabled .step { + margin: 0; + opacity: 0.7; + transition: opacity 1s; +} + +.impress-enabled .step.active { opacity: 1 } + +.notes { + display: none; +} + +h1, +h2, +h3 { + margin-bottom: 0.5em; + margin-top: 0.5em; + text-align: center; +} + +p { + margin: 0.7em; +} + +li { + margin: 0.2em; +} + +/* Highlight.js used for coloring pre > code blocks. */ +pre > code { + font-size: 14px; + text-shadow: 0 0 0 rgba(0, 0, 0, 0); +} + +/* Inline code, no Highlight.js */ +code { + font-family: "Cutive mono","Courier New", monospace; +} + + +a { + color: inherit; + text-decoration: none; + padding: 0 0.1em; + background: rgba(200,200,200,0.2); + text-shadow: -1px 1px 2px rgba(100,100,100,0.9); + border-radius: 0.2em; + border-bottom: 1px solid rgba(100,100,100,0.2); + border-left: 1px solid rgba(100,100,100,0.2); + + transition: 0.5s; +} +a:hover, +a:focus { + background: rgba(200,200,200,1); + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +blockquote { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; +} + +em { + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strong { + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +q { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strike { + opacity: 0.7; +} + +small { + font-size: 0.4em; +} + + +/* + This version of impress.js supports plugins, and in particular, a UI toolbar + plugin that allows easy navigation between steps and autoplay. +*/ +.impress-enabled div#impress-toolbar { + position: fixed; + right: 1px; + bottom: 1px; + opacity: 0.6; + z-index: 10; +} +.impress-enabled div#impress-toolbar > span { + margin-right: 10px; +} + +/* + With help from the mouse-timeout plugin, we can hide the toolbar and + have it show only when you move/click/touch the mouse. +*/ +body.impress-mouse-timeout div#impress-toolbar { + display: none; +} + +/* + In fact, we can hide the mouse cursor itself too, when mouse isn't used. +*/ +body.impress-mouse-timeout { + cursor: none; +} + + + +/* Progress bar */ +.impress-progressbar { + position: absolute; + right: 118px; + bottom: 1px; + left: 118px; + border-radius: 7px; + border: 2px solid rgba(100, 100, 100, 0.2); +} +.impress-progressbar DIV { + width: 0; + height: 2px; + border-radius: 5px; + background: rgba(75, 75, 75, 0.4); + transition: width 1s linear; +} +.impress-progress { + position: absolute; + left: 59px; + bottom: 1px; + text-align: left; + font-size: 10pt; + opacity: 0.6; +} + +/* Help popup plugin */ +.impress-enabled #impress-help { + background: none repeat scroll 0 0 rgba(0, 0, 0, 0.5); + color: #EEEEEE; + font-size: 80%; + position: fixed; + left: 2em; + bottom: 2em; + width: 24em; + border-radius: 1em; + padding: 1em; + text-align: center; + z-index: 100; + font-family: Verdana, Arial, Sans; +} +.impress-enabled #impress-help td { + padding-left: 1em; + padding-right: 1em; +} + +/* + And as the last thing there is a workaround for quite strange bug. + It happens a lot in Chrome. I don't remember if I've seen it in Firefox. + + Sometimes the element positioned in 3D (especially when it's moved back + along Z axis) is not clickable, because it falls 'behind' the + element. + + To prevent this, I decided to make non clickable by setting + pointer-events property to `none` value. + Value if this property is inherited, so to make everything else clickable + I bring it back on the #impress element. + + If you want to know more about `pointer-events` here are some docs: + https://developer.mozilla.org/en/CSS/pointer-events + + There is one very important thing to notice about this workaround - it makes + everything 'unclickable' except what's in #impress element. + + So use it wisely ... or don't use at all. +*/ +.impress-enabled { pointer-events: none } +.impress-enabled #impress { pointer-events: auto } +.impress-enabled #impress-toolbar { pointer-events: auto } diff --git a/examples/cube/css/fonts.css b/examples/cube/css/fonts.css new file mode 100644 index 0000000..8e9d8f7 --- /dev/null +++ b/examples/cube/css/fonts.css @@ -0,0 +1,497 @@ +/* latin-ext */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQSYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQY4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSq-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSpX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNShWV49_lSm1NYrwo-zkhivY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSqaRobkAwv3vxw3jMhVENGA.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSv8zf_FOSsgRmwsS7Aa9k2w.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSj0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSugdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBkbcKLIaa1LC45dFaAfauRA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBmo_sUJ8uO4YLWRInS22T3Y.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBr6up8jxqWt8HVA3mDhkV_0.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBiYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBo4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxmgpAmOCqD37_tyH_8Ri5MM.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxsPNMTLbnS9uQzHQlYieHUU.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxgyhumQnPMBCoGYhRaNxyyY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxhUVAXEdVvYDDqrz3aeR0Yc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxlf4y_3s5bcYyyLIFUSWYUU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxnywqdtBbUHn3VPgzuFrCy8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxl2umOyRU7PgRiv8DXcgJjk.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/JX7MlXqjSJNjQvI4heMMGvY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/vtwNVMP8y9C17vLvIBNZI_Y6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/9kaD4V2pNPMMeUVBHayd7vY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/ATKpv8nLYAKUYexo8iqqrg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/kTYfCWJhlldPf5LnG4ZnHCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/g46X4VH_KHOWAAa-HpnGPiEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/hpORcvLZtemlH8gI-1S-7iEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/0XxGQsSc1g4rdRdjJKZrNPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/GpWpM_6S4VQLPNAQ3iWvVRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/7dSh6BcuqDLzS2qAASIeuhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/DVKQJxMmC9WF_oplMzlQqRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/PIPMHY90P7jtyjpXuZ2cLFtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkK-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkJX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkD0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkOgdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/5hX15RUpPERmeybVlLQEWBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/fU0HAfLiPHGlZhZpY6M7dBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/CPRt--GVMETgA6YEaoGitxTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/I-OtoJZa3TeyH6D9oli3ifesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpCYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpI4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/O_WhD9hODL16N4KLHLX7xSEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/3Nwg9VzlwLXPq3fNKwVRMCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/b31S45a_TNgaBApZhTgE6CEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/03aPdn7fFF3H6ngCgAlQzPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9ede9INZm0R8ZMJUtfOsxrw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9bpHcMS0zZe4mIYvDKG2oeM.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9RHJTnCUrjaAm2S9z52xC3Y.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9YWiMMZ7xLd792ULpGE4W_Y.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} + diff --git a/examples/cube/index.html b/examples/cube/index.html new file mode 100644 index 0000000..fc811e9 --- /dev/null +++ b/examples/cube/index.html @@ -0,0 +1,60 @@ + + + + + Cube | Explore impress.js in 3D | by Henrik Ingo @henrikingo + + + + + + +
+

Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

+

For the best experience please use the latest Chrome, Safari or Firefox browser.

+
+ +
+ +
+

Slide one

+
+ +
+

Slide two

+
+ +
+

Slide three

+
+ +
+

Slide four

+
+ +
+

Slide five

+
+ +
+

Slide six

+
+ +
+
+
+ +
+
+ + + + + + diff --git a/examples/index.html b/examples/index.html new file mode 100644 index 0000000..1e5924b --- /dev/null +++ b/examples/index.html @@ -0,0 +1,14 @@ + + +Example presentations + +

Example presentations

+ + + \ No newline at end of file diff --git a/examples/markdown/css/devopsy.css b/examples/markdown/css/devopsy.css new file mode 100644 index 0000000..392e93f --- /dev/null +++ b/examples/markdown/css/devopsy.css @@ -0,0 +1,47 @@ +/***** Menu where this style is selected *****/ +.devopsy .css-menu-devopsy { + border: solid 1px #aaaaaa; +} + + +/***** Presentation *****/ + +body.devopsy { + background: #000; +} + +.devopsy .step { + color: #ffff00; +} + +/***** Styles *****/ +.devopsy h1, +.devopsy h2, +.devopsy h3 { + color: #ff6600; +} + +.devopsy a { + color: #00ffff; +} + +.devopsy blockquote { + text-shadow: 3px 3px 3px rgba(255, 100, 0, .7); +} + +.devopsy em { + text-shadow: 3px 3px 3px rgba(255, 100, 0, .7); +} + +.devopsy strong { + text-shadow: 3px 3px 3px rgba(255, 100, 0, .7); +} + +.devopsy q { + text-shadow: 3px 3px 3px rgba(255, 100, 0, .7); +} + +.devopsy strike { + opacity: 0.7; +} + diff --git a/examples/markdown/css/effects.css b/examples/markdown/css/effects.css new file mode 100644 index 0000000..ad60de4 --- /dev/null +++ b/examples/markdown/css/effects.css @@ -0,0 +1,41 @@ +/***** Menu where this style is selected *****/ +.effects .css-menu-effects { + border: solid 1px #aaaaaa; +} + +/***** Presentation *****/ + +body.effects { + font-family: 'PT Sans', sans-serif; + min-height: 740px; + + background: #dde5dd; +} + +.effects .step { +} + + +/* Color effect. */ +.effects .past > *, +.effects .future > * { + color: inherit; + transition: 3s; +} +.effects .present > * { + color: rgb(200, 102, 102); + transition: 3s; +} + +/* Fly right */ + +.effects .past h1, +.effects .future h1 { + transform: scale(3); + transition: 1s; +} +.effects .present h1 { + transform: scale(1); + transition: 1s; +} + diff --git a/examples/markdown/css/fonts.css b/examples/markdown/css/fonts.css new file mode 100644 index 0000000..8e9d8f7 --- /dev/null +++ b/examples/markdown/css/fonts.css @@ -0,0 +1,497 @@ +/* latin-ext */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQSYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Cutive Mono'; + font-style: normal; + font-weight: 400; + src: local('Cutive Mono'), local('CutiveMono-Regular'), url(http://fonts.gstatic.com/s/cutivemono/v4/N5odNRruTwjvCM8y77PhQY4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSq-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSpX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNShWV49_lSm1NYrwo-zkhivY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSqaRobkAwv3vxw3jMhVENGA.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSv8zf_FOSsgRmwsS7Aa9k2w.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSj0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v13/MTP_ySUJH_bn48VBG8sNSugdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBjUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBkbcKLIaa1LC45dFaAfauRA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBmo_sUJ8uO4YLWRInS22T3Y.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBr6up8jxqWt8HVA3mDhkV_0.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBiYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v13/xjAJXh38I15wypJXxuGMBo4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxmgpAmOCqD37_tyH_8Ri5MM.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxsPNMTLbnS9uQzHQlYieHUU.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxgyhumQnPMBCoGYhRaNxyyY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxhUVAXEdVvYDDqrz3aeR0Yc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxlf4y_3s5bcYyyLIFUSWYUU.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxnywqdtBbUHn3VPgzuFrCy8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxl2umOyRU7PgRiv8DXcgJjk.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/JX7MlXqjSJNjQvI4heMMGvY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/vtwNVMP8y9C17vLvIBNZI_Y6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/9kaD4V2pNPMMeUVBHayd7vY6323mHUZFJMgTvxaG2iE.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/ATKpv8nLYAKUYexo8iqqrg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/kTYfCWJhlldPf5LnG4ZnHCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/g46X4VH_KHOWAAa-HpnGPiEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/hpORcvLZtemlH8gI-1S-7iEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/0XxGQsSc1g4rdRdjJKZrNPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/GpWpM_6S4VQLPNAQ3iWvVRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/7dSh6BcuqDLzS2qAASIeuhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/DVKQJxMmC9WF_oplMzlQqRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://fonts.gstatic.com/s/ptsans/v8/PIPMHY90P7jtyjpXuZ2cLFtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkK-j2U0lmluP9RWlSytm3ho.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkJX5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkD0LW-43aMEzIO6XUTLjad8.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 700; + src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://fonts.gstatic.com/s/ptsans/v8/lILlYDvubYemzYzN7GbLkOgdm0LZdjqr5-oayXSOefg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/5hX15RUpPERmeybVlLQEWBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/fU0HAfLiPHGlZhZpY6M7dBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/CPRt--GVMETgA6YEaoGitxTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + src: local('PT Serif'), local('PTSerif-Regular'), url(http://fonts.gstatic.com/s/ptserif/v8/I-OtoJZa3TeyH6D9oli3ifesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpDUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpCYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://fonts.gstatic.com/s/ptserif/v8/QABk9IxT-LFTJ_dQzv7xpI4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/O_WhD9hODL16N4KLHLX7xSEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/3Nwg9VzlwLXPq3fNKwVRMCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/b31S45a_TNgaBApZhTgE6CEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://fonts.gstatic.com/s/ptserif/v8/03aPdn7fFF3H6ngCgAlQzPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9ede9INZm0R8ZMJUtfOsxrw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9bpHcMS0zZe4mIYvDKG2oeM.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9RHJTnCUrjaAm2S9z52xC3Y.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 700; + src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://fonts.gstatic.com/s/ptserif/v8/Foydq9xJp--nfYIx2TBz9YWiMMZ7xLd792ULpGE4W_Y.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} + diff --git a/examples/markdown/css/markdown-slides.css b/examples/markdown/css/markdown-slides.css new file mode 100644 index 0000000..ed1e23a --- /dev/null +++ b/examples/markdown/css/markdown-slides.css @@ -0,0 +1,233 @@ +/***** Fonts *****/ + +/* @import url(http://fonts.googleapis.com/css?family=Open+Sans:regular,semibold,italic,italicsemibold|PT+Sans:400,700,400italic,700italic|PT+Serif:400,700,400italic,700italic|Cutive+Mono); */ +@import url(fonts.css); + + +/***** Fallback message *****/ + +.fallback-message { + font-family: sans-serif; + line-height: 1.3; + + width: 780px; + padding: 10px 10px 0; + margin: 20px auto; + + border: 1px solid #E4C652; + border-radius: 10px; + background: #EEDC94; +} + +.fallback-message p { + margin-bottom: 10px; +} + +.impress-supported .fallback-message { + display: none; +} + +/***** Per slide hacks *****/ + +div#step-4 > p:last-child { + margin-top: 150px; + font-size: 0.5em; + text-align: right; +} + +div#tilted-slide { + text-shadow: 20px 20px 10px rgba(0, 0, 0, .4); +} +div#tilted-slide h1 { + margin-top: 200px; +} + +/***** Menu where this style is selected *****/ +.css-menu-bw { + border: solid 1px rgb(102, 102, 102); +} + +.effects .css-menu-bw, +.devopsy .css-menu-bw { + border: none; +} + +/***** Presentation *****/ + +body { + font-family: 'PT Sans', sans-serif; + min-height: 740px; + + background: #fff; +} + +.step { + position: relative; + width: 900px; + height: 700px; + padding: 40px 60px; + margin: 20px auto; + + box-sizing: border-box; + + color: rgb(102, 102, 102); + text-shadow: 0 2px 2px rgba(0, 0, 0, .1); + font-family: 'Open Sans', Arial, sans-serif; + font-size: 30px; + letter-spacing: -1px; + line-height: 1.5; +} + +/* + Make inactive steps a little bit transparent. +*/ +.impress-enabled .step { + margin: 0; + opacity: 0.3; + transition: opacity 1s; +} +.impress-enabled .step.active { opacity: 1 } + +.notes { + display: none; +} + +h1, +h2, +h3 { + margin-bottom: 0.5em; + margin-top: 0.5em; + text-align: center; +} + +p { + margin: 0.7em; +} + +li { + margin: 0.2em; +} + +/* Highlight.js used for coloring pre > code blocks. */ +pre > code { + font-size: 14px; + text-shadow: 0 0 0 rgba(0, 0, 0, 0); +} + +/* Inline code, no Highlight.js */ +code { + font-family: "Cutive mono","Courier New", monospace; +} + + +a { + color: inherit; + text-decoration: none; + padding: 0 0.1em; + text-shadow: -1px 1px 2px rgba(100,100,100,0.9); + border-radius: 0.2em; + + transition: 0.5s; +} +a:hover, +a:focus { + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +blockquote { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; +} + +em { + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strong { + text-shadow: -1px 1px 2px rgba(100,100,100,0.5); +} + +q { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + text-shadow: 0 2px 2px rgba(0, 0, 0, .3); +} + +strike { + opacity: 0.7; +} + +img { + width: 300px; + float: right; + margin-left: 40px; + margin-right: 0px; + margin-top: 20px; + margin-bottom: 20px; +} + + +/* + Specific styles for: .title steps +*/ + +.title h1, +.title h2, +.title h3 { + position: absolute; + left: 45px; /* slide width is 900px, so this is like a 5% margin on both sides */ + width: 90%; + text-align: center; +} +.title h1 { top: 50px; } +.title h2 { top: 400px; } +.title h3 { top: 500px; } + + + +/***** Plugins ******/ +.impress-enabled div#impress-toolbar { + position: fixed; + right: 1px; + bottom: 1px; + opacity: 0.6; +} +.impress-enabled div#impress-toolbar > span { + margin-right: 10px; +} +body.impress-mouse-timeout div#impress-toolbar { + display: none; +} +body.impress-mouse-timeout { + cursor: none; +} +/* Help popup plugin */ +.impress-enabled #impress-help { + background: none repeat scroll 0 0 rgba(0, 0, 0, 0.5); + color: #EEEEEE; + font-size: 80%; + position: fixed; + left: 2em; + bottom: 2em; + width: 24em; + border-radius: 1em; + padding: 1em; + text-align: center; + z-index: 100; + font-family: Verdana, Arial, Sans; +} +.impress-enabled #impress-help td { + padding-left: 1em; + padding-right: 1em; +} + + + +/* + Disable mouse clicks / focus for body +*/ +.impress-enabled { pointer-events: none } +.impress-enabled #impress { pointer-events: auto } +.impress-enabled #impress-toolbar { pointer-events: auto } diff --git a/examples/markdown/images/3476636111_c551295ca4_b.jpg b/examples/markdown/images/3476636111_c551295ca4_b.jpg new file mode 100644 index 0000000..0488bf2 Binary files /dev/null and b/examples/markdown/images/3476636111_c551295ca4_b.jpg differ diff --git a/examples/markdown/index.html b/examples/markdown/index.html new file mode 100644 index 0000000..fa24563 --- /dev/null +++ b/examples/markdown/index.html @@ -0,0 +1,188 @@ + + + + + + + + Markdown in impress.js | by Henrik Ingo @henrikingo + + + + + + + + + + + + + + +
+

Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

+

For the best experience please use the latest Chrome, Safari or Firefox browser.

+
+ +
+ +
+# Markdown +## to author Impress.js presentations + +* This presentation was written entirely in Markdown +* Added by popular request + * Easy way to make quick, simple yet aesthetic, presentations + * Authoring without all the clutter of HTML + +----- +# Markdown.js + +* Provided by [Markdown.js](https://github.com/evilstreak/markdown-js) in [extras/](https://github.com/impress/impress.js/tree/master/extras) +* Jot down your bullet points in *Markdown* & have it automatically converted to HTML +* Note: The Markdown is converted into a presentation client side, in the browser. This is unlike + existing tools like [Hovercraft](https://github.com/regebro/hovercraft) and + [markdown-impress](http://binbinliao.com/markdown-impress/) where you generate a new + html file on the command line. +* This combines the ease of typing Markdown with the full power of impress.js HTML5+CSS3+JavaScript! + +----- +# Styles + +* You can use *italics* & **bold** +* ...and `code` + + +----- +# A blockquote & image + +![Mother Teresa holding a newborn baby](images/3476636111_c551295ca4_b.jpg) + +> Spread love everywhere you go. +> Let no one ever come to you without leaving happier. + +*-- Mother Teresa* + +Image credit: [Peta de Aztlan](https://www.flickr.com/photos/peta-de-aztlan/3476636111/)@Flickr. CC-BY 2.0 + +----- +# Code + +When also using [Highlight.js](https://highlightjs.org/) integration, code blocks in Markdown +are converted to HTML first, then colored by Highlight.js: + + // `init` API function that initializes (and runs) the presentation. + var init = function () { + if (initialized) { return; } + execPreInitPlugins(); + + // First we set up the viewport for mobile devices. + // For some reason iPad goes nuts when it is not done properly. + var meta = $("meta[name='viewport']") || document.createElement("meta"); + meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no"; + if (meta.parentNode !== document.head) { + meta.name = 'viewport'; + document.head.appendChild(meta); + } + +----- + +# Slide separator + +* 5 dashes are used to separate slides: + +`-----` + +* Attributes from `div.step` element are simply repeated. + * Better use relative positioning, lest your slides will all be on top of each other. +* If you need to set some attributes, just use HTML and create a div element, then write + Markdown inside each div. +
+ +
+# Title slide +## This slide has different CSS class than the previous ones +
+ + +
+# Simplicity of Markdown & Full power of Impress.js + +* This slide sets its own `rotate`, `x`, `y`, and even `z` coordinates +* Note that the Mother Teresa slide earlier was pimped with some custom CSS, all the while + the content was written in simple Markdown. +
+ + + + +
+

CSS & JavaScript magic

+ +

Just to emphasize my point, this last slide allows you to use a JavaScript powered menu to +toggle the CSS style:

+ +

Black & white, +Devopsy, +Effects overload

+ +

Simplicity of Markdown married with full power of Impress.js!

+ +
+ + +
+
+ +
+ +
+
+ + + + + + + + + + + + diff --git a/extras b/extras new file mode 160000 index 0000000..6230c2f --- /dev/null +++ b/extras @@ -0,0 +1 @@ +Subproject commit 6230c2ff1060f49eedc4ed1d1b8eec7eb30b8ef5 diff --git a/index.html b/index.html index e508218..7fb5fad 100644 --- a/index.html +++ b/index.html @@ -143,8 +143,12 @@ But as I said, you won't need it for now, so don't worry - there are some simple but interesting things right around the corner of this tag ;) + ---------- + Plugins: We set the default time for autoplay plugin to 6 seconds. Autoplay will automatically advance + to next slide after a timeout expires. + --> -
+
-
+
Aren’t you just bored with all those slides-based presentations?
@@ -256,8 +263,12 @@ So basically every step element has one of three classes: `future`, `present` and `past`. Only one current step has the `present` class. + Note: data-x/y/z attributes, if not defined, by default will inherit the value of the + previous step. So to get back to 0 on the z-axis, we must set it to 0. + See src/plugins/rel/README.md for more information. + --> -
+

by positioning, rotating and scaling them on an infinite canvas

@@ -267,7 +278,7 @@

want to know more?

- use the source, Luke! + use the source, Luke!
@@ -306,11 +317,18 @@ CSS transfrom docs: https://developer.mozilla.org/en/CSS/transform --> -
+
+ +
+
-

Use a spacebar or arrow keys to navigate

+

Use a spacebar or arrow keys to navigate.
+ Press 'P' to launch speaker console.

diff --git a/js/impress.js b/js/impress.js index 25e8996..78d4cbc 100644 --- a/js/impress.js +++ b/js/impress.js @@ -11,18 +11,16 @@ * * ------------------------------------------------ * author: Bartek Szopka - * version: 0.6.0 + * version: 1.0.0-beta1 * url: http://bartaz.github.com/impress.js/ * source: http://github.com/bartaz/impress.js/ */ -/*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, latedef:true, newcap:true, - noarg:true, noempty:true, undef:true, strict:true, browser:true */ - // You are one of those who like to know how things work inside? // Let me show you the cogs that make impress.js run... ( function( document, window ) { "use strict"; + var lib; // HELPER FUNCTIONS @@ -56,10 +54,26 @@ } )(); - // `arrayify` takes an array-like object and turns it into real Array - // to make all the Array.prototype goodness available. - var arrayify = function( a ) { - return [].slice.call( a ); + var validateOrder = function( order, fallback ) { + var validChars = "xyz"; + var returnStr = ""; + if ( typeof order === "string" ) { + for ( var i in order.split( "" ) ) { + if ( validChars.indexOf( order[ i ] >= 0 ) ) { + returnStr += order[ i ]; + + // Each of x,y,z can be used only once. + validChars = validChars.split( order[ i ] ).join( "" ); + } + } + } + if ( returnStr ) { + return returnStr; + } else if ( fallback !== undefined ) { + return fallback; + } else { + return "xyz"; + } }; // `css` function applies the styles given in `props` object to the element @@ -78,40 +92,6 @@ return el; }; - // `toNumber` takes a value given as `numeric` parameter and tries to turn - // it into a number. If it is not possible it returns 0 (or other value - // given as `fallback`). - var toNumber = function( numeric, fallback ) { - return isNaN( numeric ) ? ( fallback || 0 ) : Number( numeric ); - }; - - // `byId` returns element with given `id` - you probably have guessed that ;) - var byId = function( id ) { - return document.getElementById( id ); - }; - - // `$` returns first element for given CSS `selector` in the `context` of - // the given element or whole document. - var $ = function( selector, context ) { - context = context || document; - return context.querySelector( selector ); - }; - - // `$$` return an array of elements for given CSS `selector` in the `context` of - // the given element or whole document. - var $$ = function( selector, context ) { - context = context || document; - return arrayify( context.querySelectorAll( selector ) ); - }; - - // `triggerEvent` builds a custom DOM event with given `eventName` and `detail` data - // and triggers it on element given as `el`. - var triggerEvent = function( el, eventName, detail ) { - var event = document.createEvent( "CustomEvent" ); - event.initCustomEvent( eventName, true, true, detail ); - el.dispatchEvent( event ); - }; - // `translate` builds a translate transform string for given data. var translate = function( t ) { return " translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) "; @@ -121,11 +101,17 @@ // By default the rotations are in X Y Z order that can be reverted by passing `true` // as second parameter. var rotate = function( r, revert ) { - var rX = " rotateX(" + r.x + "deg) ", - rY = " rotateY(" + r.y + "deg) ", - rZ = " rotateZ(" + r.z + "deg) "; + var order = r.order ? r.order : "xyz"; + var css = ""; + var axes = order.split( "" ); + if ( revert ) { + axes = axes.reverse(); + } - return revert ? rZ + rY + rX : rX + rY + rZ; + for ( var i = 0; i < axes.length; i++ ) { + css += " rotate" + axes[ i ].toUpperCase() + "(" + r[ axes[ i ] ] + "deg)"; + } + return css; }; // `scale` builds a scale transform string for given data. @@ -133,15 +119,6 @@ return " scale(" + s + ") "; }; - // `getElementFromHash` returns an element located by id from hash part of - // window location. - var getElementFromHash = function() { - - // Get id from url # by removing `#` or `#/` from the beginning, - // so both "fallback" `#slide-id` and "enhanced" `#/slide-id` will work - return byId( window.location.hash.replace( /^#\/?/, "" ) ); - }; - // `computeWindowScale` counts the scale factor between window size and size // defined for the presentation in the config. var computeWindowScale = function( config ) { @@ -162,29 +139,19 @@ // CHECK SUPPORT var body = document.body; - - var ua = navigator.userAgent.toLowerCase(); var impressSupported = // Browser should support CSS 3D transtorms ( pfx( "perspective" ) !== null ) && - // Browser should support `classList` and `dataset` APIs + // And `classList` and `dataset` APIs ( body.classList ) && - ( body.dataset ) && - - // But some mobile devices need to be blacklisted, - // because their CSS 3D support or hardware is not - // good enough to run impress.js properly, sorry... - ( ua.search( /(iphone)|(ipod)|(android)/ ) === -1 ); + ( body.dataset ); if ( !impressSupported ) { // We can't be sure that `classList` is supported body.className += " impress-not-supported "; - } else { - body.classList.remove( "impress-not-supported" ); - body.classList.add( "impress-supported" ); } // GLOBALS AND DEFAULTS @@ -194,6 +161,9 @@ // sure if it makes any sense in practice ;) var roots = {}; + var preInitPlugins = []; + var preStepLeavePlugins = []; + // Some default config values. var defaults = { width: 1024, @@ -213,7 +183,7 @@ // And that's where interesting things will start to happen. // It's the core `impress` function that returns the impress.js API - // for a presentation based on the element with given id ('impress' + // for a presentation based on the element with given id ("impress" // by default). var impress = window.impress = function( rootId ) { @@ -225,7 +195,10 @@ init: empty, goto: empty, prev: empty, - next: empty + next: empty, + swipe: empty, + tear: empty, + lib: {} }; } @@ -236,6 +209,12 @@ return roots[ "impress-root-" + rootId ]; } + // The gc library depends on being initialized before we do any changes to DOM. + lib = initLibraries( rootId ); + + body.classList.remove( "impress-not-supported" ); + body.classList.add( "impress-supported" ); + // Data of all presentation steps var stepsData = {}; @@ -255,7 +234,7 @@ var windowScale = null; // Root presentation elements - var root = byId( rootId ); + var root = lib.util.byId( rootId ); var canvas = document.createElement( "div" ); var initialized = false; @@ -274,19 +253,23 @@ // `onStepEnter` is called whenever the step element is entered // but the event is triggered only if the step is different than // last entered step. + // We sometimes call `goto`, and therefore `onStepEnter`, just to redraw a step, such as + // after screen resize. In this case - more precisely, in any case - we trigger a + // `impress:steprefresh` event. var onStepEnter = function( step ) { if ( lastEntered !== step ) { - triggerEvent( step, "impress:stepenter" ); + lib.util.triggerEvent( step, "impress:stepenter" ); lastEntered = step; } + lib.util.triggerEvent( step, "impress:steprefresh" ); }; - // `onStepLeave` is called whenever the step element is left - // but the event is triggered only if the step is the same as - // last entered step. - var onStepLeave = function( step ) { - if ( lastEntered === step ) { - triggerEvent( step, "impress:stepleave" ); + // `onStepLeave` is called whenever the currentStep element is left + // but the event is triggered only if the currentStep is the same as + // lastEntered step. + var onStepLeave = function( currentStep, nextStep ) { + if ( lastEntered === currentStep ) { + lib.util.triggerEvent( currentStep, "impress:stepleave", { next: nextStep } ); lastEntered = null; } }; @@ -297,16 +280,20 @@ var data = el.dataset, step = { translate: { - x: toNumber( data.x ), - y: toNumber( data.y ), - z: toNumber( data.z ) + x: lib.util.toNumber( data.x ), + y: lib.util.toNumber( data.y ), + z: lib.util.toNumber( data.z ) }, rotate: { - x: toNumber( data.rotateX ), - y: toNumber( data.rotateY ), - z: toNumber( data.rotateZ || data.rotate ) + x: lib.util.toNumber( data.rotateX ), + y: lib.util.toNumber( data.rotateY ), + z: lib.util.toNumber( data.rotateZ || data.rotate ), + order: validateOrder( data.rotateOrder ) }, - scale: toNumber( data.scale, 1 ), + scale: lib.util.toNumber( data.scale, 1 ), + transitionDuration: lib.util.toNumber( + data.transitionDuration, config.transitionDuration + ), el: el }; @@ -326,13 +313,21 @@ } ); }; + // Initialize all steps. + // Read the data-* attributes, store in internal stepsData, and render with CSS. + var initAllSteps = function() { + steps = lib.util.$$( ".step", root ); + steps.forEach( initStep ); + }; + // `init` API function that initializes (and runs) the presentation. var init = function() { if ( initialized ) { return; } + execPreInitPlugins( root ); // First we set up the viewport for mobile devices. // For some reason iPad goes nuts when it is not done properly. - var meta = $( "meta[name='viewport']" ) || document.createElement( "meta" ); + var meta = lib.util.$( "meta[name='viewport']" ) || document.createElement( "meta" ); meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no"; if ( meta.parentNode !== document.head ) { meta.name = "viewport"; @@ -342,20 +337,20 @@ // Initialize configuration object var rootData = root.dataset; config = { - width: toNumber( rootData.width, defaults.width ), - height: toNumber( rootData.height, defaults.height ), - maxScale: toNumber( rootData.maxScale, defaults.maxScale ), - minScale: toNumber( rootData.minScale, defaults.minScale ), - perspective: toNumber( rootData.perspective, defaults.perspective ), - transitionDuration: toNumber( - rootData.transitionDuration, defaults.transitionDuration + width: lib.util.toNumber( rootData.width, defaults.width ), + height: lib.util.toNumber( rootData.height, defaults.height ), + maxScale: lib.util.toNumber( rootData.maxScale, defaults.maxScale ), + minScale: lib.util.toNumber( rootData.minScale, defaults.minScale ), + perspective: lib.util.toNumber( rootData.perspective, defaults.perspective ), + transitionDuration: lib.util.toNumber( + rootData.transitionDuration, defaults.transitionDuration ) }; windowScale = computeWindowScale( config ); // Wrap steps with "canvas" element - arrayify( root.childNodes ).forEach( function( el ) { + lib.util.arrayify( root.childNodes ).forEach( function( el ) { canvas.appendChild( el ); } ); root.appendChild( canvas ); @@ -388,19 +383,19 @@ body.classList.add( "impress-enabled" ); // Get and init steps - steps = $$( ".step", root ); - steps.forEach( initStep ); + initAllSteps(); // Set a default initial state of the canvas currentState = { translate: { x: 0, y: 0, z: 0 }, - rotate: { x: 0, y: 0, z: 0 }, + rotate: { x: 0, y: 0, z: 0, order: "xyz" }, scale: 1 }; initialized = true; - triggerEvent( root, "impress:init", { api: roots[ "impress-root-" + rootId ] } ); + lib.util.triggerEvent( root, "impress:init", + { api: roots[ "impress-root-" + rootId ] } ); }; // `getStep` is a helper function that returns a step element defined by parameter. @@ -411,7 +406,7 @@ if ( typeof step === "number" ) { step = step < 0 ? steps[ steps.length + step ] : steps[ step ]; } else if ( typeof step === "string" ) { - step = byId( step ); + step = lib.util.byId( step ); } return ( step && step.id && stepsData[ "impress-" + step.id ] ) ? step : null; }; @@ -419,14 +414,25 @@ // Used to reset timeout for `impress:stepenter` event var stepEnterTimeout = null; - // `goto` API function that moves to step given with `el` parameter - // (by index, id or element), with a transition `duration` optionally - // given as second parameter. - var goto = function( el, duration ) { + // `goto` API function that moves to step given as `el` parameter (by index, id or element). + // `duration` optionally given as second parameter, is the transition duration in css. + // `reason` is the string "next", "prev" or "goto" (default) and will be made available to + // preStepLeave plugins. + // `origEvent` may contain event that caused the call to goto, such as a key press event + var goto = function( el, duration, reason, origEvent ) { + reason = reason || "goto"; + origEvent = origEvent || null; - if ( !initialized || !( el = getStep( el ) ) ) { + if ( !initialized ) { + return false; + } - // Presentation not initialized or given element is not a step + // Re-execute initAllSteps for each transition. This allows to edit step attributes + // dynamically, such as change their coordinates, or even remove or add steps, and have + // that change apply when goto() is called. + initAllSteps(); + + if ( !( el = getStep( el ) ) ) { return false; } @@ -442,6 +448,32 @@ window.scrollTo( 0, 0 ); var step = stepsData[ "impress-" + el.id ]; + duration = ( duration !== undefined ? duration : step.transitionDuration ); + + // If we are in fact moving to another step, start with executing the registered + // preStepLeave plugins. + if ( activeStep && activeStep !== el ) { + var event = { target: activeStep, detail: {} }; + event.detail.next = el; + event.detail.transitionDuration = duration; + event.detail.reason = reason; + if ( origEvent ) { + event.origEvent = origEvent; + } + + if ( execPreStepLeavePlugins( event ) === false ) { + + // PreStepLeave plugins are allowed to abort the transition altogether, by + // returning false. + // see stop and substep plugins for an example of doing just that + return false; + } + + // Plugins are allowed to change the detail values + el = event.detail.next; + step = stepsData[ "impress-" + el.id ]; + duration = event.detail.transitionDuration; + } if ( activeStep ) { activeStep.classList.remove( "active" ); @@ -456,7 +488,8 @@ rotate: { x: -step.rotate.x, y: -step.rotate.y, - z: -step.rotate.z + z: -step.rotate.z, + order: step.rotate.order }, translate: { x: -step.translate.x, @@ -474,7 +507,7 @@ // with scaling down and move and rotation are delayed. var zoomin = target.scale >= currentState.scale; - duration = toNumber( duration, config.transitionDuration ); + duration = lib.util.toNumber( duration, config.transitionDuration ); var delay = ( duration / 2 ); // If the same step is re-selected, force computing window scaling, @@ -487,7 +520,7 @@ // Trigger leave of currently active element (if it's not the same step again) if ( activeStep && activeStep !== el ) { - onStepLeave( activeStep ); + onStepLeave( activeStep, el ); } // Now we alter transforms of `root` and `canvas` to trigger transitions. @@ -496,16 +529,15 @@ // being animated separately: // `root` is used for scaling and `canvas` for translate and rotations. // Transitions on them are triggered with different delays (to make - // visually nice and 'natural' looking transitions), so we need to know + // visually nice and "natural" looking transitions), so we need to know // that both of them are finished. css( root, { + // To keep the perspective look similar for different scales + // we need to "scale" the perspective, too // For IE 11 support we must specify perspective independent // of transform. perspective: ( config.perspective / targetScale ) + "px", - - // To keep the perspective look similar for different scales - // we need to 'scale' the perspective, too transform: scale( targetScale ), transitionDuration: duration + "ms", transitionDelay: ( zoomin ? delay : 0 ) + "ms" @@ -526,8 +558,7 @@ // account. // // I know that this `if` statement looks scary, but it's pretty simple when you know - // what is going on - // - it's simply comparing all the values. + // what is going on - it's simply comparing all the values. if ( currentState.scale === target.scale || ( currentState.rotate.x === target.rotate.x && currentState.rotate.y === target.rotate.y && @@ -543,22 +574,20 @@ activeStep = el; // And here is where we trigger `impress:stepenter` event. - // We simply set up a timeout to fire it taking transition duration - // (and possible delay) into account. + // We simply set up a timeout to fire it taking transition duration (and possible delay) + // into account. // // I really wanted to make it in more elegant way. The `transitionend` event seemed to // be the best way to do it, but the fact that I'm using transitions on two separate // elements and that the `transitionend` event is only triggered when there was a // transition (change in the values) caused some bugs and made the code really // complicated, cause I had to handle all the conditions separately. And it still - // needed a `setTimeout` fallback for the situations when there is no transition at - // all. + // needed a `setTimeout` fallback for the situations when there is no transition at all. // So I decided that I'd rather make the code simpler than use shiny new // `transitionend`. // // If you want learn something interesting and see how it was done with `transitionend` - // go back to - // version 0.5.2 of impress.js: + // go back to version 0.5.2 of impress.js: // http://github.com/bartaz/impress.js/blob/0.5.2/js/impress.js window.clearTimeout( stepEnterTimeout ); stepEnterTimeout = window.setTimeout( function() { @@ -569,19 +598,138 @@ }; // `prev` API function goes to previous step (in document order) - var prev = function() { + // `event` is optional, may contain the event that caused the need to call prev() + var prev = function( origEvent ) { var prev = steps.indexOf( activeStep ) - 1; prev = prev >= 0 ? steps[ prev ] : steps[ steps.length - 1 ]; - return goto( prev ); + return goto( prev, undefined, "prev", origEvent ); }; // `next` API function goes to next step (in document order) - var next = function() { + // `event` is optional, may contain the event that caused the need to call next() + var next = function( origEvent ) { var next = steps.indexOf( activeStep ) + 1; next = next < steps.length ? steps[ next ] : steps[ 0 ]; - return goto( next ); + return goto( next, undefined, "next", origEvent ); + }; + + // Swipe for touch devices by @and3rson. + // Below we extend the api to control the animation between the currently + // active step and a presumed next/prev step. See touch plugin for + // an example of using this api. + + // Helper function + var interpolate = function( a, b, k ) { + return a + ( b - a ) * k; + }; + + // Animate a swipe. + // + // Pct is a value between -1.0 and +1.0, designating the current length + // of the swipe. + // + // If pct is negative, swipe towards the next() step, if positive, + // towards the prev() step. + // + // Note that pre-stepleave plugins such as goto can mess with what is a + // next() and prev() step, so we need to trigger the pre-stepleave event + // here, even if a swipe doesn't guarantee that the transition will + // actually happen. + // + // Calling swipe(), with any value of pct, won't in itself cause a + // transition to happen, this is just to animate the swipe. Once the + // transition is committed - such as at a touchend event - caller is + // responsible for also calling prev()/next() as appropriate. + // + // Note: For now, this function is made available to be used by the swipe plugin (which + // is the UI counterpart to this). It is a semi-internal API and intentionally not + // documented in DOCUMENTATION.md. + var swipe = function( pct ) { + if ( Math.abs( pct ) > 1 ) { + return; + } + + // Prepare & execute the preStepLeave event + var event = { target: activeStep, detail: {} }; + event.detail.swipe = pct; + + // Will be ignored within swipe animation, but just in case a plugin wants to read this, + // humor them + event.detail.transitionDuration = config.transitionDuration; + var idx; // Needed by jshint + if ( pct < 0 ) { + idx = steps.indexOf( activeStep ) + 1; + event.detail.next = idx < steps.length ? steps[ idx ] : steps[ 0 ]; + event.detail.reason = "next"; + } else if ( pct > 0 ) { + idx = steps.indexOf( activeStep ) - 1; + event.detail.next = idx >= 0 ? steps[ idx ] : steps[ steps.length - 1 ]; + event.detail.reason = "prev"; + } else { + + // No move + return; + } + if ( execPreStepLeavePlugins( event ) === false ) { + + // If a preStepLeave plugin wants to abort the transition, don't animate a swipe + // For stop, this is probably ok. For substep, the plugin it self might want to do + // some animation, but that's not the current implementation. + return false; + } + var nextElement = event.detail.next; + + var nextStep = stepsData[ "impress-" + nextElement.id ]; + + // If the same step is re-selected, force computing window scaling, + var nextScale = nextStep.scale * windowScale; + var k = Math.abs( pct ); + + var interpolatedStep = { + translate: { + x: interpolate( currentState.translate.x, -nextStep.translate.x, k ), + y: interpolate( currentState.translate.y, -nextStep.translate.y, k ), + z: interpolate( currentState.translate.z, -nextStep.translate.z, k ) + }, + rotate: { + x: interpolate( currentState.rotate.x, -nextStep.rotate.x, k ), + y: interpolate( currentState.rotate.y, -nextStep.rotate.y, k ), + z: interpolate( currentState.rotate.z, -nextStep.rotate.z, k ), + + // Unfortunately there's a discontinuity if rotation order changes. Nothing I + // can do about it? + order: k < 0.7 ? currentState.rotate.order : nextStep.rotate.order + }, + scale: interpolate( currentState.scale, nextScale, k ) + }; + + css( root, { + + // To keep the perspective look similar for different scales + // we need to 'scale' the perspective, too + perspective: config.perspective / interpolatedStep.scale + "px", + transform: scale( interpolatedStep.scale ), + transitionDuration: "0ms", + transitionDelay: "0ms" + } ); + + css( canvas, { + transform: rotate( interpolatedStep.rotate, true ) + + translate( interpolatedStep.translate ), + transitionDuration: "0ms", + transitionDelay: "0ms" + } ); + }; + + // Teardown impress + // Resets the DOM to the state it was before impress().init() was called. + // (If you called impress(rootId).init() for multiple different rootId's, then you must + // also call tear() once for each of them.) + var tear = function() { + lib.gc.teardown(); + delete roots[ "impress-root-" + rootId ]; }; // Adding some useful classes to step elements. @@ -597,20 +745,20 @@ // There classes can be used in CSS to style different types of steps. // For example the `present` class can be used to trigger some custom // animations when step is shown. - root.addEventListener( "impress:init", function() { + lib.gc.addEventListener( root, "impress:init", function() { // STEP CLASSES steps.forEach( function( step ) { step.classList.add( "future" ); } ); - root.addEventListener( "impress:stepenter", function( event ) { + lib.gc.addEventListener( root, "impress:stepenter", function( event ) { event.target.classList.remove( "past" ); event.target.classList.remove( "future" ); event.target.classList.add( "present" ); }, false ); - root.addEventListener( "impress:stepleave", function( event ) { + lib.gc.addEventListener( root, "impress:stepleave", function( event ) { event.target.classList.remove( "present" ); event.target.classList.add( "past" ); }, false ); @@ -618,7 +766,7 @@ }, false ); // Adding hash change support. - root.addEventListener( "impress:init", function() { + lib.gc.addEventListener( root, "impress:init", function() { // Last hash detected var lastHash = ""; @@ -629,11 +777,11 @@ // And it has to be set after animation finishes, because in Chrome it // makes transtion laggy. // BUG: http://code.google.com/p/chromium/issues/detail?id=62820 - root.addEventListener( "impress:stepenter", function( event ) { + lib.gc.addEventListener( root, "impress:stepenter", function( event ) { window.location.hash = lastHash = "#/" + event.target.id; }, false ); - window.addEventListener( "hashchange", function() { + lib.gc.addEventListener( window, "hashchange", function() { // When the step is entered hash in the location is updated // (just few lines above from here), so the hash change is @@ -641,13 +789,13 @@ // // To avoid this we store last entered hash and compare. if ( window.location.hash !== lastHash ) { - goto( getElementFromHash() ); + goto( lib.util.getElementFromHash() ); } }, false ); // START // by selecting step defined in url or first step of the presentation - goto( getElementFromHash() || steps[ 0 ], 0 ); + goto( lib.util.getElementFromHash() || steps[ 0 ], 0 ); }, false ); body.classList.add( "impress-disabled" ); @@ -657,7 +805,10 @@ init: init, goto: goto, next: next, - prev: prev + prev: prev, + swipe: swipe, + tear: tear, + lib: lib } ); }; @@ -665,32 +816,2050 @@ // Flag that can be used in JS to check if browser have passed the support test impress.supported = impressSupported; + // ADD and INIT LIBRARIES + // Library factories are defined in src/lib/*.js, and register themselves by calling + // impress.addLibraryFactory(libraryFactoryObject). They're stored here, and used to augment + // the API with library functions when client calls impress(rootId). + // See src/lib/README.md for clearer example. + // (Advanced usage: For different values of rootId, a different instance of the libaries are + // generated, in case they need to hold different state for different root elements.) + var libraryFactories = {}; + impress.addLibraryFactory = function( obj ) { + for ( var libname in obj ) { + if ( obj.hasOwnProperty( libname ) ) { + libraryFactories[ libname ] = obj[ libname ]; + } + } + }; + + // Call each library factory, and return the lib object that is added to the api. + var initLibraries = function( rootId ) { //jshint ignore:line + var lib = {}; + for ( var libname in libraryFactories ) { + if ( libraryFactories.hasOwnProperty( libname ) ) { + if ( lib[ libname ] !== undefined ) { + throw "impress.js ERROR: Two libraries both tried to use libname: " + libname; + } + lib[ libname ] = libraryFactories[ libname ]( rootId ); + } + } + return lib; + }; + + // `addPreInitPlugin` allows plugins to register a function that should + // be run (synchronously) at the beginning of init, before + // impress().init() itself executes. + impress.addPreInitPlugin = function( plugin, weight ) { + weight = parseInt( weight ) || 10; + if ( weight <= 0 ) { + throw "addPreInitPlugin: weight must be a positive integer"; + } + + if ( preInitPlugins[ weight ] === undefined ) { + preInitPlugins[ weight ] = []; + } + preInitPlugins[ weight ].push( plugin ); + }; + + // Called at beginning of init, to execute all pre-init plugins. + var execPreInitPlugins = function( root ) { //jshint ignore:line + for ( var i = 0; i < preInitPlugins.length; i++ ) { + var thisLevel = preInitPlugins[ i ]; + if ( thisLevel !== undefined ) { + for ( var j = 0; j < thisLevel.length; j++ ) { + thisLevel[ j ]( root ); + } + } + } + }; + + // `addPreStepLeavePlugin` allows plugins to register a function that should + // be run (synchronously) at the beginning of goto() + impress.addPreStepLeavePlugin = function( plugin, weight ) { //jshint ignore:line + weight = parseInt( weight ) || 10; + if ( weight <= 0 ) { + throw "addPreStepLeavePlugin: weight must be a positive integer"; + } + + if ( preStepLeavePlugins[ weight ] === undefined ) { + preStepLeavePlugins[ weight ] = []; + } + preStepLeavePlugins[ weight ].push( plugin ); + }; + + // Called at beginning of goto(), to execute all preStepLeave plugins. + var execPreStepLeavePlugins = function( event ) { //jshint ignore:line + for ( var i = 0; i < preStepLeavePlugins.length; i++ ) { + var thisLevel = preStepLeavePlugins[ i ]; + if ( thisLevel !== undefined ) { + for ( var j = 0; j < thisLevel.length; j++ ) { + if ( thisLevel[ j ]( event ) === false ) { + + // If a plugin returns false, the stepleave event (and related transition) + // is aborted + return false; + } + } + } + } + }; + } )( document, window ); -// NAVIGATION EVENTS - -// As you can see this part is separate from the impress.js core code. -// It's because these navigation actions only need what impress.js provides with -// its simple API. +// THAT'S ALL FOLKS! // -// In future I think about moving it to make them optional, move to separate files -// and treat more like a 'plugins'. +// Thanks for reading it all. +// Or thanks for scrolling down and reading the last part. +// +// I've learnt a lot when building impress.js and I hope this code and comments +// will help somebody learn at least some part of it. + +/** + * Garbage collection utility + * + * This library allows plugins to add elements and event listeners they add to the DOM. The user + * can call `impress().lib.gc.teardown()` to cause all of them to be removed from DOM, so that + * the document is in the state it was before calling `impress().init()`. + * + * In addition to just adding elements and event listeners to the garbage collector, plugins + * can also register callback functions to do arbitrary cleanup upon teardown. + * + * Henrik Ingo (c) 2016 + * MIT License + */ + +( function( document, window ) { + "use strict"; + var roots = []; + var rootsCount = 0; + var startingState = { roots: [] }; + + var libraryFactory = function( rootId ) { + if ( roots[ rootId ] ) { + return roots[ rootId ]; + } + + // Per root global variables (instance variables?) + var elementList = []; + var eventListenerList = []; + var callbackList = []; + + recordStartingState( rootId ); + + // LIBRARY FUNCTIONS + // Definitions of the library functions we return as an object at the end + + // `pushElement` adds a DOM element to the gc stack + var pushElement = function( element ) { + elementList.push( element ); + }; + + // `appendChild` is a convenience wrapper that combines DOM appendChild with gc.pushElement + var appendChild = function( parent, element ) { + parent.appendChild( element ); + pushElement( element ); + }; + + // `pushEventListener` adds an event listener to the gc stack + var pushEventListener = function( target, type, listenerFunction ) { + eventListenerList.push( { target:target, type:type, listener:listenerFunction } ); + }; + + // `addEventListener` combines DOM addEventListener with gc.pushEventListener + var addEventListener = function( target, type, listenerFunction ) { + target.addEventListener( type, listenerFunction ); + pushEventListener( target, type, listenerFunction ); + }; + + // `pushCallback` If the above utilities are not enough, plugins can add their own callback + // function to do arbitrary things. + var pushCallback = function( callback ) { + callbackList.push( callback ); + }; + pushCallback( function( rootId ) { resetStartingState( rootId ); } ); + + // `teardown` will + // - execute all callbacks in LIFO order + // - call `removeChild` on all DOM elements in LIFO order + // - call `removeEventListener` on all event listeners in LIFO order + // The goal of a teardown is to return to the same state that the DOM was before + // `impress().init()` was called. + var teardown = function() { + + // Execute the callbacks in LIFO order + var i; // Needed by jshint + for ( i = callbackList.length - 1; i >= 0; i-- ) { + callbackList[ i ]( rootId ); + } + callbackList = []; + for ( i = 0; i < elementList.length; i++ ) { + elementList[ i ].parentElement.removeChild( elementList[ i ] ); + } + elementList = []; + for ( i = 0; i < eventListenerList.length; i++ ) { + var target = eventListenerList[ i ].target; + var type = eventListenerList[ i ].type; + var listener = eventListenerList[ i ].listener; + target.removeEventListener( type, listener ); + } + }; + + var lib = { + pushElement: pushElement, + appendChild: appendChild, + pushEventListener: pushEventListener, + addEventListener: addEventListener, + pushCallback: pushCallback, + teardown: teardown + }; + roots[ rootId ] = lib; + rootsCount++; + return lib; + }; + + // Let impress core know about the existence of this library + window.impress.addLibraryFactory( { gc: libraryFactory } ); + + // CORE INIT + // The library factory (gc(rootId)) is called at the beginning of impress(rootId).init() + // For the purposes of teardown(), we can use this as an opportunity to save the state + // of a few things in the DOM in their virgin state, before impress().init() did anything. + // Note: These could also be recorded by the code in impress.js core as these values + // are changed, but in an effort to not deviate too much from upstream, I'm adding + // them here rather than the core itself. + var recordStartingState = function( rootId ) { + startingState.roots[ rootId ] = {}; + startingState.roots[ rootId ].steps = []; + + // Record whether the steps have an id or not + var steps = document.getElementById( rootId ).querySelectorAll( ".step" ); + for ( var i = 0; i < steps.length; i++ ) { + var el = steps[ i ]; + startingState.roots[ rootId ].steps.push( { + el: el, + id: el.getAttribute( "id" ) + } ); + } + + // In the rare case of multiple roots, the following is changed on first init() and + // reset at last tear(). + if ( rootsCount === 0 ) { + startingState.body = {}; + + // It is customary for authors to set body.class="impress-not-supported" as a starting + // value, which can then be removed by impress().init(). But it is not required. + // Remember whether it was there or not. + if ( document.body.classList.contains( "impress-not-supported" ) ) { + startingState.body.impressNotSupported = true; + } else { + startingState.body.impressNotSupported = false; + } + + // If there's a element, its contents will be overwritten by init + var metas = document.head.querySelectorAll( "meta" ); + for ( i = 0; i < metas.length; i++ ) { + var m = metas[ i ]; + if ( m.name === "viewport" ) { + startingState.meta = m.content; + } + } + } + }; + + // CORE TEARDOWN + var resetStartingState = function( rootId ) { + + // Reset body element + document.body.classList.remove( "impress-enabled" ); + document.body.classList.remove( "impress-disabled" ); + + var root = document.getElementById( rootId ); + var activeId = root.querySelector( ".active" ).id; + document.body.classList.remove( "impress-on-" + activeId ); + + document.documentElement.style.height = ""; + document.body.style.height = ""; + document.body.style.overflow = ""; + + // Remove style values from the root and step elements + // Note: We remove the ones set by impress.js core. Otoh, we didn't preserve any original + // values. A more sophisticated implementation could keep track of original values and then + // reset those. + var steps = root.querySelectorAll( ".step" ); + for ( var i = 0; i < steps.length; i++ ) { + steps[ i ].classList.remove( "future" ); + steps[ i ].classList.remove( "past" ); + steps[ i ].classList.remove( "present" ); + steps[ i ].classList.remove( "active" ); + steps[ i ].style.position = ""; + steps[ i ].style.transform = ""; + steps[ i ].style[ "transform-style" ] = ""; + } + root.style.position = ""; + root.style[ "transform-origin" ] = ""; + root.style.transition = ""; + root.style[ "transform-style" ] = ""; + root.style.top = ""; + root.style.left = ""; + root.style.transform = ""; + + // Reset id of steps ("step-1" id's are auto generated) + steps = startingState.roots[ rootId ].steps; + var step; + while ( step = steps.pop() ) { + if ( step.id === null ) { + step.el.removeAttribute( "id" ); + } else { + step.el.setAttribute( "id", step.id ); + } + } + delete startingState.roots[ rootId ]; + + // Move step div elements away from canvas, then delete canvas + // Note: There's an implicit assumption here that the canvas div is the only child element + // of the root div. If there would be something else, it's gonna be lost. + var canvas = root.firstChild; + var canvasHTML = canvas.innerHTML; + root.innerHTML = canvasHTML; + + if ( roots[ rootId ] !== undefined ) { + delete roots[ rootId ]; + rootsCount--; + } + if ( rootsCount === 0 ) { + + // In the rare case that more than one impress root elements were initialized, these + // are only reset when all are uninitialized. + document.body.classList.remove( "impress-supported" ); + if ( startingState.body.impressNotSupported ) { + document.body.classList.add( "impress-not-supported" ); + } + + // We need to remove or reset the meta element inserted by impress.js + var metas = document.head.querySelectorAll( "meta" ); + for ( i = 0; i < metas.length; i++ ) { + var m = metas[ i ]; + if ( m.name === "viewport" ) { + if ( startingState.meta !== undefined ) { + m.content = startingState.meta; + } else { + m.parentElement.removeChild( m ); + } + } + } + } + + }; + +} )( document, window ); + +/** + * Common utility functions + * + * Copyright 2011-2012 Bartek Szopka (@bartaz) + * Henrik Ingo (c) 2016 + * MIT License + */ + +( function( document, window ) { + "use strict"; + var roots = []; + + var libraryFactory = function( rootId ) { + if ( roots[ rootId ] ) { + return roots[ rootId ]; + } + + // `$` returns first element for given CSS `selector` in the `context` of + // the given element or whole document. + var $ = function( selector, context ) { + context = context || document; + return context.querySelector( selector ); + }; + + // `$$` return an array of elements for given CSS `selector` in the `context` of + // the given element or whole document. + var $$ = function( selector, context ) { + context = context || document; + return arrayify( context.querySelectorAll( selector ) ); + }; + + // `arrayify` takes an array-like object and turns it into real Array + // to make all the Array.prototype goodness available. + var arrayify = function( a ) { + return [].slice.call( a ); + }; + + // `byId` returns element with given `id` - you probably have guessed that ;) + var byId = function( id ) { + return document.getElementById( id ); + }; + + // `getElementFromHash` returns an element located by id from hash part of + // window location. + var getElementFromHash = function() { + + // Get id from url # by removing `#` or `#/` from the beginning, + // so both "fallback" `#slide-id` and "enhanced" `#/slide-id` will work + return byId( window.location.hash.replace( /^#\/?/, "" ) ); + }; + + // Throttling function calls, by Remy Sharp + // http://remysharp.com/2010/07/21/throttling-function-calls/ + var throttle = function( fn, delay ) { + var timer = null; + return function() { + var context = this, args = arguments; + window.clearTimeout( timer ); + timer = window.setTimeout( function() { + fn.apply( context, args ); + }, delay ); + }; + }; + + // `toNumber` takes a value given as `numeric` parameter and tries to turn + // it into a number. If it is not possible it returns 0 (or other value + // given as `fallback`). + var toNumber = function( numeric, fallback ) { + return isNaN( numeric ) ? ( fallback || 0 ) : Number( numeric ); + }; + + // `triggerEvent` builds a custom DOM event with given `eventName` and `detail` data + // and triggers it on element given as `el`. + var triggerEvent = function( el, eventName, detail ) { + var event = document.createEvent( "CustomEvent" ); + event.initCustomEvent( eventName, true, true, detail ); + el.dispatchEvent( event ); + }; + + var lib = { + $: $, + $$: $$, + arrayify: arrayify, + byId: byId, + getElementFromHash: getElementFromHash, + throttle: throttle, + toNumber: toNumber, + triggerEvent: triggerEvent + }; + roots[ rootId ] = lib; + return lib; + }; + + // Let impress core know about the existence of this library + window.impress.addLibraryFactory( { util: libraryFactory } ); + +} )( document, window ); + +/** + * Autoplay plugin - Automatically advance slideshow after N seconds + * + * Copyright 2016 Henrik Ingo, henrik.ingo@avoinelama.fi + * Released under the MIT license. + */ +/* global clearTimeout, setTimeout, document */ + +( function( document ) { + "use strict"; + + var autoplayDefault = 0; + var currentStepTimeout = 0; + var api = null; + var timeoutHandle = null; + var root = null; + var util; + + // On impress:init, check whether there is a default setting, as well as + // handle step-1. + document.addEventListener( "impress:init", function( event ) { + util = event.detail.api.lib.util; + + // Getting API from event data instead of global impress().init(). + // You don't even need to know what is the id of the root element + // or anything. `impress:init` event data gives you everything you + // need to control the presentation that was just initialized. + api = event.detail.api; + root = event.target; + + // Element attributes starting with "data-", become available under + // element.dataset. In addition hyphenized words become camelCased. + var data = root.dataset; + + if ( data.autoplay ) { + autoplayDefault = util.toNumber( data.autoplay, 0 ); + } + + var toolbar = document.querySelector( "#impress-toolbar" ); + if ( toolbar ) { + addToolbarButton( toolbar ); + } + + api.lib.gc.pushCallback( function() { + clearTimeout( timeoutHandle ); + } ); + + // Note that right after impress:init event, also impress:stepenter is + // triggered for the first slide, so that's where code flow continues. + }, false ); + + // If default autoplay time was defined in the presentation root, or + // in this step, set timeout. + var reloadTimeout = function( event ) { + var step = event.target; + currentStepTimeout = util.toNumber( step.dataset.autoplay, autoplayDefault ); + if ( status === "paused" ) { + setAutoplayTimeout( 0 ); + } else { + setAutoplayTimeout( currentStepTimeout ); + } + }; + + document.addEventListener( "impress:stepenter", function( event ) { + reloadTimeout( event ); + }, false ); + + document.addEventListener( "impress:substep:stepleaveaborted", function( event ) { + reloadTimeout( event ); + }, false ); + + /** + * Set timeout after which we move to next() step. + */ + var setAutoplayTimeout = function( timeout ) { + if ( timeoutHandle ) { + clearTimeout( timeoutHandle ); + } + + if ( timeout > 0 ) { + timeoutHandle = setTimeout( function() { api.next(); }, timeout * 1000 ); + } + setButtonText(); + }; + + /*** Toolbar plugin integration *******************************************/ + var status = "not clicked"; + var toolbarButton = null; + + // Copied from core impress.js. Good candidate for moving to a utilities collection. + var triggerEvent = function( el, eventName, detail ) { + var event = document.createEvent( "CustomEvent" ); + event.initCustomEvent( eventName, true, true, detail ); + el.dispatchEvent( event ); + }; + + var makeDomElement = function( html ) { + var tempDiv = document.createElement( "div" ); + tempDiv.innerHTML = html; + return tempDiv.firstChild; + }; + + var toggleStatus = function() { + if ( currentStepTimeout > 0 && status !== "paused" ) { + status = "paused"; + } else { + status = "playing"; + } + }; + + var getButtonText = function() { + if ( currentStepTimeout > 0 && status !== "paused" ) { + return "||"; // Pause + } else { + return "▶"; // Play + } + }; + + var setButtonText = function() { + if ( toolbarButton ) { + + // Keep button size the same even if label content is changing + var buttonWidth = toolbarButton.offsetWidth; + var buttonHeight = toolbarButton.offsetHeight; + toolbarButton.innerHTML = getButtonText(); + if ( !toolbarButton.style.width ) { + toolbarButton.style.width = buttonWidth + "px"; + } + if ( !toolbarButton.style.height ) { + toolbarButton.style.height = buttonHeight + "px"; + } + } + }; + + var addToolbarButton = function( toolbar ) { + var html = '"; // jshint ignore:line + toolbarButton = makeDomElement( html ); + toolbarButton.addEventListener( "click", function() { + toggleStatus(); + if ( status === "playing" ) { + if ( autoplayDefault === 0 ) { + autoplayDefault = 7; + } + if ( currentStepTimeout === 0 ) { + currentStepTimeout = autoplayDefault; + } + setAutoplayTimeout( currentStepTimeout ); + } else if ( status === "paused" ) { + setAutoplayTimeout( 0 ); + } + } ); + + triggerEvent( toolbar, "impress:toolbar:appendChild", + { group: 10, element: toolbarButton } ); + }; + +} )( document ); + +/** + * Blackout plugin + * + * Press Ctrl+b to hide all slides, and Ctrl+b again to show them. + * Also navigating to a different slide will show them again (impress:stepleave). + * + * Copyright 2014 @Strikeskids + * Released under the MIT license. + */ +/* global document */ + +( function( document ) { + "use strict"; + + var canvas = null; + var blackedOut = false; + + // While waiting for a shared library of utilities, copying these 2 from main impress.js + var css = function( el, props ) { + var key, pkey; + for ( key in props ) { + if ( props.hasOwnProperty( key ) ) { + pkey = pfx( key ); + if ( pkey !== null ) { + el.style[ pkey ] = props[ key ]; + } + } + } + return el; + }; + + var pfx = ( function() { + + var style = document.createElement( "dummy" ).style, + prefixes = "Webkit Moz O ms Khtml".split( " " ), + memory = {}; + + return function( prop ) { + if ( typeof memory[ prop ] === "undefined" ) { + + var ucProp = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ), + props = ( prop + " " + prefixes.join( ucProp + " " ) + ucProp ).split( " " ); + + memory[ prop ] = null; + for ( var i in props ) { + if ( style[ props[ i ] ] !== undefined ) { + memory[ prop ] = props[ i ]; + break; + } + } + + } + + return memory[ prop ]; + }; + + } )(); + + var removeBlackout = function() { + if ( blackedOut ) { + css( canvas, { + display: "block" + } ); + blackedOut = false; + } + }; + + var blackout = function() { + if ( blackedOut ) { + removeBlackout(); + } else { + css( canvas, { + display: ( blackedOut = !blackedOut ) ? "none" : "block" + } ); + blackedOut = true; + } + }; + + // Wait for impress.js to be initialized + document.addEventListener( "impress:init", function( event ) { + var api = event.detail.api; + var root = event.target; + canvas = root.firstElementChild; + var gc = api.lib.gc; + + gc.addEventListener( document, "keydown", function( event ) { + if ( event.ctrlKey && event.keyCode === 66 ) { + event.preventDefault(); + if ( !blackedOut ) { + blackout(); + } else { + + // Note: This doesn't work on Firefox. It will set display:block, + // but slides only become visible again upon next transition, which + // forces some kind of redraw. Works as intended on Chrome. + removeBlackout(); + } + } + }, false ); + + gc.addEventListener( document, "keyup", function( event ) { + if ( event.ctrlKey && event.keyCode === 66 ) { + event.preventDefault(); + } + }, false ); + + }, false ); + + document.addEventListener( "impress:stepleave", function() { + removeBlackout(); + }, false ); + +} )( document ); + + +/** + * Extras Plugin + * + * This plugin performs initialization (like calling mermaid.initialize()) + * for the extras/ plugins if they are loaded into a presentation. + * + * See README.md for details. + * + * Copyright 2016 Henrik Ingo (@henrikingo) + * Released under the MIT license. + */ +/* global markdown, hljs, mermaid, impress, document, window */ + ( function( document, window ) { "use strict"; - // Throttling function calls, by Remy Sharp - // http://remysharp.com/2010/07/21/throttling-function-calls/ - var throttle = function( fn, delay ) { - var timer = null; - return function() { - var context = this, args = arguments; - clearTimeout( timer ); - timer = setTimeout( function() { - fn.apply( context, args ); - }, delay ); - }; + var preInit = function() { + if ( window.markdown ) { + + // Unlike the other extras, Markdown.js doesn't by default do anything in + // particular. We do it ourselves here. + // In addition, we use "-----" as a delimiter for new slide. + + // Query all .markdown elements and translate to HTML + var markdownDivs = document.querySelectorAll( ".markdown" ); + for ( var idx = 0; idx < markdownDivs.length; idx++ ) { + var element = markdownDivs[ idx ]; + + var slides = element.textContent.split( /^-----$/m ); + var i = slides.length - 1; + element.innerHTML = markdown.toHTML( slides[ i ] ); + + // If there's an id, unset it for last, and all other, elements, + // and then set it for the first. + var id = null; + if ( element.id ) { + id = element.id; + element.id = ""; + } + i--; + while ( i >= 0 ) { + var newElement = element.cloneNode( false ); + newElement.innerHTML = markdown.toHTML( slides[ i ] ); + element.parentNode.insertBefore( newElement, element ); + element = newElement; + i--; + } + if ( id !== null ) { + element.id = id; + } + } + } // Markdown + + if ( window.hljs ) { + hljs.initHighlightingOnLoad(); + } + + if ( window.mermaid ) { + mermaid.initialize( { startOnLoad:true } ); + } }; + // Register the plugin to be called in pre-init phase + // Note: Markdown.js should run early/first, because it creates new div elements. + // So add this with a lower-than-default weight. + impress.addPreInitPlugin( preInit, 1 ); + +} )( document, window ); + + +/** + * Form support + * + * Functionality to better support use of input, textarea, button... elements in a presentation. + * + * Currently this does only one single thing: On impress:stepleave, de-focus any potentially active + * element. This is to prevent the focus from being left in a form element that is no longer visible + * in the window, and user therefore typing garbage into the form. + * + * TODO: Currently it is not possible to use TAB to navigate between form elements. Impress.js, and + * in particular the navigation plugin, unfortunately must fully take control of the tab key, + * otherwise a user could cause the browser to scroll to a link or button that's not on the current + * step. However, it could be possible to allow tab navigation between form elements, as long as + * they are on the active step. This is a topic for further study. + * + * Copyright 2016 Henrik Ingo + * MIT License + */ +/* global document */ +( function( document ) { + "use strict"; + + document.addEventListener( "impress:stepleave", function() { + document.activeElement.blur(); + }, false ); + +} )( document ); + + +/** + * Goto Plugin + * + * The goto plugin is a pre-stepleave plugin. It is executed before impress:stepleave, + * and will alter the destination where to transition next. + * + * Example: + * + * + *
+ * + * + *
+ * + * + *
+ * + * See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values for a table + * of what strings to use for each key. + * + * Copyright 2016-2017 Henrik Ingo (@henrikingo) + * Released under the MIT license. + */ +/* global window, document, impress */ + +( function( document, window ) { + "use strict"; + var lib; + + document.addEventListener( "impress:init", function( event ) { + lib = event.detail.api.lib; + }, false ); + + var isNumber = function( numeric ) { + return !isNaN( numeric ); + }; + + var goto = function( event ) { + if ( ( !event ) || ( !event.target ) ) { + return; + } + + var data = event.target.dataset; + var steps = document.querySelectorAll( ".step" ); + + // Data-goto-key-list="" & data-goto-next-list="" ////////////////////////////////////////// + if ( data.gotoKeyList !== undefined && + data.gotoNextList !== undefined && + event.origEvent !== undefined && + event.origEvent.key !== undefined ) { + var keylist = data.gotoKeyList.split( " " ); + var nextlist = data.gotoNextList.split( " " ); + + if ( keylist.length !== nextlist.length ) { + window.console.log( + "impress goto plugin: data-goto-key-list and data-goto-next-list don't match:" + ); + window.console.log( keylist ); + window.console.log( nextlist ); + + // Don't return, allow the other categories to work despite this error + } else { + var index = keylist.indexOf( event.origEvent.key ); + if ( index >= 0 ) { + var next = nextlist[ index ]; + if ( isNumber( next ) ) { + event.detail.next = steps[ next ]; + + // If the new next element has its own transitionDuration, we're responsible + // for setting that on the event as well + event.detail.transitionDuration = lib.util.toNumber( + event.detail.next.dataset.transitionDuration, + event.detail.transitionDuration + ); + return; + } else { + var newTarget = document.getElementById( next ); + if ( newTarget && newTarget.classList.contains( "step" ) ) { + event.detail.next = newTarget; + event.detail.transitionDuration = lib.util.toNumber( + event.detail.next.dataset.transitionDuration, + event.detail.transitionDuration + ); + return; + } else { + window.console.log( "impress goto plugin: " + next + + " is not a step in this impress presentation." ); + } + } + } + } + } + + // Data-goto-next="" & data-goto-prev="" /////////////////////////////////////////////////// + + // Handle event.target data-goto-next attribute + if ( isNumber( data.gotoNext ) && event.detail.reason === "next" ) { + event.detail.next = steps[ data.gotoNext ]; + + // If the new next element has its own transitionDuration, we're responsible for setting + // that on the event as well + event.detail.transitionDuration = lib.util.toNumber( + event.detail.next.dataset.transitionDuration, event.detail.transitionDuration + ); + return; + } + if ( data.gotoNext && event.detail.reason === "next" ) { + var newTarget = document.getElementById( data.gotoNext ); // jshint ignore:line + if ( newTarget && newTarget.classList.contains( "step" ) ) { + event.detail.next = newTarget; + event.detail.transitionDuration = lib.util.toNumber( + event.detail.next.dataset.transitionDuration, + event.detail.transitionDuration + ); + return; + } else { + window.console.log( "impress goto plugin: " + data.gotoNext + + " is not a step in this impress presentation." ); + } + } + + // Handle event.target data-goto-prev attribute + if ( isNumber( data.gotoPrev ) && event.detail.reason === "prev" ) { + event.detail.next = steps[ data.gotoPrev ]; + event.detail.transitionDuration = lib.util.toNumber( + event.detail.next.dataset.transitionDuration, event.detail.transitionDuration + ); + return; + } + if ( data.gotoPrev && event.detail.reason === "prev" ) { + var newTarget = document.getElementById( data.gotoPrev ); // jshint ignore:line + if ( newTarget && newTarget.classList.contains( "step" ) ) { + event.detail.next = newTarget; + event.detail.transitionDuration = lib.util.toNumber( + event.detail.next.dataset.transitionDuration, event.detail.transitionDuration + ); + return; + } else { + window.console.log( "impress goto plugin: " + data.gotoPrev + + " is not a step in this impress presentation." ); + } + } + + // Data-goto="" /////////////////////////////////////////////////////////////////////////// + + // Handle event.target data-goto attribute + if ( isNumber( data.goto ) ) { + event.detail.next = steps[ data.goto ]; + event.detail.transitionDuration = lib.util.toNumber( + event.detail.next.dataset.transitionDuration, event.detail.transitionDuration + ); + return; + } + if ( data.goto ) { + var newTarget = document.getElementById( data.goto ); // jshint ignore:line + if ( newTarget && newTarget.classList.contains( "step" ) ) { + event.detail.next = newTarget; + event.detail.transitionDuration = lib.util.toNumber( + event.detail.next.dataset.transitionDuration, event.detail.transitionDuration + ); + return; + } else { + window.console.log( "impress goto plugin: " + data.goto + + " is not a step in this impress presentation." ); + } + } + }; + + // Register the plugin to be called in pre-stepleave phase + impress.addPreStepLeavePlugin( goto ); + +} )( document, window ); + + +/** + * Help popup plugin + * + * Example: + * + * + *
+ * + * For developers: + * + * Typical use for this plugin, is for plugins that support some keypress, to add a line + * to the help popup produced by this plugin. For example "P: Presenter console". + * + * Copyright 2016 Henrik Ingo (@henrikingo) + * Released under the MIT license. + */ +/* global window, document */ + +( function( document, window ) { + "use strict"; + var rows = []; + var timeoutHandle; + + var triggerEvent = function( el, eventName, detail ) { + var event = document.createEvent( "CustomEvent" ); + event.initCustomEvent( eventName, true, true, detail ); + el.dispatchEvent( event ); + }; + + var renderHelpDiv = function() { + var helpDiv = document.getElementById( "impress-help" ); + if ( helpDiv ) { + var html = []; + for ( var row in rows ) { + for ( var arrayItem in row ) { + html.push( rows[ row ][ arrayItem ] ); + } + } + if ( html ) { + helpDiv.innerHTML = "\n" + html.join( "\n" ) + "
\n"; + } + } + }; + + var toggleHelp = function() { + var helpDiv = document.getElementById( "impress-help" ); + if ( !helpDiv ) { + return; + } + + if ( helpDiv.style.display === "block" ) { + helpDiv.style.display = "none"; + } else { + helpDiv.style.display = "block"; + window.clearTimeout( timeoutHandle ); + } + }; + + document.addEventListener( "keyup", function( event ) { + + // Check that event target is html or body element. + if ( event.target.nodeName === "BODY" || event.target.nodeName === "HTML" ) { + if ( event.keyCode === 72 ) { // "h" + event.preventDefault(); + toggleHelp(); + } + } + }, false ); + + // API + // Other plugins can add help texts, typically if they support an action on a keypress. + /** + * Add a help text to the help popup. + * + * :param: e.detail.command Example: "H" + * :param: e.detail.text Example: "Show this help." + * :param: e.detail.row Row index from 0 to 9 where to place this help text. Example: 0 + */ + document.addEventListener( "impress:help:add", function( e ) { + + // The idea is for the sender of the event to supply a unique row index, used for sorting. + // But just in case two plugins would ever use the same row index, we wrap each row into + // its own array. If there are more than one entry for the same index, they are shown in + // first come, first serve ordering. + var rowIndex = e.detail.row; + if ( typeof rows[ rowIndex ] !== "object" || !rows[ rowIndex ].isArray ) { + rows[ rowIndex ] = []; + } + rows[ e.detail.row ].push( "" + e.detail.command + "" + + e.detail.text + "" ); + renderHelpDiv(); + } ); + + document.addEventListener( "impress:init", function( e ) { + renderHelpDiv(); + + // At start, show the help for 7 seconds. + var helpDiv = document.getElementById( "impress-help" ); + if ( helpDiv ) { + helpDiv.style.display = "block"; + timeoutHandle = window.setTimeout( function() { + var helpDiv = document.getElementById( "impress-help" ); + helpDiv.style.display = "none"; + }, 7000 ); + + // Regster callback to empty the help div on teardown + var api = e.detail.api; + api.lib.gc.pushCallback( function() { + window.clearTimeout( timeoutHandle ); + helpDiv.style.display = ""; + helpDiv.innerHTML = ""; + rows = []; + } ); + } + + // Use our own API to register the help text for "h" + triggerEvent( document, "impress:help:add", + { command: "H", text: "Show this help", row: 0 } ); + } ); + +} )( document, window ); + + +/** + * Adds a presenter console to impress.js + * + * MIT Licensed, see license.txt. + * + * Copyright 2012, 2013, 2015 impress-console contributors (see README.txt) + * + * version: 1.3-dev + * + */ + +// This file contains so much HTML, that we will just respectfully disagree about js +/* jshint quotmark:single */ +/* global navigator, top, setInterval, clearInterval, document, window */ + +( function( document, window ) { + 'use strict'; + + // TODO: Move this to src/lib/util.js + var triggerEvent = function( el, eventName, detail ) { + var event = document.createEvent( 'CustomEvent' ); + event.initCustomEvent( eventName, true, true, detail ); + el.dispatchEvent( event ); + }; + + // Create Language object depending on browsers language setting + var lang; + switch ( navigator.language ) { + case 'de': + lang = { + 'noNotes': '
Keine Notizen hierzu
', + 'restart': 'Neustart', + 'clickToOpen': 'Klicken um Sprecherkonsole zu öffnen', + 'prev': 'zurück', + 'next': 'weiter', + 'loading': 'initalisiere', + 'ready': 'Bereit', + 'moving': 'in Bewegung', + 'useAMPM': false + }; + break; + case 'en': // jshint ignore:line + default : // jshint ignore:line + lang = { + 'noNotes': '
No notes for this step
', + 'restart': 'Restart', + 'clickToOpen': 'Click to open speaker console', + 'prev': 'Prev', + 'next': 'Next', + 'loading': 'Loading', + 'ready': 'Ready', + 'moving': 'Moving', + 'useAMPM': false + }; + break; + } + + // Settings to set iframe in speaker console + const preViewDefaultFactor = 0.7; + const preViewMinimumFactor = 0.5; + const preViewGap = 4; + + // This is the default template for the speaker console window + const consoleTemplate = '' + + '' + + + // Order is important: If user provides a cssFile, those will win, because they're later + '{{cssStyle}}' + + '{{cssLink}}' + + '' + + '
' + + '
' + + '' + + '' + + '
' + + '
' + + '
' + + '
' + + '
' + + '' + + '' + + '
--:--
' + + '
00m 00s
' + + '
{{loading}}
' + + '
' + + ''; + + // Default css location + var cssFileOldDefault = 'css/impressConsole.css'; + var cssFile = undefined; // jshint ignore:line + + // Css for styling iframs on the console + var cssFileIframeOldDefault = 'css/iframe.css'; + var cssFileIframe = undefined; // jshint ignore:line + + // All console windows, so that you can call impressConsole() repeatedly. + var allConsoles = {}; + + // Zero padding helper function: + var zeroPad = function( i ) { + return ( i < 10 ? '0' : '' ) + i; + }; + + // The console object + var impressConsole = window.impressConsole = function( rootId ) { + + rootId = rootId || 'impress'; + + if ( allConsoles[ rootId ] ) { + return allConsoles[ rootId ]; + } + + // Root presentation elements + var root = document.getElementById( rootId ); + + var consoleWindow = null; + + var nextStep = function() { + var classes = ''; + var nextElement = document.querySelector( '.active' ); + + // Return to parents as long as there is no next sibling + while ( !nextElement.nextElementSibling && nextElement.parentNode ) { + nextElement = nextElement.parentNode; + } + nextElement = nextElement.nextElementSibling; + while ( nextElement ) { + classes = nextElement.attributes[ 'class' ]; + if ( classes && classes.value.indexOf( 'step' ) !== -1 ) { + consoleWindow.document.getElementById( 'blocker' ).innerHTML = lang.next; + return nextElement; + } + + if ( nextElement.firstElementChild ) { // First go into deep + nextElement = nextElement.firstElementChild; + } else { + + // Go to next sibling or through parents until there is a next sibling + while ( !nextElement.nextElementSibling && nextElement.parentNode ) { + nextElement = nextElement.parentNode; + } + nextElement = nextElement.nextElementSibling; + } + } + + // No next element. Pick the first + consoleWindow.document.getElementById( 'blocker' ).innerHTML = lang.restart; + return document.querySelector( '.step' ); + }; + + // Sync the notes to the step + var onStepLeave = function() { + if ( consoleWindow ) { + + // Set notes to next steps notes. + var newNotes = document.querySelector( '.active' ).querySelector( '.notes' ); + if ( newNotes ) { + newNotes = newNotes.innerHTML; + } else { + newNotes = lang.noNotes; + } + consoleWindow.document.getElementById( 'notes' ).innerHTML = newNotes; + + // Set the views + var baseURL = document.URL.substring( 0, document.URL.search( '#/' ) ); + var slideSrc = baseURL + '#' + document.querySelector( '.active' ).id; + var preSrc = baseURL + '#' + nextStep().id; + var slideView = consoleWindow.document.getElementById( 'slideView' ); + + // Setting them when they are already set causes glithes in Firefox, so check first: + if ( slideView.src !== slideSrc ) { + slideView.src = slideSrc; + } + var preView = consoleWindow.document.getElementById( 'preView' ); + if ( preView.src !== preSrc ) { + preView.src = preSrc; + } + + consoleWindow.document.getElementById( 'status' ).innerHTML = + '' + lang.moving + ''; + } + }; + + // Sync the previews to the step + var onStepEnter = function() { + if ( consoleWindow ) { + + // We do everything here again, because if you stopped the previos step to + // early, the onstepleave trigger is not called for that step, so + // we need this to sync things. + var newNotes = document.querySelector( '.active' ).querySelector( '.notes' ); + if ( newNotes ) { + newNotes = newNotes.innerHTML; + } else { + newNotes = lang.noNotes; + } + var notes = consoleWindow.document.getElementById( 'notes' ); + notes.innerHTML = newNotes; + notes.scrollTop = 0; + + // Set the views + var baseURL = document.URL.substring( 0, document.URL.search( '#/' ) ); + var slideSrc = baseURL + '#' + document.querySelector( '.active' ).id; + var preSrc = baseURL + '#' + nextStep().id; + var slideView = consoleWindow.document.getElementById( 'slideView' ); + + // Setting them when they are already set causes glithes in Firefox, so check first: + if ( slideView.src !== slideSrc ) { + slideView.src = slideSrc; + } + var preView = consoleWindow.document.getElementById( 'preView' ); + if ( preView.src !== preSrc ) { + preView.src = preSrc; + } + + consoleWindow.document.getElementById( 'status' ).innerHTML = + '' + lang.ready + ''; + } + }; + + // Sync substeps + var onSubstep = function( event ) { + if ( consoleWindow ) { + if ( event.detail.reason === 'next' ) { + onSubstepShow(); + } + if ( event.detail.reason === 'prev' ) { + onSubstepHide(); + } + } + }; + + var onSubstepShow = function() { + var slideView = consoleWindow.document.getElementById( 'slideView' ); + triggerEventInView( slideView, 'impress:substep:show' ); + }; + + var onSubstepHide = function() { + var slideView = consoleWindow.document.getElementById( 'slideView' ); + triggerEventInView( slideView, 'impress:substep:hide' ); + }; + + var triggerEventInView = function( frame, eventName, detail ) { + + // Note: Unfortunately Chrome does not allow createEvent on file:// URLs, so this won't + // work. This does work on Firefox, and should work if viewing the presentation on a + // http:// URL on Chrome. + var event = frame.contentDocument.createEvent( 'CustomEvent' ); + event.initCustomEvent( eventName, true, true, detail ); + frame.contentDocument.dispatchEvent( event ); + }; + + var spaceHandler = function() { + var notes = consoleWindow.document.getElementById( 'notes' ); + if ( notes.scrollTopMax - notes.scrollTop > 20 ) { + notes.scrollTop = notes.scrollTop + notes.clientHeight * 0.8; + } else { + window.impress().next(); + } + }; + + var timerReset = function() { + consoleWindow.timerStart = new Date(); + }; + + // Show a clock + var clockTick = function() { + var now = new Date(); + var hours = now.getHours(); + var minutes = now.getMinutes(); + var seconds = now.getSeconds(); + var ampm = ''; + + if ( lang.useAMPM ) { + ampm = ( hours < 12 ) ? 'AM' : 'PM'; + hours = ( hours > 12 ) ? hours - 12 : hours; + hours = ( hours === 0 ) ? 12 : hours; + } + + // Clock + var clockStr = zeroPad( hours ) + ':' + zeroPad( minutes ) + ':' + zeroPad( seconds ) + + ' ' + ampm; + consoleWindow.document.getElementById( 'clock' ).firstChild.nodeValue = clockStr; + + // Timer + seconds = Math.floor( ( now - consoleWindow.timerStart ) / 1000 ); + minutes = Math.floor( seconds / 60 ); + seconds = Math.floor( seconds % 60 ); + consoleWindow.document.getElementById( 'timer' ).firstChild.nodeValue = + zeroPad( minutes ) + 'm ' + zeroPad( seconds ) + 's'; + + if ( !consoleWindow.initialized ) { + + // Nudge the slide windows after load, or they will scrolled wrong on Firefox. + consoleWindow.document.getElementById( 'slideView' ).contentWindow.scrollTo( 0, 0 ); + consoleWindow.document.getElementById( 'preView' ).contentWindow.scrollTo( 0, 0 ); + consoleWindow.initialized = true; + } + }; + + var registerKeyEvent = function( keyCodes, handler, window ) { + if ( window === undefined ) { + window = consoleWindow; + } + + // Prevent default keydown action when one of supported key is pressed + window.document.addEventListener( 'keydown', function( event ) { + if ( !event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey && + keyCodes.indexOf( event.keyCode ) !== -1 ) { + event.preventDefault(); + } + }, false ); + + // Trigger impress action on keyup + window.document.addEventListener( 'keyup', function( event ) { + if ( !event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey && + keyCodes.indexOf( event.keyCode ) !== -1 ) { + handler(); + event.preventDefault(); + } + }, false ); + }; + + var consoleOnLoad = function() { + var slideView = consoleWindow.document.getElementById( 'slideView' ); + var preView = consoleWindow.document.getElementById( 'preView' ); + + // Firefox: + slideView.contentDocument.body.classList.add( 'impress-console' ); + preView.contentDocument.body.classList.add( 'impress-console' ); + if ( cssFileIframe !== undefined ) { + slideView.contentDocument.head.insertAdjacentHTML( + 'beforeend', + '' + ); + preView.contentDocument.head.insertAdjacentHTML( + 'beforeend', + '' + ); + } + + // Chrome: + slideView.addEventListener( 'load', function() { + slideView.contentDocument.body.classList.add( 'impress-console' ); + if ( cssFileIframe !== undefined ) { + slideView.contentDocument.head.insertAdjacentHTML( + 'beforeend', + '' + ); + } + } ); + preView.addEventListener( 'load', function() { + preView.contentDocument.body.classList.add( 'impress-console' ); + if ( cssFileIframe !== undefined ) { + preView.contentDocument.head.insertAdjacentHTML( + 'beforeend', + '' ); + } + } ); + }; + + var open = function() { + if ( top.isconsoleWindow ) { + return; + } + + if ( consoleWindow && !consoleWindow.closed ) { + consoleWindow.focus(); + } else { + consoleWindow = window.open( '', 'impressConsole' ); + + // If opening failes this may be because the browser prevents this from + // not (or less) interactive JavaScript... + if ( consoleWindow == null ) { + + // ... so I add a button to klick. + // workaround on firefox + var message = document.createElement( 'div' ); + message.id = 'consoleWindowError'; + message.style.position = 'fixed'; + message.style.left = 0; + message.style.top = 0; + message.style.right = 0; + message.style.bottom = 0; + message.style.backgroundColor = 'rgba(255, 255, 255, 0.9)'; + var onClickStr = 'var x = document.getElementById(\'consoleWindowError\');' + + 'x.parentNode.removeChild(x);impressConsole().open();'; + message.innerHTML = ''; + document.body.appendChild( message ); + return; + } + + var cssLink = ''; + if ( cssFile !== undefined ) { + cssLink = ''; + } + + // This sets the window location to the main window location, so css can be loaded: + consoleWindow.document.open(); + + // Write the template: + consoleWindow.document.write( + + // CssStyleStr is lots of inline defined at the end of this file + consoleTemplate.replace( '{{cssStyle}}', cssStyleStr() ) + .replace( '{{cssLink}}', cssLink ) + .replace( /{{.*?}}/gi, function( x ) { + return lang[ x.substring( 2, x.length - 2 ) ]; } + ) + ); + consoleWindow.document.title = 'Speaker Console (' + document.title + ')'; + consoleWindow.impress = window.impress; + + // We set this flag so we can detect it later, to prevent infinite popups. + consoleWindow.isconsoleWindow = true; + + // Set the onload function: + consoleWindow.onload = consoleOnLoad; + + // Add clock tick + consoleWindow.timerStart = new Date(); + consoleWindow.timerReset = timerReset; + consoleWindow.clockInterval = setInterval( allConsoles[ rootId ].clockTick, 1000 ); + + // Keyboard navigation handlers + // 33: pg up, 37: left, 38: up + registerKeyEvent( [ 33, 37, 38 ], window.impress().prev ); + + // 34: pg down, 39: right, 40: down + registerKeyEvent( [ 34, 39, 40 ], window.impress().next ); + + // 32: space + registerKeyEvent( [ 32 ], spaceHandler ); + + // 82: R + registerKeyEvent( [ 82 ], timerReset ); + + // Cleanup + consoleWindow.onbeforeunload = function() { + + // I don't know why onunload doesn't work here. + clearInterval( consoleWindow.clockInterval ); + }; + + // It will need a little nudge on Firefox, but only after loading: + onStepEnter(); + consoleWindow.initialized = false; + consoleWindow.document.close(); + + //Catch any window resize to pass size on + window.onresize = resize; + consoleWindow.onresize = resize; + + return consoleWindow; + } + }; + + var resize = function() { + var slideView = consoleWindow.document.getElementById( 'slideView' ); + var preView = consoleWindow.document.getElementById( 'preView' ); + + // Get ratio of presentation + var ratio = window.innerHeight / window.innerWidth; + + // Get size available for views + var views = consoleWindow.document.getElementById( 'views' ); + + // SlideView may have a border or some padding: + // asuming same border width on both direktions + var delta = slideView.offsetWidth - slideView.clientWidth; + + // Set views + var slideViewWidth = ( views.clientWidth - delta ); + var slideViewHeight = Math.floor( slideViewWidth * ratio ); + + var preViewTop = slideViewHeight + preViewGap; + + var preViewWidth = Math.floor( slideViewWidth * preViewDefaultFactor ); + var preViewHeight = Math.floor( slideViewHeight * preViewDefaultFactor ); + + // Shrink preview to fit into space available + if ( views.clientHeight - delta < preViewTop + preViewHeight ) { + preViewHeight = views.clientHeight - delta - preViewTop; + preViewWidth = Math.floor( preViewHeight / ratio ); + } + + // If preview is not high enough forget ratios! + if ( preViewWidth <= Math.floor( slideViewWidth * preViewMinimumFactor ) ) { + slideViewWidth = ( views.clientWidth - delta ); + slideViewHeight = Math.floor( ( views.clientHeight - delta - preViewGap ) / + ( 1 + preViewMinimumFactor ) ); + + preViewTop = slideViewHeight + preViewGap; + + preViewWidth = Math.floor( slideViewWidth * preViewMinimumFactor ); + preViewHeight = views.clientHeight - delta - preViewTop; + } + + // Set the calculated into styles + slideView.style.width = slideViewWidth + 'px'; + slideView.style.height = slideViewHeight + 'px'; + + preView.style.top = preViewTop + 'px'; + + preView.style.width = preViewWidth + 'px'; + preView.style.height = preViewHeight + 'px'; + }; + + var _init = function( cssConsole, cssIframe ) { + if ( cssConsole !== undefined ) { + cssFile = cssConsole; + } + + // You can also specify the css in the presentation root div: + //
+ else if ( root.dataset.consoleCss !== undefined ) { + cssFile = root.dataset.consoleCss; + } + + if ( cssIframe !== undefined ) { + cssFileIframe = cssIframe; + } else if ( root.dataset.consoleCssIframe !== undefined ) { + cssFileIframe = root.dataset.consoleCssIframe; + } + + // Register the event + root.addEventListener( 'impress:stepleave', onStepLeave ); + root.addEventListener( 'impress:stepenter', onStepEnter ); + root.addEventListener( 'impress:substep:stepleaveaborted', onSubstep ); + root.addEventListener( 'impress:substep:show', onSubstepShow ); + root.addEventListener( 'impress:substep:hide', onSubstepHide ); + + //When the window closes, clean up after ourselves. + window.onunload = function() { + if ( consoleWindow && !consoleWindow.closed ) { + consoleWindow.close(); + } + }; + + //Open speaker console when they press 'p' + registerKeyEvent( [ 80 ], open, window ); + + //Btw, you can also launch console automatically: + //
+ if ( root.dataset.consoleAutolaunch === 'true' ) { + window.open(); + } + }; + + var init = function( cssConsole, cssIframe ) { + if ( ( cssConsole === undefined || cssConsole === cssFileOldDefault ) && + ( cssIframe === undefined || cssIframe === cssFileIframeOldDefault ) ) { + window.console.log( 'impressConsole.init() is deprecated. ' + + 'impressConsole is now initialized automatically when you ' + + 'call impress().init().' ); + } + _init( cssConsole, cssIframe ); + }; + + document.addEventListener( 'impress:init', function() { + _init(); + + // Add 'P' to the help popup + triggerEvent( document, 'impress:help:add', + { command: 'P', text: 'Presenter console', row: 10 } ); + } ); + + // New API for impress.js plugins is based on using events + root.addEventListener( 'impress:console:open', function() { + window.open(); + } ); + + /** + * Register a key code to an event handler + * + * :param: event.detail.keyCodes List of key codes + * :param: event.detail.handler A function registered as the event handler + * :param: event.detail.window The console window to register the keycode in + */ + root.addEventListener( 'impress:console:registerKeyEvent', function( event ) { + registerKeyEvent( event.detail.keyCodes, event.detail.handler, event.detail.window ); + } ); + + // Return the object + allConsoles[ rootId ] = { init: init, open: open, clockTick: clockTick, + registerKeyEvent: registerKeyEvent }; + return allConsoles[ rootId ]; + + }; + + // Returns a string to be used inline as a css `; + }; + + impressConsole(); + +} )( document, window ); + +/** + * Mobile devices support + * + * Allow presentation creators to hide all but 3 slides, to save resources, particularly on mobile + * devices, using classes body.impress-mobile, .step.prev, .step.active and .step.next. + * + * Note: This plugin does not take into account possible redirections done with skip, goto etc + * plugins. Basically it wouldn't work as intended in such cases, but the active step will at least + * be correct. + * + * Adapted to a plugin from a submission by @Kzeni: + * https://github.com/impress/impress.js/issues/333 + */ +/* global document, navigator */ +( function( document ) { + "use strict"; + + var getNextStep = function( el ) { + var steps = document.querySelectorAll( ".step" ); + for ( var i = 0; i < steps.length; i++ ) { + if ( steps[ i ] === el ) { + if ( i + 1 < steps.length ) { + return steps[ i + 1 ]; + } else { + return steps[ 0 ]; + } + } + } + }; + var getPrevStep = function( el ) { + var steps = document.querySelectorAll( ".step" ); + for ( var i = steps.length - 1; i >= 0; i-- ) { + if ( steps[ i ] === el ) { + if ( i - 1 >= 0 ) { + return steps[ i - 1 ]; + } else { + return steps[ steps.length - 1 ]; + } + } + } + }; + + // Detect mobile browsers & add CSS class as appropriate. + document.addEventListener( "impress:init", function( event ) { + var body = document.body; + if ( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( + navigator.userAgent + ) ) { + body.classList.add( "impress-mobile" ); + } + + // Unset all this on teardown + var api = event.detail.api; + api.lib.gc.pushCallback( function() { + document.body.classList.remove( "impress-mobile" ); + var prev = document.getElementsByClassName( "prev" )[ 0 ]; + var next = document.getElementsByClassName( "next" )[ 0 ]; + if ( typeof prev !== "undefined" ) { + prev.classList.remove( "prev" ); + } + if ( typeof next !== "undefined" ) { + next.classList.remove( "next" ); + } + } ); + } ); + + // Add prev and next classes to the siblings of the newly entered active step element + // Remove prev and next classes from their current step elements + // Note: As an exception we break namespacing rules, as these are useful general purpose + // classes. (Naming rules would require us to use css classes mobile-next and mobile-prev, + // based on plugin name.) + document.addEventListener( "impress:stepenter", function( event ) { + var oldprev = document.getElementsByClassName( "prev" )[ 0 ]; + var oldnext = document.getElementsByClassName( "next" )[ 0 ]; + + var prev = getPrevStep( event.target ); + prev.classList.add( "prev" ); + var next = getNextStep( event.target ); + next.classList.add( "next" ); + + if ( typeof oldprev !== "undefined" ) { + oldprev.classList.remove( "prev" ); + } + if ( typeof oldnext !== "undefined" ) { + oldnext.classList.remove( "next" ); + } + } ); +} )( document ); + + +/** + * Mouse timeout plugin + * + * After 3 seconds of mouse inactivity, add the css class + * `body.impress-mouse-timeout`. On `mousemove`, `click` or `touch`, remove the + * class. + * + * The use case for this plugin is to use CSS to hide elements from the screen + * and only make them visible when the mouse is moved. Examples where this + * might be used are: the toolbar from the toolbar plugin, and the mouse cursor + * itself. + * + * Example CSS: + * + * body.impress-mouse-timeout { + * cursor: none; + * } + * body.impress-mouse-timeout div#impress-toolbar { + * display: none; + * } + * + * + * Copyright 2016 Henrik Ingo (@henrikingo) + * Released under the MIT license. + */ +/* global window, document */ +( function( document, window ) { + "use strict"; + var timeout = 3; + var timeoutHandle; + + var hide = function() { + + // Mouse is now inactive + document.body.classList.add( "impress-mouse-timeout" ); + }; + + var show = function() { + if ( timeoutHandle ) { + window.clearTimeout( timeoutHandle ); + } + + // Mouse is now active + document.body.classList.remove( "impress-mouse-timeout" ); + + // Then set new timeout after which it is considered inactive again + timeoutHandle = window.setTimeout( hide, timeout * 1000 ); + }; + + document.addEventListener( "impress:init", function( event ) { + var api = event.detail.api; + var gc = api.lib.gc; + gc.addEventListener( document, "mousemove", show ); + gc.addEventListener( document, "click", show ); + gc.addEventListener( document, "touch", show ); + + // Set first timeout + show(); + + // Unset all this on teardown + gc.pushCallback( function() { + window.clearTimeout( timeoutHandle ); + document.body.classList.remove( "impress-mouse-timeout" ); + } ); + }, false ); + +} )( document, window ); + +/** + * Navigation events plugin + * + * As you can see this part is separate from the impress.js core code. + * It's because these navigation actions only need what impress.js provides with + * its simple API. + * + * This plugin is what we call an _init plugin_. It's a simple kind of + * impress.js plugin. When loaded, it starts listening to the `impress:init` + * event. That event listener initializes the plugin functionality - in this + * case we listen to some keypress and mouse events. The only dependencies on + * core impress.js functionality is the `impress:init` method, as well as using + * the public api `next(), prev(),` etc when keys are pressed. + * + * Copyright 2011-2012 Bartek Szopka (@bartaz) + * Released under the MIT license. + * ------------------------------------------------ + * author: Bartek Szopka + * version: 0.5.3 + * url: http://bartaz.github.com/impress.js/ + * source: http://github.com/bartaz/impress.js/ + * + */ +/* global document */ +( function( document ) { + "use strict"; + // Wait for impress.js to be initialized document.addEventListener( "impress:init", function( event ) { @@ -699,19 +2868,8 @@ // or anything. `impress:init` event data gives you everything you // need to control the presentation that was just initialized. var api = event.detail.api; - - // KEYBOARD NAVIGATION HANDLERS - - // Prevent default keydown action when one of supported key is pressed. - document.addEventListener( "keydown", function( event ) { - if ( event.keyCode === 9 || - ( event.keyCode >= 32 && event.keyCode <= 34 ) || - ( event.keyCode >= 37 && event.keyCode <= 40 ) ) { - event.preventDefault(); - } - }, false ); - - // Trigger impress action (next or prev) on keyup. + var gc = api.lib.gc; + var util = api.lib.util; // Supported keys are: // [space] - quite common in presentation software to move forward @@ -726,39 +2884,80 @@ // positioning. I didn't want to just prevent this default action, so I used [tab] // as another way to moving to next step... And yes, I know that for the sake of // consistency I should add [shift+tab] as opposite action... - document.addEventListener( "keyup", function( event ) { + var isNavigationEvent = function( event ) { - if ( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) { - return; + // Don't trigger navigation for example when user returns to browser window with ALT+TAB + if ( event.altKey || event.ctrlKey || event.metaKey ) { + return false; } - if ( event.keyCode === 9 || - ( event.keyCode >= 32 && event.keyCode <= 34 ) || - ( event.keyCode >= 37 && event.keyCode <= 40 ) ) { - switch ( event.keyCode ) { - case 33: // Page up - case 37: // Left - case 38: // Up - api.prev(); - break; - case 9: // Tab - case 32: // Space - case 34: // Page down - case 39: // Right - case 40: // Down - api.next(); - break; - } + // In the case of TAB, we force step navigation always, overriding the browser + // navigation between input elements, buttons and links. + if ( event.keyCode === 9 ) { + return true; + } + // With the sole exception of TAB, we also ignore keys pressed if shift is down. + if ( event.shiftKey ) { + return false; + } + + // For arrows, etc, check that event target is html or body element. This is to allow + // presentations to have, for example, forms with input elements where user can type + // text, including space, and not move to next step. + if ( event.target.nodeName !== "BODY" && event.target.nodeName !== "HTML" ) { + return false; + } + + if ( ( event.keyCode >= 32 && event.keyCode <= 34 ) || + ( event.keyCode >= 37 && event.keyCode <= 40 ) ) { + return true; + } + }; + + // KEYBOARD NAVIGATION HANDLERS + + // Prevent default keydown action when one of supported key is pressed. + gc.addEventListener( document, "keydown", function( event ) { + if ( isNavigationEvent( event ) ) { + event.preventDefault(); + } + }, false ); + + // Trigger impress action (next or prev) on keyup. + gc.addEventListener( document, "keyup", function( event ) { + if ( isNavigationEvent( event ) ) { + if ( event.shiftKey ) { + switch ( event.keyCode ) { + case 9: // Shift+tab + api.prev(); + break; + } + } else { + switch ( event.keyCode ) { + case 33: // Pg up + case 37: // Left + case 38: // Up + api.prev( event ); + break; + case 9: // Tab + case 32: // Space + case 34: // Pg down + case 39: // Right + case 40: // Down + api.next( event ); + break; + } + } event.preventDefault(); } }, false ); // Delegated handler for clicking on the links to presentation steps - document.addEventListener( "click", function( event ) { + gc.addEventListener( document, "click", function( event ) { // Event delegation with "bubbling" - // Check if event target (or any of its parents is a link) + // check if event target (or any of its parents is a link) var target = event.target; while ( ( target.tagName !== "A" ) && ( target !== document.documentElement ) ) { @@ -781,13 +2980,13 @@ }, false ); // Delegated handler for clicking on step elements - document.addEventListener( "click", function( event ) { + gc.addEventListener( document, "click", function( event ) { var target = event.target; // Find closest step element that is not active while ( !( target.classList.contains( "step" ) && - !target.classList.contains( "active" ) ) && - ( target !== document.documentElement ) ) { + !target.classList.contains( "active" ) ) && + ( target !== document.documentElement ) ) { target = target.parentNode; } @@ -796,41 +2995,864 @@ } }, false ); - // Touch handler to detect taps on the left and right side of the screen - // based on awesome work of @hakimel: https://github.com/hakimel/reveal.js - document.addEventListener( "touchstart", function( event ) { - if ( event.touches.length === 1 ) { - var x = event.touches[ 0 ].clientX, - width = window.innerWidth * 0.3, - result = null; + // Add a line to the help popup + util.triggerEvent( document, "impress:help:add", { command: "Left & Right", + text: "Previous & Next step", + row: 1 } ); - if ( x < width ) { - result = api.prev(); - } else if ( x > window.innerWidth - width ) { - result = api.next(); + }, false ); + +} )( document ); + + +/** + * Navigation UI plugin + * + * This plugin provides UI elements "back", "forward" and a list to select + * a specific slide number. + * + * The navigation controls are added to the toolbar plugin via DOM events. User must enable the + * toolbar in a presentation to have them visible. + * + * Copyright 2016 Henrik Ingo (@henrikingo) + * Released under the MIT license. + */ + +// This file contains so much HTML, that we will just respectfully disagree about js +/* jshint quotmark:single */ +/* global document */ + +( function( document ) { + 'use strict'; + var toolbar; + var api; + var root; + var steps; + var hideSteps = []; + var prev; + var select; + var next; + + var triggerEvent = function( el, eventName, detail ) { + var event = document.createEvent( 'CustomEvent' ); + event.initCustomEvent( eventName, true, true, detail ); + el.dispatchEvent( event ); + }; + + var makeDomElement = function( html ) { + var tempDiv = document.createElement( 'div' ); + tempDiv.innerHTML = html; + return tempDiv.firstChild; + }; + + var selectOptionsHtml = function() { + var options = ''; + for ( var i = 0; i < steps.length; i++ ) { + + // Omit steps that are listed as hidden from select widget + if ( hideSteps.indexOf( steps[ i ] ) < 0 ) { + options = options + '' + '\n'; // jshint ignore:line + } + } + return options; + }; + + var addNavigationControls = function( event ) { + api = event.detail.api; + var gc = api.lib.gc; + root = event.target; + steps = root.querySelectorAll( '.step' ); + + var prevHtml = ''; + var selectHtml = ''; + var nextHtml = ''; + + prev = makeDomElement( prevHtml ); + prev.addEventListener( 'click', + function() { + api.prev(); + } ); + select = makeDomElement( selectHtml ); + select.addEventListener( 'change', + function( event ) { + api.goto( event.target.value ); + } ); + gc.addEventListener( root, 'impress:steprefresh', function( event ) { + + // As impress.js core now allows to dynamically edit the steps, including adding, + // removing, and reordering steps, we need to requery and redraw the select list on + // every stepenter event. + steps = root.querySelectorAll( '.step' ); + select.innerHTML = '\n' + selectOptionsHtml(); + + // Make sure the list always shows the step we're actually on, even if it wasn't + // selected from the list + select.value = event.target.id; + } ); + next = makeDomElement( nextHtml ); + next.addEventListener( 'click', + function() { + api.next(); + } ); + + triggerEvent( toolbar, 'impress:toolbar:appendChild', { group: 0, element: prev } ); + triggerEvent( toolbar, 'impress:toolbar:appendChild', { group: 0, element: select } ); + triggerEvent( toolbar, 'impress:toolbar:appendChild', { group: 0, element: next } ); + + }; + + // API for not listing given step in the select widget. + // For example, if you set class="skip" on some element, you may not want it to show up in the + // list either. Otoh we cannot assume that, or anything else, so steps that user wants omitted + // must be specifically added with this API call. + document.addEventListener( 'impress:navigation-ui:hideStep', function( event ) { + hideSteps.push( event.target ); + if ( select ) { + select.innerHTML = selectOptionsHtml(); + } + }, false ); + + // Wait for impress.js to be initialized + document.addEventListener( 'impress:init', function( event ) { + toolbar = document.querySelector( '#impress-toolbar' ); + if ( toolbar ) { + addNavigationControls( event ); + } + }, false ); + +} )( document ); + + +/* global document */ +( function( document ) { + "use strict"; + var root; + var stepids = []; + + // Get stepids from the steps under impress root + var getSteps = function() { + stepids = []; + var steps = root.querySelectorAll( ".step" ); + for ( var i = 0; i < steps.length; i++ ) + { + stepids[ i + 1 ] = steps[ i ].id; + } + }; + + // Wait for impress.js to be initialized + document.addEventListener( "impress:init", function( event ) { + root = event.target; + getSteps(); + var gc = event.detail.api.lib.gc; + gc.pushCallback( function() { + stepids = []; + if ( progressbar ) { + progressbar.style.width = ""; + } + if ( progress ) { + progress.innerHTML = ""; + } + } ); + } ); + + var progressbar = document.querySelector( "div.impress-progressbar div" ); + var progress = document.querySelector( "div.impress-progress" ); + + if ( null !== progressbar || null !== progress ) { + document.addEventListener( "impress:stepleave", function( event ) { + updateProgressbar( event.detail.next.id ); + } ); + + document.addEventListener( "impress:steprefresh", function( event ) { + getSteps(); + updateProgressbar( event.target.id ); + } ); + + } + + function updateProgressbar( slideId ) { + var slideNumber = stepids.indexOf( slideId ); + if ( null !== progressbar ) { + var width = 100 / ( stepids.length - 1 ) * ( slideNumber ); + progressbar.style.width = width.toFixed( 2 ) + "%"; + } + if ( null !== progress ) { + progress.innerHTML = slideNumber + "/" + ( stepids.length - 1 ); + } + } +} )( document ); + +/** + * Relative Positioning Plugin + * + * This plugin provides support for defining the coordinates of a step relative + * to the previous step. This is often more convenient when creating presentations, + * since as you add, remove or move steps, you may not need to edit the positions + * as much as is the case with the absolute coordinates supported by impress.js + * core. + * + * Example: + * + * + *
+ * + * Following html attributes are supported for step elements: + * + * data-rel-x + * data-rel-y + * data-rel-z + * + * These values are also inherited from the previous step. This makes it easy to + * create a boring presentation where each slide shifts for example 1000px down + * from the previous. + * + * In addition to plain numbers, which are pixel values, it is also possible to + * define relative positions as a multiple of screen height and width, using + * a unit of "h" and "w", respectively, appended to the number. + * + * Example: + * + *
+ * + * This plugin is a *pre-init plugin*. It is called synchronously from impress.js + * core at the beginning of `impress().init()`. This allows it to process its own + * data attributes first, and possibly alter the data-x, data-y and data-z attributes + * that will then be processed by `impress().init()`. + * + * (Another name for this kind of plugin might be called a *filter plugin*, but + * *pre-init plugin* is more generic, as a plugin might do whatever it wants in + * the pre-init stage.) + * + * Copyright 2016 Henrik Ingo (@henrikingo) + * Released under the MIT license. + */ + +/* global document, window */ + +( function( document, window ) { + "use strict"; + + var startingState = {}; + + /** + * Copied from core impress.js. We currently lack a library mechanism to + * to share utility functions like this. + */ + var toNumber = function( numeric, fallback ) { + return isNaN( numeric ) ? ( fallback || 0 ) : Number( numeric ); + }; + + /** + * Extends toNumber() to correctly compute also relative-to-screen-size values 5w and 5h. + * + * Returns the computed value in pixels with w/h postfix removed. + */ + var toNumberAdvanced = function( numeric, fallback ) { + if ( typeof numeric !== "string" ) { + return toNumber( numeric, fallback ); + } + var ratio = numeric.match( /^([+-]*[\d\.]+)([wh])$/ ); + if ( ratio == null ) { + return toNumber( numeric, fallback ); + } else { + var value = parseFloat( ratio[ 1 ] ); + var multiplier = ratio[ 2 ] === "w" ? window.innerWidth : window.innerHeight; + return value * multiplier; + } + }; + + var computeRelativePositions = function( el, prev ) { + var data = el.dataset; + + if ( !prev ) { + + // For the first step, inherit these defaults + prev = { x:0, y:0, z:0, relative: { x:0, y:0, z:0 } }; + } + + var step = { + x: toNumber( data.x, prev.x ), + y: toNumber( data.y, prev.y ), + z: toNumber( data.z, prev.z ), + relative: { + x: toNumberAdvanced( data.relX, prev.relative.x ), + y: toNumberAdvanced( data.relY, prev.relative.y ), + z: toNumberAdvanced( data.relZ, prev.relative.z ) } + }; - if ( result ) { - event.preventDefault(); + // Relative position is ignored/zero if absolute is given. + // Note that this also has the effect of resetting any inherited relative values. + if ( data.x !== undefined ) { + step.relative.x = 0; + } + if ( data.y !== undefined ) { + step.relative.y = 0; + } + if ( data.z !== undefined ) { + step.relative.z = 0; + } + + // Apply relative position to absolute position, if non-zero + // Note that at this point, the relative values contain a number value of pixels. + step.x = step.x + step.relative.x; + step.y = step.y + step.relative.y; + step.z = step.z + step.relative.z; + + return step; + }; + + var rel = function( root ) { + var steps = root.querySelectorAll( ".step" ); + var prev; + startingState[ root.id ] = []; + for ( var i = 0; i < steps.length; i++ ) { + var el = steps[ i ]; + startingState[ root.id ].push( { + el: el, + x: el.getAttribute( "data-x" ), + y: el.getAttribute( "data-y" ), + z: el.getAttribute( "data-z" ) + } ); + var step = computeRelativePositions( el, prev ); + + // Apply relative position (if non-zero) + el.setAttribute( "data-x", step.x ); + el.setAttribute( "data-y", step.y ); + el.setAttribute( "data-z", step.z ); + prev = step; + } + }; + + // Register the plugin to be called in pre-init phase + window.impress.addPreInitPlugin( rel ); + + // Register teardown callback to reset the data.x, .y, .z values. + document.addEventListener( "impress:init", function( event ) { + var root = event.target; + event.detail.api.lib.gc.pushCallback( function() { + var steps = startingState[ root.id ]; + var step; + while ( step = steps.pop() ) { + if ( step.x === null ) { + step.el.removeAttribute( "data-x" ); + } else { + step.el.setAttribute( "data-x", step.x ); + } + if ( step.y === null ) { + step.el.removeAttribute( "data-y" ); + } else { + step.el.setAttribute( "data-y", step.y ); + } + if ( step.z === null ) { + step.el.removeAttribute( "data-z" ); + } else { + step.el.setAttribute( "data-z", step.z ); } } - }, false ); + delete startingState[ root.id ]; + } ); + }, false ); +} )( document, window ); + + +/** + * Resize plugin + * + * Rescale the presentation after a window resize. + * + * Copyright 2011-2012 Bartek Szopka (@bartaz) + * Released under the MIT license. + * ------------------------------------------------ + * author: Bartek Szopka + * version: 0.5.3 + * url: http://bartaz.github.com/impress.js/ + * source: http://github.com/bartaz/impress.js/ + * + */ + +/* global document, window */ + +( function( document, window ) { + "use strict"; + + // Wait for impress.js to be initialized + document.addEventListener( "impress:init", function( event ) { + var api = event.detail.api; // Rescale presentation when window is resized - window.addEventListener( "resize", throttle( function() { + api.lib.gc.addEventListener( window, "resize", api.lib.util.throttle( function() { // Force going to active step again, to trigger rescaling api.goto( document.querySelector( ".step.active" ), 500 ); }, 250 ), false ); - }, false ); } )( document, window ); -// THAT'S ALL FOLKS! -// -// Thanks for reading it all. -// Or thanks for scrolling down and reading the last part. -// -// I've learnt a lot when building impress.js and I hope this code and comments -// will help somebody learn at least some part of it. + +/** + * Skip Plugin + * + * Example: + * + * + *