From 2c61451d3e3a3107f8457365cbcf5459a73bad9e Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Mon, 25 Feb 2019 10:51:48 +0100 Subject: [PATCH 01/23] chore: maj reveal.js en version 3.7.0 ajout d'un watcher grunt. --- Gruntfile.js | 191 ++ css/print/paper.css | 7 +- css/print/pdf.css | 117 +- css/reveal.css | 954 +++++--- css/reveal.scss | 621 ++++- css/theme/README.md | 6 +- css/theme/beige.css | 140 +- css/theme/black.css | 126 +- css/theme/blood.css | 133 +- css/theme/league.css | 128 +- css/theme/moon.css | 128 +- css/theme/night.css | 126 +- css/theme/serif.css | 122 +- css/theme/simple.css | 127 +- css/theme/sky.css | 128 +- css/theme/solarized.css | 128 +- css/theme/source/black.scss | 4 +- css/theme/source/blood.scss | 1 - css/theme/source/night.scss | 1 - css/theme/source/simple.scss | 5 + css/theme/source/white.scss | 4 +- css/theme/template/settings.scss | 2 +- css/theme/template/theme.scss | 80 +- css/theme/white.css | 128 +- index.html | 38 +- js/reveal.js | 2073 ++++++++++++---- lib/css/zenburn.css | 119 +- lib/js/head.min.js | 14 +- package-lock.json | 3761 ++++++++++++++++++++++++++++++ package.json | 26 +- plugin/highlight/highlight.js | 55 +- plugin/markdown/example.html | 7 + plugin/markdown/example.md | 5 + plugin/markdown/markdown.js | 57 +- plugin/markdown/marked.js | 2 +- plugin/math/math.js | 7 +- plugin/multiplex/client.js | 2 +- plugin/multiplex/index.js | 40 +- plugin/multiplex/master.js | 69 +- plugin/multiplex/package.json | 19 + plugin/notes-server/client.js | 7 +- plugin/notes-server/index.js | 31 +- plugin/notes-server/notes.html | 241 +- plugin/notes/notes.html | 450 +++- plugin/notes/notes.js | 57 +- plugin/print-pdf/print-pdf.js | 75 +- plugin/search/search.js | 244 +- plugin/zoom-js/zoom.js | 40 +- 48 files changed, 8738 insertions(+), 2108 deletions(-) create mode 100644 Gruntfile.js create mode 100644 package-lock.json create mode 100644 plugin/multiplex/package.json diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..6f6ea28 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,191 @@ +/* global module:false */ +module.exports = function(grunt) { + var port = grunt.option("port") || 8000; + var root = grunt.option("root") || "."; + + if (!Array.isArray(root)) root = [root]; + + // Project configuration + grunt.initConfig({ + pkg: grunt.file.readJSON("package.json"), + meta: { + banner: + "/*!\n" + + ' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' + + " * http://revealjs.com\n" + + " * MIT licensed\n" + + " *\n" + + " * Copyright (C) 2018 Hakim El Hattab, http://hakim.se\n" + + " */" + }, + + qunit: { + files: ["test/*.html"] + }, + + uglify: { + options: { + banner: "<%= meta.banner %>\n", + ie8: true + }, + build: { + src: "js/reveal.js", + dest: "js/reveal.min.js" + } + }, + + sass: { + core: { + src: "css/reveal.scss", + dest: "css/reveal.css" + }, + themes: { + expand: true, + cwd: "css/theme/source", + src: ["*.sass", "*.scss"], + dest: "css/theme", + ext: ".css" + } + }, + + autoprefixer: { + core: { + src: "css/reveal.css" + } + }, + + cssmin: { + options: { + compatibility: "ie9" + }, + compress: { + src: "css/reveal.css", + dest: "css/reveal.min.css" + } + }, + + jshint: { + options: { + curly: false, + eqeqeq: true, + immed: true, + esnext: true, + latedef: "nofunc", + newcap: true, + noarg: true, + sub: true, + undef: true, + eqnull: true, + browser: true, + expr: true, + loopfunc: true, + globals: { + head: false, + module: false, + console: false, + unescape: false, + define: false, + exports: false + } + }, + files: ["Gruntfile.js", "js/reveal.js"] + }, + + connect: { + server: { + options: { + port: port, + base: root, + livereload: true, + open: true, + useAvailablePort: true + } + } + }, + + zip: { + bundle: { + src: [ + "index.html", + "css/**", + "js/**", + "lib/**", + "images/**", + "plugin/**", + "**.md" + ], + dest: "reveal-js-presentation.zip" + } + }, + + watch: { + js: { + files: ["Gruntfile.js", "js/reveal.js"], + tasks: "js" + }, + theme: { + files: [ + "css/theme/source/*.sass", + "css/theme/source/*.scss", + "css/theme/template/*.sass", + "css/theme/template/*.scss" + ], + tasks: "css-themes" + }, + css: { + files: ["css/reveal.scss"], + tasks: "css-core" + }, + html: { + files: root.map(path => path + "/*.html") + }, + markdown: { + files: root.map(path => path + "/*.md") + }, + options: { + livereload: true + } + }, + + retire: { + js: ["js/reveal.js", "lib/js/*.js", "plugin/**/*.js"], + node: ["."] + } + }); + + // Dependencies + grunt.loadNpmTasks("grunt-contrib-connect"); + grunt.loadNpmTasks("grunt-contrib-cssmin"); + grunt.loadNpmTasks("grunt-contrib-jshint"); + grunt.loadNpmTasks("grunt-contrib-qunit"); + grunt.loadNpmTasks("grunt-contrib-uglify"); + grunt.loadNpmTasks("grunt-contrib-watch"); + grunt.loadNpmTasks("grunt-autoprefixer"); + grunt.loadNpmTasks("grunt-retire"); + grunt.loadNpmTasks("grunt-sass"); + grunt.loadNpmTasks("grunt-zip"); + + // Default task + grunt.registerTask("default", ["css", "js"]); + + // JS task + grunt.registerTask("js", ["jshint", "uglify", "qunit"]); + + // Theme CSS + grunt.registerTask("css-themes", ["sass:themes"]); + + // Core framework CSS + grunt.registerTask("css-core", ["sass:core", "autoprefixer", "cssmin"]); + + // All CSS + grunt.registerTask("css", ["sass", "autoprefixer", "cssmin"]); + + // Package presentation to archive + grunt.registerTask("package", ["default", "zip"]); + + // Serve presentation locally + grunt.registerTask("serve", ["connect", "watch"]); + + // Run tests + grunt.registerTask("test", ["jshint", "qunit"]); +}; diff --git a/css/print/paper.css b/css/print/paper.css index 7c7257a..27d19dd 100644 --- a/css/print/paper.css +++ b/css/print/paper.css @@ -38,7 +38,8 @@ .share-reveal, .state-background, .reveal .progress, - .reveal .backgrounds { + .reveal .backgrounds, + .reveal .slide-number { display: none !important; } @@ -141,7 +142,7 @@ .reveal .slides section { visibility: visible !important; position: static !important; - width: 100% !important; + width: auto !important; height: auto !important; display: block !important; overflow: visible !important; @@ -199,4 +200,4 @@ font-size: 0.8em; } -} \ No newline at end of file +} diff --git a/css/print/pdf.css b/css/print/pdf.css index 2eb4cf2..752d955 100644 --- a/css/print/pdf.css +++ b/css/print/pdf.css @@ -1,15 +1,9 @@ -/* Default Print Stylesheet Template - by Rob Glazebrook of CSSnewbie.com - Last Updated: June 4, 2008 - - Feel free (nay, compelled) to edit, append, and - manipulate this file as you see fit. */ - - -/* SECTION 1: Set default width, margin, float, and - background. This prevents elements from extending - beyond the edge of the printed page, and prevents - unnecessary background images from printing */ +/** + * This stylesheet is used to print reveal.js + * presentations to PDF. + * + * https://github.com/hakimel/reveal.js#pdf-export + */ * { -webkit-print-color-adjust: exact; @@ -29,12 +23,10 @@ html { overflow: visible; } -/* SECTION 2: Remove any elements not needed in print. - This would include navigation, ads, sidebars, etc. */ +/* Remove any elements not needed in print. */ .nestedarrow, .reveal .controls, .reveal .progress, -.reveal .slide-number, .reveal .playback, .reveal.overview, .fork-reveal, @@ -43,16 +35,7 @@ html { display: none !important; } -/* SECTION 3: Set body font face, size, and color. - Consider using a serif font for readability. */ -body, p, td, li, div { - -} - -/* SECTION 4: Set heading font face, sizes, and color. - Differentiate your headings from your body text. - Perhaps use a large sans-serif for distinction. */ -h1,h2,h3,h4,h5,h6 { +h1, h2, h3, h4, h5, h6 { text-shadow: 0 0 0 #000 !important; } @@ -61,8 +44,6 @@ h1,h2,h3,h4,h5,h6 { font-family: Courier, 'Courier New', monospace !important; } - -/* SECTION 5: more reveal.js specific additions by @skypanther */ ul, ol, div, p { visibility: visible; position: static; @@ -79,8 +60,9 @@ ul, ol, div, p { } .reveal .slides { position: static; - width: 100%; - height: auto; + width: 100% !important; + height: auto !important; + zoom: 1 !important; left: auto; top: auto; @@ -90,23 +72,22 @@ ul, ol, div, p { overflow: visible; display: block; - -webkit-perspective: none; - -moz-perspective: none; - -ms-perspective: none; - perspective: none; + perspective: none; + perspective-origin: 50% 50%; +} - -webkit-perspective-origin: 50% 50%; /* there isn't a none/auto value but 50-50 is the default */ - -moz-perspective-origin: 50% 50%; - -ms-perspective-origin: 50% 50%; - perspective-origin: 50% 50%; +.reveal .slides .pdf-page { + position: relative; + overflow: hidden; + z-index: 1; + + page-break-after: always; } -.reveal .slides section { - page-break-after: always !important; +.reveal .slides section { visibility: visible !important; - position: relative !important; display: block !important; - position: relative !important; + position: absolute !important; margin: 0 !important; padding: 0 !important; @@ -115,43 +96,69 @@ ul, ol, div, p { opacity: 1 !important; - -webkit-transform-style: flat !important; - -moz-transform-style: flat !important; - -ms-transform-style: flat !important; - transform-style: flat !important; - - -webkit-transform: none !important; - -moz-transform: none !important; - -ms-transform: none !important; - transform: none !important; + transform-style: flat !important; + transform: none !important; } + .reveal section.stack { + position: relative !important; margin: 0 !important; padding: 0 !important; page-break-after: avoid !important; height: auto !important; min-height: auto !important; } + .reveal img { box-shadow: none; } + .reveal .roll { overflow: visible; line-height: 1em; } /* Slide backgrounds are placed inside of their slide when exporting to PDF */ -.reveal section .slide-background { +.reveal .slide-background { display: block !important; position: absolute; top: 0; left: 0; width: 100%; - z-index: -1; + height: 100%; + z-index: auto !important; } -/* All elements should be above the slide-background */ -.reveal section>* { + +/* Display slide speaker notes when 'showNotes' is enabled */ +.reveal.show-notes { + max-width: none; + max-height: none; +} +.reveal .speaker-notes-pdf { + display: block; + width: 100%; + height: auto; + max-height: none; + top: auto; + right: auto; + bottom: auto; + left: auto; + z-index: 100; +} + +/* Layout option which makes notes appear on a separate page */ +.reveal .speaker-notes-pdf[data-layout="separate-page"] { position: relative; - z-index: 1; + color: inherit; + background-color: transparent; + padding: 20px; + page-break-after: always; + border: 0; } +/* Display slide numbers when 'slideNumber' is enabled */ +.reveal .slide-number-pdf { + display: block; + position: absolute; + font-size: 14px; +} diff --git a/css/reveal.css b/css/reveal.css index 258e975..eda311e 100644 --- a/css/reveal.css +++ b/css/reveal.css @@ -1,14 +1,26 @@ /*! * reveal.js - * http://lab.hakim.se/reveal-js + * http://revealjs.com * MIT licensed * - * Copyright (C) 2015 Hakim El Hattab, http://hakim.se + * Copyright (C) 2018 Hakim El Hattab, http://hakim.se */ /********************************************* * RESET STYLES *********************************************/ -html, body, .reveal div, .reveal span, .reveal applet, .reveal object, .reveal iframe, .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .reveal p, .reveal blockquote, .reveal pre, .reveal a, .reveal abbr, .reveal acronym, .reveal address, .reveal big, .reveal cite, .reveal code, .reveal del, .reveal dfn, .reveal em, .reveal img, .reveal ins, .reveal kbd, .reveal q, .reveal s, .reveal samp, .reveal small, .reveal strike, .reveal strong, .reveal sub, .reveal sup, .reveal tt, .reveal var, .reveal b, .reveal u, .reveal center, .reveal dl, .reveal dt, .reveal dd, .reveal ol, .reveal ul, .reveal li, .reveal fieldset, .reveal form, .reveal label, .reveal legend, .reveal table, .reveal caption, .reveal tbody, .reveal tfoot, .reveal thead, .reveal tr, .reveal th, .reveal td, .reveal article, .reveal aside, .reveal canvas, .reveal details, .reveal embed, .reveal figure, .reveal figcaption, .reveal footer, .reveal header, .reveal hgroup, .reveal menu, .reveal nav, .reveal output, .reveal ruby, .reveal section, .reveal summary, .reveal time, .reveal mark, .reveal audio, video { +html, body, .reveal div, .reveal span, .reveal applet, .reveal object, .reveal iframe, +.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .reveal p, .reveal blockquote, .reveal pre, +.reveal a, .reveal abbr, .reveal acronym, .reveal address, .reveal big, .reveal cite, .reveal code, +.reveal del, .reveal dfn, .reveal em, .reveal img, .reveal ins, .reveal kbd, .reveal q, .reveal s, .reveal samp, +.reveal small, .reveal strike, .reveal strong, .reveal sub, .reveal sup, .reveal tt, .reveal var, +.reveal b, .reveal u, .reveal center, +.reveal dl, .reveal dt, .reveal dd, .reveal ol, .reveal ul, .reveal li, +.reveal fieldset, .reveal form, .reveal label, .reveal legend, +.reveal table, .reveal caption, .reveal tbody, .reveal tfoot, .reveal thead, .reveal tr, .reveal th, .reveal td, +.reveal article, .reveal aside, .reveal canvas, .reveal details, .reveal embed, +.reveal figure, .reveal figcaption, .reveal footer, .reveal header, .reveal hgroup, +.reveal menu, .reveal nav, .reveal output, .reveal ruby, .reveal section, .reveal summary, +.reveal time, .reveal mark, .reveal audio, .reveal video { margin: 0; padding: 0; border: 0; @@ -16,13 +28,15 @@ html, body, .reveal div, .reveal span, .reveal applet, .reveal object, .reveal i font: inherit; vertical-align: baseline; } -.reveal article, .reveal aside, .reveal details, .reveal figcaption, .reveal figure, .reveal footer, .reveal header, .reveal hgroup, .reveal menu, .reveal nav, .reveal section { +.reveal article, .reveal aside, .reveal details, .reveal figcaption, .reveal figure, +.reveal footer, .reveal header, .reveal hgroup, .reveal menu, .reveal nav, .reveal section { display: block; } /********************************************* * GLOBAL STYLES *********************************************/ -html, body { +html, +body { width: 100%; height: 100%; overflow: hidden; } @@ -39,66 +53,107 @@ body { .reveal .slides section .fragment { opacity: 0; visibility: hidden; - -webkit-transition: all 0.2s ease; - transition: all 0.2s ease; } + transition: all .2s ease; } .reveal .slides section .fragment.visible { opacity: 1; - visibility: visible; } + visibility: inherit; } .reveal .slides section .fragment.grow { opacity: 1; - visibility: visible; } + visibility: inherit; } .reveal .slides section .fragment.grow.visible { -webkit-transform: scale(1.3); - -ms-transform: scale(1.3); transform: scale(1.3); } .reveal .slides section .fragment.shrink { opacity: 1; - visibility: visible; } + visibility: inherit; } .reveal .slides section .fragment.shrink.visible { -webkit-transform: scale(0.7); - -ms-transform: scale(0.7); transform: scale(0.7); } .reveal .slides section .fragment.zoom-in { -webkit-transform: scale(0.1); - -ms-transform: scale(0.1); transform: scale(0.1); } .reveal .slides section .fragment.zoom-in.visible { -webkit-transform: none; - -ms-transform: none; transform: none; } .reveal .slides section .fragment.fade-out { opacity: 1; - visibility: visible; } + visibility: inherit; } .reveal .slides section .fragment.fade-out.visible { opacity: 0; visibility: hidden; } .reveal .slides section .fragment.semi-fade-out { opacity: 1; - visibility: visible; } + visibility: inherit; } .reveal .slides section .fragment.semi-fade-out.visible { opacity: 0.5; - visibility: visible; } + visibility: inherit; } .reveal .slides section .fragment.strike { - opacity: 1; } + opacity: 1; + visibility: inherit; } .reveal .slides section .fragment.strike.visible { text-decoration: line-through; } +.reveal .slides section .fragment.fade-up { + -webkit-transform: translate(0, 20%); + transform: translate(0, 20%); } + .reveal .slides section .fragment.fade-up.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-down { + -webkit-transform: translate(0, -20%); + transform: translate(0, -20%); } + .reveal .slides section .fragment.fade-down.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-right { + -webkit-transform: translate(-20%, 0); + transform: translate(-20%, 0); } + .reveal .slides section .fragment.fade-right.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-left { + -webkit-transform: translate(20%, 0); + transform: translate(20%, 0); } + .reveal .slides section .fragment.fade-left.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-in-then-out, .reveal .slides section .fragment.current-visible { opacity: 0; visibility: hidden; } + .reveal .slides section .fragment.fade-in-then-out.current-fragment, .reveal .slides section .fragment.current-visible.current-fragment { opacity: 1; - visibility: visible; } + visibility: inherit; } -.reveal .slides section .fragment.highlight-red, .reveal .slides section .fragment.highlight-current-red, .reveal .slides section .fragment.highlight-green, .reveal .slides section .fragment.highlight-current-green, .reveal .slides section .fragment.highlight-blue, .reveal .slides section .fragment.highlight-current-blue { +.reveal .slides section .fragment.fade-in-then-semi-out { + opacity: 0; + visibility: hidden; } + .reveal .slides section .fragment.fade-in-then-semi-out.visible { + opacity: 0.5; + visibility: inherit; } + .reveal .slides section .fragment.fade-in-then-semi-out.current-fragment { + opacity: 1; + visibility: inherit; } + +.reveal .slides section .fragment.highlight-red, +.reveal .slides section .fragment.highlight-current-red, +.reveal .slides section .fragment.highlight-green, +.reveal .slides section .fragment.highlight-current-green, +.reveal .slides section .fragment.highlight-blue, +.reveal .slides section .fragment.highlight-current-blue { opacity: 1; - visibility: visible; } + visibility: inherit; } .reveal .slides section .fragment.highlight-red.visible { color: #ff2c2d; } @@ -140,116 +195,288 @@ body { .reveal pre.stretch code { height: 100%; max-height: 100%; - -moz-box-sizing: border-box; - box-sizing: border-box; } + box-sizing: border-box; } /********************************************* * CONTROLS *********************************************/ +@-webkit-keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } + +@-webkit-keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + .reveal .controls { display: none; - position: fixed; - width: 110px; - height: 110px; - z-index: 30; - right: 10px; - bottom: 10px; - -webkit-user-select: none; } - -.reveal .controls div { position: absolute; - opacity: 0.05; - width: 0; - height: 0; - border: 12px solid transparent; - -webkit-transform: scale(0.9999); - -ms-transform: scale(0.9999); - transform: scale(0.9999); - -webkit-transition: all 0.2s ease; - transition: all 0.2s ease; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } - -.reveal .controls div.enabled { - opacity: 0.7; - cursor: pointer; } - -.reveal .controls div.enabled:active { - margin-top: 1px; } - -.reveal .controls div.navigate-left { - top: 42px; - border-right-width: 22px; - border-right-color: #000; } + top: auto; + bottom: 12px; + right: 12px; + left: auto; + z-index: 1; + color: #000; + pointer-events: none; + font-size: 10px; } + .reveal .controls button { + position: absolute; + padding: 0; + background-color: transparent; + border: 0; + outline: 0; + cursor: pointer; + color: currentColor; + -webkit-transform: scale(0.9999); + transform: scale(0.9999); + transition: color 0.2s ease, opacity 0.2s ease, -webkit-transform 0.2s ease; + transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease; + z-index: 2; + pointer-events: auto; + font-size: inherit; + visibility: hidden; + opacity: 0; + -webkit-appearance: none; + -webkit-tap-highlight-color: transparent; } + .reveal .controls .controls-arrow:before, + .reveal .controls .controls-arrow:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 2.6em; + height: 0.5em; + border-radius: 0.25em; + background-color: currentColor; + transition: all 0.15s ease, background-color 0.8s ease; + -webkit-transform-origin: 0.2em 50%; + transform-origin: 0.2em 50%; + will-change: transform; } + .reveal .controls .controls-arrow { + position: relative; + width: 3.6em; + height: 3.6em; } + .reveal .controls .controls-arrow:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } + .reveal .controls .controls-arrow:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } + .reveal .controls .controls-arrow:hover:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(40deg); + transform: translateX(0.5em) translateY(1.55em) rotate(40deg); } + .reveal .controls .controls-arrow:hover:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); } + .reveal .controls .controls-arrow:active:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(36deg); + transform: translateX(0.5em) translateY(1.55em) rotate(36deg); } + .reveal .controls .controls-arrow:active:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); } + .reveal .controls .navigate-left { + right: 6.4em; + bottom: 3.2em; + -webkit-transform: translateX(-10px); + transform: translateX(-10px); } + .reveal .controls .navigate-right { + right: 0; + bottom: 3.2em; + -webkit-transform: translateX(10px); + transform: translateX(10px); } + .reveal .controls .navigate-right .controls-arrow { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + .reveal .controls .navigate-right.highlight { + -webkit-animation: bounce-right 2s 50 both ease-out; + animation: bounce-right 2s 50 both ease-out; } + .reveal .controls .navigate-up { + right: 3.2em; + bottom: 6.4em; + -webkit-transform: translateY(-10px); + transform: translateY(-10px); } + .reveal .controls .navigate-up .controls-arrow { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + .reveal .controls .navigate-down { + right: 3.2em; + bottom: 0; + -webkit-transform: translateY(10px); + transform: translateY(10px); } + .reveal .controls .navigate-down .controls-arrow { + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); } + .reveal .controls .navigate-down.highlight { + -webkit-animation: bounce-down 2s 50 both ease-out; + animation: bounce-down 2s 50 both ease-out; } + .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled, + .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled { + opacity: 0.3; } + .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled:hover, + .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled:hover { + opacity: 1; } + .reveal .controls[data-controls-back-arrows="hidden"] .navigate-left.enabled, + .reveal .controls[data-controls-back-arrows="hidden"] .navigate-up.enabled { + opacity: 0; + visibility: hidden; } + .reveal .controls .enabled { + visibility: visible; + opacity: 0.9; + cursor: pointer; + -webkit-transform: none; + transform: none; } + .reveal .controls .enabled.fragmented { + opacity: 0.5; } + .reveal .controls .enabled:hover, + .reveal .controls .enabled.fragmented:hover { + opacity: 1; } -.reveal .controls div.navigate-left.fragmented { - opacity: 0.3; } +.reveal:not(.has-vertical-slides) .controls .navigate-left { + bottom: 1.4em; + right: 5.5em; } -.reveal .controls div.navigate-right { - left: 74px; - top: 42px; - border-left-width: 22px; - border-left-color: #000; } +.reveal:not(.has-vertical-slides) .controls .navigate-right { + bottom: 1.4em; + right: 0.5em; } -.reveal .controls div.navigate-right.fragmented { - opacity: 0.3; } +.reveal:not(.has-horizontal-slides) .controls .navigate-up { + right: 1.4em; + bottom: 5em; } -.reveal .controls div.navigate-up { - left: 42px; - border-bottom-width: 22px; - border-bottom-color: #000; } +.reveal:not(.has-horizontal-slides) .controls .navigate-down { + right: 1.4em; + bottom: 0.5em; } -.reveal .controls div.navigate-up.fragmented { - opacity: 0.3; } +.reveal.has-dark-background .controls { + color: #fff; } -.reveal .controls div.navigate-down { - left: 42px; - top: 74px; - border-top-width: 22px; - border-top-color: #000; } +.reveal.has-light-background .controls { + color: #000; } -.reveal .controls div.navigate-down.fragmented { - opacity: 0.3; } +.reveal.no-hover .controls .controls-arrow:hover:before, +.reveal.no-hover .controls .controls-arrow:active:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } + +.reveal.no-hover .controls .controls-arrow:hover:after, +.reveal.no-hover .controls .controls-arrow:active:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } + +@media screen and (min-width: 500px) { + .reveal .controls[data-controls-layout="edges"] { + top: 0; + right: 0; + bottom: 0; + left: 0; } + .reveal .controls[data-controls-layout="edges"] .navigate-left, + .reveal .controls[data-controls-layout="edges"] .navigate-right, + .reveal .controls[data-controls-layout="edges"] .navigate-up, + .reveal .controls[data-controls-layout="edges"] .navigate-down { + bottom: auto; + right: auto; } + .reveal .controls[data-controls-layout="edges"] .navigate-left { + top: 50%; + left: 8px; + margin-top: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-right { + top: 50%; + right: 8px; + margin-top: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-up { + top: 8px; + left: 50%; + margin-left: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-down { + bottom: 8px; + left: 50%; + margin-left: -1.8em; } } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - position: fixed; + position: absolute; display: none; height: 3px; width: 100%; bottom: 0; left: 0; z-index: 10; - background-color: rgba(0, 0, 0, 0.2); } + background-color: rgba(0, 0, 0, 0.2); + color: #fff; } .reveal .progress:after { content: ''; display: block; position: absolute; - height: 20px; + height: 10px; width: 100%; - top: -20px; } + top: -10px; } .reveal .progress span { display: block; height: 100%; width: 0px; - background-color: #000; - -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); - transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + background-color: currentColor; + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* * SLIDE NUMBER *********************************************/ .reveal .slide-number { - position: fixed; + position: absolute; display: block; - right: 15px; - bottom: 15px; - opacity: 0.5; + right: 8px; + bottom: 8px; z-index: 31; - font-size: 12px; } + font-family: Helvetica, sans-serif; + font-size: 12px; + line-height: 1; + color: #fff; + background-color: rgba(0, 0, 0, 0.4); + padding: 5px; } + +.reveal .slide-number a { + color: currentColor; } + +.reveal .slide-number-delimiter { + margin: 0 3px; } /********************************************* * SLIDES @@ -262,6 +489,10 @@ body { -ms-touch-action: none; touch-action: none; } +@media only screen and (orientation: landscape) { + .reveal.ua-iphone { + position: fixed; } } + .reveal .slides { position: absolute; width: 100%; @@ -271,6 +502,7 @@ body { bottom: 0; left: 0; margin: auto; + pointer-events: none; overflow: visible; z-index: 1; text-align: center; @@ -282,56 +514,70 @@ body { .reveal .slides > section { -ms-perspective: 600px; } -.reveal .slides > section, .reveal .slides > section > section { +.reveal .slides > section, +.reveal .slides > section > section { display: none; position: absolute; width: 100%; padding: 20px 0px; + pointer-events: auto; z-index: 10; - -webkit-transform-style: preserve-3d; - transform-style: preserve-3d; - -webkit-transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); - transition: -ms-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); - transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + -webkit-transform-style: flat; + transform-style: flat; + transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /* Global transition speed settings */ .reveal[data-transition-speed="fast"] .slides section { - -webkit-transition-duration: 400ms; - transition-duration: 400ms; } + transition-duration: 400ms; } .reveal[data-transition-speed="slow"] .slides section { - -webkit-transition-duration: 1200ms; - transition-duration: 1200ms; } + transition-duration: 1200ms; } /* Slide-specific transition speed overrides */ .reveal .slides section[data-transition-speed="fast"] { - -webkit-transition-duration: 400ms; - transition-duration: 400ms; } + transition-duration: 400ms; } .reveal .slides section[data-transition-speed="slow"] { - -webkit-transition-duration: 1200ms; - transition-duration: 1200ms; } + transition-duration: 1200ms; } .reveal .slides > section.stack { padding-top: 0; - padding-bottom: 0; } + padding-bottom: 0; + pointer-events: none; } -.reveal .slides > section.present, .reveal .slides > section > section.present { +.reveal .slides > section.present, +.reveal .slides > section > section.present { display: block; z-index: 11; opacity: 1; } -.reveal.center, .reveal.center .slides, .reveal.center .slides section { +.reveal .slides > section:empty, +.reveal .slides > section > section:empty, +.reveal .slides > section[data-background-interactive], +.reveal .slides > section > section[data-background-interactive] { + pointer-events: none; } + +.reveal.center, +.reveal.center .slides, +.reveal.center .slides section { min-height: 0 !important; } /* Don't allow interaction with invisible slides */ -.reveal .slides > section.future, .reveal .slides > section > section.future, .reveal .slides > section.past, .reveal .slides > section > section.past { +.reveal .slides > section.future, +.reveal .slides > section > section.future, +.reveal .slides > section.past, +.reveal .slides > section > section.past { pointer-events: none; } -.reveal.overview .slides > section, .reveal.overview .slides > section > section { +.reveal.overview .slides > section, +.reveal.overview .slides > section > section { pointer-events: auto; } -.reveal .slides > section.past, .reveal .slides > section.future, .reveal .slides > section > section.past, .reveal .slides > section > section.future { +.reveal .slides > section.past, +.reveal .slides > section.future, +.reveal .slides > section > section.past, +.reveal .slides > section > section.future { opacity: 0; } /********************************************* @@ -345,136 +591,191 @@ body { -webkit-backface-visibility: hidden; backface-visibility: hidden; } -.reveal .slides > section[data-transition=slide].past, .reveal .slides > section[data-transition~=slide-out].past, .reveal.slide .slides > section:not([data-transition]).past { +.reveal .slides > section[data-transition=slide].past, +.reveal .slides > section[data-transition~=slide-out].past, +.reveal.slide .slides > section:not([data-transition]).past { -webkit-transform: translate(-150%, 0); - -ms-transform: translate(-150%, 0); transform: translate(-150%, 0); } -.reveal .slides > section[data-transition=slide].future, .reveal .slides > section[data-transition~=slide-in].future, .reveal.slide .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=slide].future, +.reveal .slides > section[data-transition~=slide-in].future, +.reveal.slide .slides > section:not([data-transition]).future { -webkit-transform: translate(150%, 0); - -ms-transform: translate(150%, 0); transform: translate(150%, 0); } -.reveal .slides > section > section[data-transition=slide].past, .reveal .slides > section > section[data-transition~=slide-out].past, .reveal.slide .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=slide].past, +.reveal .slides > section > section[data-transition~=slide-out].past, +.reveal.slide .slides > section > section:not([data-transition]).past { -webkit-transform: translate(0, -150%); - -ms-transform: translate(0, -150%); transform: translate(0, -150%); } -.reveal .slides > section > section[data-transition=slide].future, .reveal .slides > section > section[data-transition~=slide-in].future, .reveal.slide .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=slide].future, +.reveal .slides > section > section[data-transition~=slide-in].future, +.reveal.slide .slides > section > section:not([data-transition]).future { -webkit-transform: translate(0, 150%); - -ms-transform: translate(0, 150%); transform: translate(0, 150%); } .reveal.linear section { -webkit-backface-visibility: hidden; backface-visibility: hidden; } -.reveal .slides > section[data-transition=linear].past, .reveal .slides > section[data-transition~=linear-out].past, .reveal.linear .slides > section:not([data-transition]).past { +.reveal .slides > section[data-transition=linear].past, +.reveal .slides > section[data-transition~=linear-out].past, +.reveal.linear .slides > section:not([data-transition]).past { -webkit-transform: translate(-150%, 0); - -ms-transform: translate(-150%, 0); transform: translate(-150%, 0); } -.reveal .slides > section[data-transition=linear].future, .reveal .slides > section[data-transition~=linear-in].future, .reveal.linear .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=linear].future, +.reveal .slides > section[data-transition~=linear-in].future, +.reveal.linear .slides > section:not([data-transition]).future { -webkit-transform: translate(150%, 0); - -ms-transform: translate(150%, 0); transform: translate(150%, 0); } -.reveal .slides > section > section[data-transition=linear].past, .reveal .slides > section > section[data-transition~=linear-out].past, .reveal.linear .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=linear].past, +.reveal .slides > section > section[data-transition~=linear-out].past, +.reveal.linear .slides > section > section:not([data-transition]).past { -webkit-transform: translate(0, -150%); - -ms-transform: translate(0, -150%); transform: translate(0, -150%); } -.reveal .slides > section > section[data-transition=linear].future, .reveal .slides > section > section[data-transition~=linear-in].future, .reveal.linear .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=linear].future, +.reveal .slides > section > section[data-transition~=linear-in].future, +.reveal.linear .slides > section > section:not([data-transition]).future { -webkit-transform: translate(0, 150%); - -ms-transform: translate(0, 150%); transform: translate(0, 150%); } /********************************************* * CONVEX TRANSITION * Aliased 'default' for backwards compatibility *********************************************/ -.reveal .slides > section[data-transition=default].past, .reveal .slides > section[data-transition~=default-out].past, .reveal.default .slides > section:not([data-transition]).past { +.reveal .slides section[data-transition=default].stack, +.reveal.default .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=default].past, +.reveal .slides > section[data-transition~=default-out].past, +.reveal.default .slides > section:not([data-transition]).past { -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } -.reveal .slides > section[data-transition=default].future, .reveal .slides > section[data-transition~=default-in].future, .reveal.default .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=default].future, +.reveal .slides > section[data-transition~=default-in].future, +.reveal.default .slides > section:not([data-transition]).future { -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } -.reveal .slides > section > section[data-transition=default].past, .reveal .slides > section > section[data-transition~=default-out].past, .reveal.default .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=default].past, +.reveal .slides > section > section[data-transition~=default-out].past, +.reveal.default .slides > section > section:not([data-transition]).past { -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } -.reveal .slides > section > section[data-transition=default].future, .reveal .slides > section > section[data-transition~=default-in].future, .reveal.default .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=default].future, +.reveal .slides > section > section[data-transition~=default-in].future, +.reveal.default .slides > section > section:not([data-transition]).future { -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } -.reveal .slides > section[data-transition=convex].past, .reveal .slides > section[data-transition~=convex-out].past, .reveal.convex .slides > section:not([data-transition]).past { +.reveal .slides section[data-transition=convex].stack, +.reveal.convex .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=convex].past, +.reveal .slides > section[data-transition~=convex-out].past, +.reveal.convex .slides > section:not([data-transition]).past { -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } -.reveal .slides > section[data-transition=convex].future, .reveal .slides > section[data-transition~=convex-in].future, .reveal.convex .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=convex].future, +.reveal .slides > section[data-transition~=convex-in].future, +.reveal.convex .slides > section:not([data-transition]).future { -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } -.reveal .slides > section > section[data-transition=convex].past, .reveal .slides > section > section[data-transition~=convex-out].past, .reveal.convex .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=convex].past, +.reveal .slides > section > section[data-transition~=convex-out].past, +.reveal.convex .slides > section > section:not([data-transition]).past { -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } -.reveal .slides > section > section[data-transition=convex].future, .reveal .slides > section > section[data-transition~=convex-in].future, .reveal.convex .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=convex].future, +.reveal .slides > section > section[data-transition~=convex-in].future, +.reveal.convex .slides > section > section:not([data-transition]).future { -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } /********************************************* * CONCAVE TRANSITION *********************************************/ -.reveal .slides > section[data-transition=concave].past, .reveal .slides > section[data-transition~=concave-out].past, .reveal.concave .slides > section:not([data-transition]).past { +.reveal .slides section[data-transition=concave].stack, +.reveal.concave .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=concave].past, +.reveal .slides > section[data-transition~=concave-out].past, +.reveal.concave .slides > section:not([data-transition]).past { -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } -.reveal .slides > section[data-transition=concave].future, .reveal .slides > section[data-transition~=concave-in].future, .reveal.concave .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=concave].future, +.reveal .slides > section[data-transition~=concave-in].future, +.reveal.concave .slides > section:not([data-transition]).future { -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } -.reveal .slides > section > section[data-transition=concave].past, .reveal .slides > section > section[data-transition~=concave-out].past, .reveal.concave .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=concave].past, +.reveal .slides > section > section[data-transition~=concave-out].past, +.reveal.concave .slides > section > section:not([data-transition]).past { -webkit-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); } -.reveal .slides > section > section[data-transition=concave].future, .reveal .slides > section > section[data-transition~=concave-in].future, .reveal.concave .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=concave].future, +.reveal .slides > section > section[data-transition~=concave-in].future, +.reveal.concave .slides > section > section:not([data-transition]).future { -webkit-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); } /********************************************* * ZOOM TRANSITION *********************************************/ -.reveal .slides > section[data-transition=zoom], .reveal.zoom .slides > section:not([data-transition]) { - -webkit-transition-timing-function: ease; - transition-timing-function: ease; } +.reveal .slides section[data-transition=zoom], +.reveal.zoom .slides section:not([data-transition]) { + transition-timing-function: ease; } -.reveal .slides > section[data-transition=zoom].past, .reveal .slides > section[data-transition~=zoom-out].past, .reveal.zoom .slides > section:not([data-transition]).past { +.reveal .slides > section[data-transition=zoom].past, +.reveal .slides > section[data-transition~=zoom-out].past, +.reveal.zoom .slides > section:not([data-transition]).past { visibility: hidden; -webkit-transform: scale(16); - -ms-transform: scale(16); transform: scale(16); } -.reveal .slides > section[data-transition=zoom].future, .reveal .slides > section[data-transition~=zoom-in].future, .reveal.zoom .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=zoom].future, +.reveal .slides > section[data-transition~=zoom-in].future, +.reveal.zoom .slides > section:not([data-transition]).future { visibility: hidden; -webkit-transform: scale(0.2); - -ms-transform: scale(0.2); transform: scale(0.2); } -.reveal .slides > section > section[data-transition=zoom].past, .reveal .slides > section > section[data-transition~=zoom-out].past, .reveal.zoom .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=zoom].past, +.reveal .slides > section > section[data-transition~=zoom-out].past, +.reveal.zoom .slides > section > section:not([data-transition]).past { -webkit-transform: translate(0, -150%); - -ms-transform: translate(0, -150%); transform: translate(0, -150%); } -.reveal .slides > section > section[data-transition=zoom].future, .reveal .slides > section > section[data-transition~=zoom-in].future, .reveal.zoom .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=zoom].future, +.reveal .slides > section > section[data-transition~=zoom-in].future, +.reveal.zoom .slides > section > section:not([data-transition]).future { -webkit-transform: translate(0, 150%); - -ms-transform: translate(0, 150%); transform: translate(0, 150%); } /********************************************* * CUBE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. *********************************************/ .reveal.cube .slides { -webkit-perspective: 1300px; @@ -485,8 +786,9 @@ body { min-height: 700px; -webkit-backface-visibility: hidden; backface-visibility: hidden; - -moz-box-sizing: border-box; - box-sizing: border-box; } + box-sizing: border-box; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } .reveal.center.cube .slides section { min-height: 0; } @@ -525,34 +827,34 @@ body { .reveal.cube .slides > section.past { -webkit-transform-origin: 100% 0%; - -ms-transform-origin: 100% 0%; transform-origin: 100% 0%; -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg); transform: translate3d(-100%, 0, 0) rotateY(-90deg); } .reveal.cube .slides > section.future { -webkit-transform-origin: 0% 0%; - -ms-transform-origin: 0% 0%; transform-origin: 0% 0%; -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg); transform: translate3d(100%, 0, 0) rotateY(90deg); } .reveal.cube .slides > section > section.past { -webkit-transform-origin: 0% 100%; - -ms-transform-origin: 0% 100%; transform-origin: 0% 100%; -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg); transform: translate3d(0, -100%, 0) rotateX(90deg); } .reveal.cube .slides > section > section.future { -webkit-transform-origin: 0% 0%; - -ms-transform-origin: 0% 0%; transform-origin: 0% 0%; -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg); transform: translate3d(0, 100%, 0) rotateX(-90deg); } /********************************************* * PAGE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. *********************************************/ .reveal.page .slides { -webkit-perspective-origin: 0% 50%; @@ -563,8 +865,9 @@ body { .reveal.page .slides section { padding: 30px; min-height: 700px; - -moz-box-sizing: border-box; - box-sizing: border-box; } + box-sizing: border-box; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } .reveal.page .slides section.past { z-index: 12; } @@ -601,28 +904,24 @@ body { .reveal.page .slides > section.past { -webkit-transform-origin: 0% 0%; - -ms-transform-origin: 0% 0%; transform-origin: 0% 0%; -webkit-transform: translate3d(-40%, 0, 0) rotateY(-80deg); transform: translate3d(-40%, 0, 0) rotateY(-80deg); } .reveal.page .slides > section.future { -webkit-transform-origin: 100% 0%; - -ms-transform-origin: 100% 0%; transform-origin: 100% 0%; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } .reveal.page .slides > section > section.past { -webkit-transform-origin: 0% 0%; - -ms-transform-origin: 0% 0%; transform-origin: 0% 0%; -webkit-transform: translate3d(0, -40%, 0) rotateX(80deg); transform: translate3d(0, -40%, 0) rotateX(80deg); } .reveal.page .slides > section > section.future { -webkit-transform-origin: 0% 100%; - -ms-transform-origin: 0% 100%; transform-origin: 0% 100%; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } @@ -630,26 +929,25 @@ body { /********************************************* * FADE TRANSITION *********************************************/ -.reveal .slides section[data-transition=fade], .reveal.fade .slides section:not([data-transition]), .reveal.fade .slides > section > section:not([data-transition]) { +.reveal .slides section[data-transition=fade], +.reveal.fade .slides section:not([data-transition]), +.reveal.fade .slides > section > section:not([data-transition]) { -webkit-transform: none; - -ms-transform: none; transform: none; - -webkit-transition: opacity 0.5s; - transition: opacity 0.5s; } + transition: opacity 0.5s; } -.reveal.fade.overview .slides section, .reveal.fade.overview .slides > section > section { - -webkit-transition: none; - transition: none; } +.reveal.fade.overview .slides section, +.reveal.fade.overview .slides > section > section { + transition: none; } /********************************************* * NO TRANSITION *********************************************/ -.reveal .slides > section[data-transition=none], .reveal.none .slides > section:not([data-transition]) { +.reveal .slides section[data-transition=none], +.reveal.none .slides section:not([data-transition]) { -webkit-transform: none; - -ms-transform: none; transform: none; - -webkit-transition: none; - transition: none; } + transition: none; } /********************************************* * PAUSED MODE @@ -664,8 +962,22 @@ body { visibility: hidden; opacity: 0; z-index: 100; - -webkit-transition: all 1s ease; - transition: all 1s ease; } + transition: all 1s ease; } + +.reveal .pause-overlay .resume-button { + position: absolute; + bottom: 20px; + right: 20px; + color: #ccc; + border-radius: 2px; + padding: 6px 14px; + border: 2px solid #ccc; + font-size: 16px; + background: transparent; + cursor: pointer; } + .reveal .pause-overlay .resume-button:hover { + color: #fff; + border-color: #fff; } .reveal.paused .pause-overlay { visibility: visible; @@ -686,7 +998,8 @@ body { margin: 0; text-align: center; } -.no-transforms .reveal .controls, .no-transforms .reveal .progress { +.no-transforms .reveal .controls, +.no-transforms .reveal .progress { display: none !important; } .no-transforms .reveal .slides section { @@ -699,15 +1012,14 @@ body { left: -50%; margin: 70px 0; -webkit-transform: none; - -ms-transform: none; transform: none; } .no-transforms .reveal .slides section section { left: 0; } -.reveal .no-transition, .reveal .no-transition * { - -webkit-transition: none !important; - transition: none !important; } +.reveal .no-transition, +.reveal .no-transition * { + transition: none !important; } /********************************************* * PER-SLIDE BACKGROUNDS @@ -728,19 +1040,25 @@ body { height: 100%; opacity: 0; visibility: hidden; - background-color: rgba(0, 0, 0, 0); + overflow: hidden; + background-color: transparent; + transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +.reveal .slide-background-content { + position: absolute; + width: 100%; + height: 100%; background-position: 50% 50%; background-repeat: no-repeat; - background-size: cover; - -webkit-transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); - transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + background-size: cover; } .reveal .slide-background.stack { display: block; } .reveal .slide-background.present { opacity: 1; - visibility: visible; } + visibility: visible; + z-index: 2; } .print-pdf .reveal .slide-background { opacity: 1 !important; @@ -754,122 +1072,135 @@ body { max-width: none; max-height: none; top: 0; - left: 0; } + left: 0; + -o-object-fit: cover; + object-fit: cover; } + +.reveal .slide-background[data-background-size="contain"] video { + -o-object-fit: contain; + object-fit: contain; } /* Immediate transition style */ -.reveal[data-background-transition=none] > .backgrounds .slide-background, .reveal > .backgrounds .slide-background[data-background-transition=none] { - -webkit-transition: none; - transition: none; } +.reveal[data-background-transition=none] > .backgrounds .slide-background, +.reveal > .backgrounds .slide-background[data-background-transition=none] { + transition: none; } /* Slide */ -.reveal[data-background-transition=slide] > .backgrounds .slide-background, .reveal > .backgrounds .slide-background[data-background-transition=slide] { +.reveal[data-background-transition=slide] > .backgrounds .slide-background, +.reveal > .backgrounds .slide-background[data-background-transition=slide] { opacity: 1; -webkit-backface-visibility: hidden; backface-visibility: hidden; } -.reveal[data-background-transition=slide] > .backgrounds .slide-background.past, .reveal > .backgrounds .slide-background.past[data-background-transition=slide] { +.reveal[data-background-transition=slide] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=slide] { -webkit-transform: translate(-100%, 0); - -ms-transform: translate(-100%, 0); transform: translate(-100%, 0); } -.reveal[data-background-transition=slide] > .backgrounds .slide-background.future, .reveal > .backgrounds .slide-background.future[data-background-transition=slide] { +.reveal[data-background-transition=slide] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=slide] { -webkit-transform: translate(100%, 0); - -ms-transform: translate(100%, 0); transform: translate(100%, 0); } -.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.past, .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=slide] { +.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=slide] { -webkit-transform: translate(0, -100%); - -ms-transform: translate(0, -100%); transform: translate(0, -100%); } -.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.future, .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=slide] { +.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=slide] { -webkit-transform: translate(0, 100%); - -ms-transform: translate(0, 100%); transform: translate(0, 100%); } /* Convex */ -.reveal[data-background-transition=convex] > .backgrounds .slide-background.past, .reveal > .backgrounds .slide-background.past[data-background-transition=convex] { +.reveal[data-background-transition=convex] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=convex] { opacity: 0; -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } -.reveal[data-background-transition=convex] > .backgrounds .slide-background.future, .reveal > .backgrounds .slide-background.future[data-background-transition=convex] { +.reveal[data-background-transition=convex] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=convex] { opacity: 0; -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } -.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.past, .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=convex] { +.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=convex] { opacity: 0; -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); } -.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.future, .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=convex] { +.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=convex] { opacity: 0; -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); } /* Concave */ -.reveal[data-background-transition=concave] > .backgrounds .slide-background.past, .reveal > .backgrounds .slide-background.past[data-background-transition=concave] { +.reveal[data-background-transition=concave] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=concave] { opacity: 0; -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } -.reveal[data-background-transition=concave] > .backgrounds .slide-background.future, .reveal > .backgrounds .slide-background.future[data-background-transition=concave] { +.reveal[data-background-transition=concave] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=concave] { opacity: 0; -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } -.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.past, .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=concave] { +.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=concave] { opacity: 0; -webkit-transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); } -.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.future, .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=concave] { +.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=concave] { opacity: 0; -webkit-transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); } /* Zoom */ -.reveal[data-background-transition=zoom] > .backgrounds .slide-background, .reveal > .backgrounds .slide-background[data-background-transition=zoom] { - -webkit-transition-timing-function: ease; - transition-timing-function: ease; } +.reveal[data-background-transition=zoom] > .backgrounds .slide-background, +.reveal > .backgrounds .slide-background[data-background-transition=zoom] { + transition-timing-function: ease; } -.reveal[data-background-transition=zoom] > .backgrounds .slide-background.past, .reveal > .backgrounds .slide-background.past[data-background-transition=zoom] { +.reveal[data-background-transition=zoom] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=zoom] { opacity: 0; visibility: hidden; -webkit-transform: scale(16); - -ms-transform: scale(16); transform: scale(16); } -.reveal[data-background-transition=zoom] > .backgrounds .slide-background.future, .reveal > .backgrounds .slide-background.future[data-background-transition=zoom] { +.reveal[data-background-transition=zoom] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=zoom] { opacity: 0; visibility: hidden; -webkit-transform: scale(0.2); - -ms-transform: scale(0.2); transform: scale(0.2); } -.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.past, .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=zoom] { +.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=zoom] { opacity: 0; visibility: hidden; -webkit-transform: scale(16); - -ms-transform: scale(16); transform: scale(16); } -.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.future, .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=zoom] { +.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=zoom] { opacity: 0; visibility: hidden; -webkit-transform: scale(0.2); - -ms-transform: scale(0.2); transform: scale(0.2); } /* Global transition speed settings */ .reveal[data-transition-speed="fast"] > .backgrounds .slide-background { - -webkit-transition-duration: 400ms; - transition-duration: 400ms; } + transition-duration: 400ms; } .reveal[data-transition-speed="slow"] > .backgrounds .slide-background { - -webkit-transition-duration: 1200ms; - transition-duration: 1200ms; } + transition-duration: 1200ms; } /********************************************* * OVERVIEW @@ -879,22 +1210,25 @@ body { perspective-origin: 50% 50%; -webkit-perspective: 700px; perspective: 700px; } + .reveal.overview .slides { + -moz-transform-style: preserve-3d; } .reveal.overview .slides section { - height: 700px; + height: 100%; + top: 0 !important; opacity: 1 !important; overflow: hidden; visibility: visible !important; cursor: pointer; - -moz-box-sizing: border-box; - box-sizing: border-box; } - .reveal.overview .slides section:hover, .reveal.overview .slides section.present { + box-sizing: border-box; } + .reveal.overview .slides section:hover, + .reveal.overview .slides section.present { outline: 10px solid rgba(150, 150, 150, 0.4); outline-offset: 10px; } .reveal.overview .slides section .fragment { opacity: 1; - -webkit-transition: none; - transition: none; } - .reveal.overview .slides section:after, .reveal.overview .slides section:before { + transition: none; } + .reveal.overview .slides section:after, + .reveal.overview .slides section:before { display: none !important; } .reveal.overview .slides > section.stack { padding: 0; @@ -904,36 +1238,43 @@ body { overflow: visible; } .reveal.overview .backgrounds { -webkit-perspective: inherit; - perspective: inherit; } + perspective: inherit; + -moz-transform-style: preserve-3d; } .reveal.overview .backgrounds .slide-background { opacity: 1; visibility: visible; outline: 10px solid rgba(150, 150, 150, 0.1); outline-offset: 10px; } + .reveal.overview .backgrounds .slide-background.stack { + overflow: visible; } -.reveal.overview .slides section, .reveal.overview-deactivating .slides section { - -webkit-transition: none; - transition: none; } - -.reveal.overview .backgrounds .slide-background, .reveal.overview-deactivating .backgrounds .slide-background { - -webkit-transition: none; - transition: none; } +.reveal.overview .slides section, +.reveal.overview-deactivating .slides section { + transition: none; } -.reveal.overview-animated .slides { - -webkit-transition: -webkit-transform 0.4s ease; - transition: transform 0.4s ease; } +.reveal.overview .backgrounds .slide-background, +.reveal.overview-deactivating .backgrounds .slide-background { + transition: none; } /********************************************* * RTL SUPPORT *********************************************/ -.reveal.rtl .slides, .reveal.rtl .slides h1, .reveal.rtl .slides h2, .reveal.rtl .slides h3, .reveal.rtl .slides h4, .reveal.rtl .slides h5, .reveal.rtl .slides h6 { +.reveal.rtl .slides, +.reveal.rtl .slides h1, +.reveal.rtl .slides h2, +.reveal.rtl .slides h3, +.reveal.rtl .slides h4, +.reveal.rtl .slides h5, +.reveal.rtl .slides h6 { direction: rtl; font-family: sans-serif; } -.reveal.rtl pre, .reveal.rtl code { +.reveal.rtl pre, +.reveal.rtl code { direction: ltr; } -.reveal.rtl ol, .reveal.rtl ul { +.reveal.rtl ol, +.reveal.rtl ul { text-align: right; } .reveal.rtl .progress span { @@ -943,17 +1284,14 @@ body { * PARALLAX BACKGROUND *********************************************/ .reveal.has-parallax-background .backgrounds { - -webkit-transition: all 0.8s ease; - transition: all 0.8s ease; } + transition: all 0.8s ease; } /* Global transition speed settings */ .reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds { - -webkit-transition-duration: 400ms; - transition-duration: 400ms; } + transition-duration: 400ms; } .reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds { - -webkit-transition-duration: 1200ms; - transition-duration: 1200ms; } + transition-duration: 1200ms; } /********************************************* * LINK PREVIEW OVERLAY @@ -968,8 +1306,7 @@ body { background: rgba(0, 0, 0, 0.9); opacity: 0; visibility: hidden; - -webkit-transition: all 0.3s ease; - transition: all 0.3s ease; } + transition: all 0.3s ease; } .reveal .overlay.visible { opacity: 1; @@ -987,8 +1324,7 @@ body { background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D); visibility: visible; opacity: 0.6; - -webkit-transition: all 0.3s ease; - transition: all 0.3s ease; } + transition: all 0.3s ease; } .reveal .overlay header { position: absolute; @@ -1003,11 +1339,11 @@ body { display: inline-block; width: 40px; height: 40px; + line-height: 36px; padding: 0 10px; float: right; opacity: 0.6; - -moz-box-sizing: border-box; - box-sizing: border-box; } + box-sizing: border-box; } .reveal .overlay header a:hover { opacity: 1; } @@ -1028,6 +1364,9 @@ body { .reveal .overlay .viewport { position: absolute; + display: -webkit-box; + display: -ms-flexbox; + display: flex; top: 40px; right: 0; bottom: 0; @@ -1041,18 +1380,32 @@ body { border: 0; opacity: 0; visibility: hidden; - -webkit-transition: all 0.3s ease; - transition: all 0.3s ease; } + transition: all 0.3s ease; } .reveal .overlay.overlay-preview.loaded .viewport iframe { opacity: 1; visibility: visible; } +.reveal .overlay.overlay-preview.loaded .viewport-inner { + position: absolute; + z-index: -1; + left: 0; + top: 45%; + width: 100%; + text-align: center; + letter-spacing: normal; } + +.reveal .overlay.overlay-preview .x-frame-error { + opacity: 0; + transition: opacity 0.3s ease 0.3s; } + +.reveal .overlay.overlay-preview.loaded .x-frame-error { + opacity: 1; } + .reveal .overlay.overlay-preview.loaded .spinner { opacity: 0; visibility: hidden; -webkit-transform: scale(0.2); - -ms-transform: scale(0.2); transform: scale(0.2); } .reveal .overlay.overlay-help .viewport { @@ -1061,8 +1414,8 @@ body { .reveal .overlay.overlay-help .viewport .viewport-inner { width: 600px; - margin: 0 auto; - padding: 60px; + margin: auto; + padding: 20px 20px 80px 20px; text-align: center; letter-spacing: normal; } @@ -1072,11 +1425,12 @@ body { .reveal .overlay.overlay-help .viewport .viewport-inner table { border: 1px solid #fff; border-collapse: collapse; - font-size: 14px; } + font-size: 16px; } -.reveal .overlay.overlay-help .viewport .viewport-inner table th, .reveal .overlay.overlay-help .viewport .viewport-inner table td { +.reveal .overlay.overlay-help .viewport .viewport-inner table th, +.reveal .overlay.overlay-help .viewport .viewport-inner table td { width: 200px; - padding: 10px; + padding: 14px; border: 1px solid #fff; vertical-align: middle; } @@ -1088,13 +1442,13 @@ body { * PLAYBACK COMPONENT *********************************************/ .reveal .playback { - position: fixed; + position: absolute; left: 15px; - bottom: 15px; + bottom: 20px; z-index: 30; cursor: pointer; - -webkit-transition: all 400ms ease; - transition: all 400ms ease; } + transition: all 400ms ease; + -webkit-tap-highlight-color: transparent; } .reveal.overview .playback { opacity: 0; @@ -1122,10 +1476,8 @@ body { position: relative; padding: 0 2px; pointer-events: none; - -webkit-transition: all 400ms ease; - transition: all 400ms ease; + transition: all 400ms ease; -webkit-transform-origin: 50% 0%; - -ms-transform-origin: 50% 0%; transform-origin: 50% 0%; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; @@ -1147,7 +1499,6 @@ body { -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-transform-origin: 50% 0%; - -ms-transform-origin: 50% 0%; transform-origin: 50% 0%; -webkit-transform: translate3d(0px, 110%, 0px) rotateX(-90deg); transform: translate3d(0px, 110%, 0px) rotateX(-90deg); } @@ -1158,14 +1509,79 @@ body { .reveal aside.notes { display: none; } +.reveal .speaker-notes { + display: none; + position: absolute; + width: 25vw; + height: 100%; + top: 0; + left: 100%; + padding: 14px 18px 14px 18px; + z-index: 1; + font-size: 18px; + line-height: 1.4; + border: 1px solid rgba(0, 0, 0, 0.05); + color: #222; + background-color: #f5f5f5; + overflow: auto; + box-sizing: border-box; + text-align: left; + font-family: Helvetica, sans-serif; + -webkit-overflow-scrolling: touch; } + .reveal .speaker-notes .notes-placeholder { + color: #ccc; + font-style: italic; } + .reveal .speaker-notes:focus { + outline: none; } + .reveal .speaker-notes:before { + content: 'Speaker notes'; + display: block; + margin-bottom: 10px; + opacity: 0.5; } + +.reveal.show-notes { + max-width: 75vw; + overflow: visible; } + +.reveal.show-notes .speaker-notes { + display: block; } + +@media screen and (min-width: 1600px) { + .reveal .speaker-notes { + font-size: 20px; } } + +@media screen and (max-width: 1024px) { + .reveal.show-notes { + border-left: 0; + max-width: none; + max-height: 70%; + overflow: visible; } + .reveal.show-notes .speaker-notes { + top: 100%; + left: 0; + width: 100%; + height: 42.8571428571%; } } + +@media screen and (max-width: 600px) { + .reveal.show-notes { + max-height: 60%; } + .reveal.show-notes .speaker-notes { + top: 100%; + height: 66.6666666667%; } + .reveal .speaker-notes { + font-size: 14px; } } + /********************************************* * ZOOM PLUGIN *********************************************/ -.zoomed .reveal *, .zoomed .reveal *:before, .zoomed .reveal *:after { +.zoomed .reveal *, +.zoomed .reveal *:before, +.zoomed .reveal *:after { -webkit-backface-visibility: visible !important; backface-visibility: visible !important; } -.zoomed .reveal .progress, .zoomed .reveal .controls { +.zoomed .reveal .progress, +.zoomed .reveal .controls { opacity: 0; } .zoomed .reveal .roll span { diff --git a/css/reveal.scss b/css/reveal.scss index 3321c98..e6608d4 100644 --- a/css/reveal.scss +++ b/css/reveal.scss @@ -1,9 +1,9 @@ /*! * reveal.js - * http://lab.hakim.se/reveal-js + * http://revealjs.com * MIT licensed * - * Copyright (C) 2015 Hakim El Hattab, http://hakim.se + * Copyright (C) 2018 Hakim El Hattab, http://hakim.se */ @@ -23,7 +23,7 @@ html, body, .reveal div, .reveal span, .reveal applet, .reveal object, .reveal i .reveal article, .reveal aside, .reveal canvas, .reveal details, .reveal embed, .reveal figure, .reveal figcaption, .reveal footer, .reveal header, .reveal hgroup, .reveal menu, .reveal nav, .reveal output, .reveal ruby, .reveal section, .reveal summary, -.reveal time, .reveal mark, .reveal audio, video { +.reveal time, .reveal mark, .reveal audio, .reveal video { margin: 0; padding: 0; border: 0; @@ -69,13 +69,13 @@ body { &.visible { opacity: 1; - visibility: visible; + visibility: inherit; } } .reveal .slides section .fragment.grow { opacity: 1; - visibility: visible; + visibility: inherit; &.visible { transform: scale( 1.3 ); @@ -84,7 +84,7 @@ body { .reveal .slides section .fragment.shrink { opacity: 1; - visibility: visible; + visibility: inherit; &.visible { transform: scale( 0.7 ); @@ -101,7 +101,7 @@ body { .reveal .slides section .fragment.fade-out { opacity: 1; - visibility: visible; + visibility: inherit; &.visible { opacity: 0; @@ -111,29 +111,78 @@ body { .reveal .slides section .fragment.semi-fade-out { opacity: 1; - visibility: visible; + visibility: inherit; &.visible { opacity: 0.5; - visibility: visible; + visibility: inherit; } } .reveal .slides section .fragment.strike { opacity: 1; + visibility: inherit; &.visible { text-decoration: line-through; } } +.reveal .slides section .fragment.fade-up { + transform: translate(0, 20%); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-down { + transform: translate(0, -20%); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-right { + transform: translate(-20%, 0); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-left { + transform: translate(20%, 0); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-in-then-out, .reveal .slides section .fragment.current-visible { opacity: 0; visibility: hidden; &.current-fragment { opacity: 1; - visibility: visible; + visibility: inherit; + } +} + +.reveal .slides section .fragment.fade-in-then-semi-out { + opacity: 0; + visibility: hidden; + + &.visible { + opacity: 0.5; + visibility: inherit; + } + + &.current-fragment { + opacity: 1; + visibility: inherit; } } @@ -144,7 +193,7 @@ body { .reveal .slides section .fragment.highlight-blue, .reveal .slides section .fragment.highlight-current-blue { opacity: 1; - visibility: visible; + visibility: inherit; } .reveal .slides section .fragment.highlight-red.visible { color: #ff2c2d @@ -202,80 +251,271 @@ body { * CONTROLS *********************************************/ -.reveal .controls { - display: none; - position: fixed; - width: 110px; - height: 110px; - z-index: 30; - right: 10px; - bottom: 10px; +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% {transform: translateX(0);} + 20% {transform: translateX(10px);} + 30% {transform: translateX(-5px);} +} - -webkit-user-select: none; +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% {transform: translateY(0);} + 20% {transform: translateY(10px);} + 30% {transform: translateY(-5px);} } -.reveal .controls div { - position: absolute; - opacity: 0.05; - width: 0; - height: 0; - border: 12px solid transparent; - transform: scale(.9999); - transition: all 0.2s ease; +$controlArrowSize: 3.6em; +$controlArrowSpacing: 1.4em; +$controlArrowLength: 2.6em; +$controlArrowThickness: 0.5em; +$controlsArrowAngle: 45deg; +$controlsArrowAngleHover: 40deg; +$controlsArrowAngleActive: 36deg; - -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); -} +@mixin controlsArrowTransform( $angle ) { + &:before { + transform: translateX(($controlArrowSize - $controlArrowLength)/2) translateY(($controlArrowSize - $controlArrowThickness)/2) rotate( $angle ); + } -.reveal .controls div.enabled { - opacity: 0.7; - cursor: pointer; + &:after { + transform: translateX(($controlArrowSize - $controlArrowLength)/2) translateY(($controlArrowSize - $controlArrowThickness)/2) rotate( -$angle ); + } } -.reveal .controls div.enabled:active { - margin-top: 1px; -} +.reveal .controls { + $spacing: 12px; + + display: none; + position: absolute; + top: auto; + bottom: $spacing; + right: $spacing; + left: auto; + z-index: 1; + color: #000; + pointer-events: none; + font-size: 10px; + + button { + position: absolute; + padding: 0; + background-color: transparent; + border: 0; + outline: 0; + cursor: pointer; + color: currentColor; + transform: scale(.9999); + transition: color 0.2s ease, + opacity 0.2s ease, + transform 0.2s ease; + z-index: 2; // above slides + pointer-events: auto; + font-size: inherit; + + visibility: hidden; + opacity: 0; + + -webkit-appearance: none; + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); + } - .reveal .controls div.navigate-left { - top: 42px; + .controls-arrow:before, + .controls-arrow:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: $controlArrowLength; + height: $controlArrowThickness; + border-radius: $controlArrowThickness/2; + background-color: currentColor; - border-right-width: 22px; - border-right-color: #000; + transition: all 0.15s ease, background-color 0.8s ease; + transform-origin: floor(($controlArrowThickness/2)*10)/10 50%; + will-change: transform; } - .reveal .controls div.navigate-left.fragmented { - opacity: 0.3; + + .controls-arrow { + position: relative; + width: $controlArrowSize; + height: $controlArrowSize; + + @include controlsArrowTransform( $controlsArrowAngle ); + + &:hover { + @include controlsArrowTransform( $controlsArrowAngleHover ); + } + + &:active { + @include controlsArrowTransform( $controlsArrowAngleActive ); } + } + + .navigate-left { + right: $controlArrowSize + $controlArrowSpacing*2; + bottom: $controlArrowSpacing + $controlArrowSize/2; + transform: translateX( -10px ); + } - .reveal .controls div.navigate-right { - left: 74px; - top: 42px; + .navigate-right { + right: 0; + bottom: $controlArrowSpacing + $controlArrowSize/2; + transform: translateX( 10px ); + + .controls-arrow { + transform: rotate( 180deg ); + } - border-left-width: 22px; - border-left-color: #000; + &.highlight { + animation: bounce-right 2s 50 both ease-out; + } } - .reveal .controls div.navigate-right.fragmented { - opacity: 0.3; + + .navigate-up { + right: $controlArrowSpacing + $controlArrowSize/2; + bottom: $controlArrowSpacing*2 + $controlArrowSize; + transform: translateY( -10px ); + + .controls-arrow { + transform: rotate( 90deg ); } + } + + .navigate-down { + right: $controlArrowSpacing + $controlArrowSize/2; + bottom: 0; + transform: translateY( 10px ); - .reveal .controls div.navigate-up { - left: 42px; + .controls-arrow { + transform: rotate( -90deg ); + } - border-bottom-width: 22px; - border-bottom-color: #000; + &.highlight { + animation: bounce-down 2s 50 both ease-out; + } } - .reveal .controls div.navigate-up.fragmented { - opacity: 0.3; + + // Back arrow style: "faded": + // Deemphasize backwards navigation arrows in favor of drawing + // attention to forwards navigation + &[data-controls-back-arrows="faded"] .navigate-left.enabled, + &[data-controls-back-arrows="faded"] .navigate-up.enabled { + opacity: 0.3; + + &:hover { + opacity: 1; } + } + + // Back arrow style: "hidden": + // Never show arrows for backwards navigation + &[data-controls-back-arrows="hidden"] .navigate-left.enabled, + &[data-controls-back-arrows="hidden"] .navigate-up.enabled { + opacity: 0; + visibility: hidden; + } + + // Any control button that can be clicked is "enabled" + .enabled { + visibility: visible; + opacity: 0.9; + cursor: pointer; + transform: none; + } - .reveal .controls div.navigate-down { - left: 42px; - top: 74px; + // Any control button that leads to showing or hiding + // a fragment + .enabled.fragmented { + opacity: 0.5; + } - border-top-width: 22px; - border-top-color: #000; + .enabled:hover, + .enabled.fragmented:hover { + opacity: 1; } - .reveal .controls div.navigate-down.fragmented { - opacity: 0.3; +} + +// Adjust the layout when there are no vertical slides +.reveal:not(.has-vertical-slides) .controls .navigate-left { + bottom: $controlArrowSpacing; + right: 0.5em + $controlArrowSpacing + $controlArrowSize; +} + +.reveal:not(.has-vertical-slides) .controls .navigate-right { + bottom: $controlArrowSpacing; + right: 0.5em; +} + +// Adjust the layout when there are no horizontal slides +.reveal:not(.has-horizontal-slides) .controls .navigate-up { + right: $controlArrowSpacing; + bottom: $controlArrowSpacing + $controlArrowSize; +} +.reveal:not(.has-horizontal-slides) .controls .navigate-down { + right: $controlArrowSpacing; + bottom: 0.5em; +} + +// Invert arrows based on background color +.reveal.has-dark-background .controls { + color: #fff; +} +.reveal.has-light-background .controls { + color: #000; +} + +// Disable active states on touch devices +.reveal.no-hover .controls .controls-arrow:hover, +.reveal.no-hover .controls .controls-arrow:active { + @include controlsArrowTransform( $controlsArrowAngle ); +} + +// Edge aligned controls layout +@media screen and (min-width: 500px) { + + $spacing: 8px; + + .reveal .controls[data-controls-layout="edges"] { + & { + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + .navigate-left, + .navigate-right, + .navigate-up, + .navigate-down { + bottom: auto; + right: auto; + } + + .navigate-left { + top: 50%; + left: $spacing; + margin-top: -$controlArrowSize/2; + } + + .navigate-right { + top: 50%; + right: $spacing; + margin-top: -$controlArrowSize/2; + } + + .navigate-up { + top: $spacing; + left: 50%; + margin-left: -$controlArrowSize/2; + } + + .navigate-down { + bottom: $spacing; + left: 50%; + margin-left: -$controlArrowSize/2; } + } + +} /********************************************* @@ -283,7 +523,7 @@ body { *********************************************/ .reveal .progress { - position: fixed; + position: absolute; display: none; height: 3px; width: 100%; @@ -292,21 +532,22 @@ body { z-index: 10; background-color: rgba( 0, 0, 0, 0.2 ); + color: #fff; } .reveal .progress:after { content: ''; display: block; position: absolute; - height: 20px; + height: 10px; width: 100%; - top: -20px; + top: -10px; } .reveal .progress span { display: block; height: 100%; width: 0px; - background-color: #000; + background-color: currentColor; transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); } @@ -315,13 +556,25 @@ body { *********************************************/ .reveal .slide-number { - position: fixed; + position: absolute; display: block; - right: 15px; - bottom: 15px; - opacity: 0.5; + right: 8px; + bottom: 8px; z-index: 31; + font-family: Helvetica, sans-serif; font-size: 12px; + line-height: 1; + color: #fff; + background-color: rgba( 0, 0, 0, 0.4 ); + padding: 5px; +} + +.reveal .slide-number a { + color: currentColor; +} + +.reveal .slide-number-delimiter { + margin: 0 3px; } /********************************************* @@ -336,6 +589,16 @@ body { touch-action: none; } +// Mobile Safari sometimes overlays a header at the top +// of the page when in landscape mode. Using fixed +// positioning ensures that reveal.js reduces its height +// when this header is visible. +@media only screen and (orientation : landscape) { + .reveal.ua-iphone { + position: fixed; + } +} + .reveal .slides { position: absolute; width: 100%; @@ -345,6 +608,7 @@ body { bottom: 0; left: 0; margin: auto; + pointer-events: none; overflow: visible; z-index: 1; @@ -363,9 +627,10 @@ body { position: absolute; width: 100%; padding: 20px 0px; + pointer-events: auto; z-index: 10; - transform-style: preserve-3d; + transform-style: flat; transition: transform-origin 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), transform 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), visibility 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), @@ -391,6 +656,7 @@ body { .reveal .slides>section.stack { padding-top: 0; padding-bottom: 0; + pointer-events: none; } .reveal .slides>section.present, @@ -400,6 +666,13 @@ body { opacity: 1; } +.reveal .slides>section:empty, +.reveal .slides>section>section:empty, +.reveal .slides>section[data-background-interactive], +.reveal .slides>section>section[data-background-interactive] { + pointer-events: none; +} + .reveal.center, .reveal.center .slides, .reveal.center .slides section { @@ -432,8 +705,14 @@ body { *********************************************/ @mixin transition-global($style) { - .reveal .slides>section[data-transition=#{$style}], - .reveal.#{$style} .slides>section:not([data-transition]) { + .reveal .slides section[data-transition=#{$style}], + .reveal.#{$style} .slides section:not([data-transition]) { + @content; + } +} +@mixin transition-stack($style) { + .reveal .slides section[data-transition=#{$style}].stack, + .reveal.#{$style} .slides section.stack { @content; } } @@ -496,6 +775,10 @@ body { *********************************************/ @each $stylename in default, convex { + @include transition-stack(#{$stylename}) { + transform-style: preserve-3d; + } + @include transition-horizontal-past(#{$stylename}) { transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } @@ -514,6 +797,10 @@ body { * CONCAVE TRANSITION *********************************************/ +@include transition-stack(concave) { + transform-style: preserve-3d; +} + @include transition-horizontal-past(concave) { transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } @@ -553,6 +840,10 @@ body { /********************************************* * CUBE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. *********************************************/ .reveal.cube .slides { @@ -564,6 +855,7 @@ body { min-height: 700px; backface-visibility: hidden; box-sizing: border-box; + transform-style: preserve-3d; } .reveal.center.cube .slides section { min-height: 0; @@ -624,6 +916,10 @@ body { /********************************************* * PAGE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. *********************************************/ .reveal.page .slides { @@ -635,6 +931,7 @@ body { padding: 30px; min-height: 700px; box-sizing: border-box; + transform-style: preserve-3d; } .reveal.page .slides section.past { z-index: 12; @@ -737,6 +1034,25 @@ body { z-index: 100; transition: all 1s ease; } + +.reveal .pause-overlay .resume-button { + position: absolute; + bottom: 20px; + right: 20px; + color: #ccc; + border-radius: 2px; + padding: 6px 14px; + border: 2px solid #ccc; + font-size: 16px; + background: transparent; + cursor: pointer; + + &:hover { + color: #fff; + border-color: #fff; + } +} + .reveal.paused .pause-overlay { visibility: visible; opacity: 1; @@ -807,13 +1123,21 @@ body { height: 100%; opacity: 0; visibility: hidden; + overflow: hidden; background-color: rgba( 0, 0, 0, 0 ); + + transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + } + + .reveal .slide-background-content { + position: absolute; + width: 100%; + height: 100%; + background-position: 50% 50%; background-repeat: no-repeat; background-size: cover; - - transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); } .reveal .slide-background.stack { @@ -823,6 +1147,7 @@ body { .reveal .slide-background.present { opacity: 1; visibility: visible; + z-index: 2; } .print-pdf .reveal .slide-background { @@ -839,7 +1164,11 @@ body { max-height: none; top: 0; left: 0; + object-fit: cover; } + .reveal .slide-background[data-background-size="contain"] video { + object-fit: contain; + } /* Immediate transition style */ .reveal[data-background-transition=none]>.backgrounds .slide-background, @@ -969,8 +1298,15 @@ body { perspective-origin: 50% 50%; perspective: 700px; + .slides { + // Fixes overview rendering errors in FF48+, not applied to + // other browsers since it degrades performance + -moz-transform-style: preserve-3d; + } + .slides section { - height: 700px; + height: 100%; + top: 0 !important; opacity: 1 !important; overflow: hidden; visibility: visible !important; @@ -1000,6 +1336,10 @@ body { .backgrounds { perspective: inherit; + + // Fixes overview rendering errors in FF48+, not applied to + // other browsers since it degrades performance + -moz-transform-style: preserve-3d; } .backgrounds .slide-background { @@ -1010,6 +1350,10 @@ body { outline: 10px solid rgba(150,150,150,0.1); outline-offset: 10px; } + + .backgrounds .slide-background.stack { + overflow: visible; + } } // Disable transitions transitions while we're activating @@ -1024,10 +1368,6 @@ body { transition: none; } -.reveal.overview-animated .slides { - transition: transform 0.4s ease; -} - /********************************************* * RTL SUPPORT @@ -1125,6 +1465,7 @@ body { display: inline-block; width: 40px; height: 40px; + line-height: 36px; padding: 0 10px; float: right; opacity: 0.6; @@ -1152,6 +1493,7 @@ body { .reveal .overlay .viewport { position: absolute; + display: flex; top: 40px; right: 0; bottom: 0; @@ -1175,6 +1517,23 @@ body { visibility: visible; } + .reveal .overlay.overlay-preview.loaded .viewport-inner { + position: absolute; + z-index: -1; + left: 0; + top: 45%; + width: 100%; + text-align: center; + letter-spacing: normal; + } + .reveal .overlay.overlay-preview .x-frame-error { + opacity: 0; + transition: opacity 0.3s ease 0.3s; + } + .reveal .overlay.overlay-preview.loaded .x-frame-error { + opacity: 1; + } + .reveal .overlay.overlay-preview.loaded .spinner { opacity: 0; visibility: hidden; @@ -1188,8 +1547,8 @@ body { .reveal .overlay.overlay-help .viewport .viewport-inner { width: 600px; - margin: 0 auto; - padding: 60px; + margin: auto; + padding: 20px 20px 80px 20px; text-align: center; letter-spacing: normal; } @@ -1201,13 +1560,13 @@ body { .reveal .overlay.overlay-help .viewport .viewport-inner table { border: 1px solid #fff; border-collapse: collapse; - font-size: 14px; + font-size: 16px; } .reveal .overlay.overlay-help .viewport .viewport-inner table th, .reveal .overlay.overlay-help .viewport .viewport-inner table td { width: 200px; - padding: 10px; + padding: 14px; border: 1px solid #fff; vertical-align: middle; } @@ -1224,12 +1583,13 @@ body { *********************************************/ .reveal .playback { - position: fixed; + position: absolute; left: 15px; - bottom: 15px; + bottom: 20px; z-index: 30; cursor: pointer; transition: all 400ms ease; + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); } .reveal.overview .playback { @@ -1288,10 +1648,97 @@ body { * SPEAKER NOTES *********************************************/ +// Hide on-page notes .reveal aside.notes { display: none; } +// An interface element that can optionally be used to show the +// speaker notes to all viewers, on top of the presentation +.reveal .speaker-notes { + display: none; + position: absolute; + width: 25vw; + height: 100%; + top: 0; + left: 100%; + padding: 14px 18px 14px 18px; + z-index: 1; + font-size: 18px; + line-height: 1.4; + border: 1px solid rgba( 0, 0, 0, 0.05 ); + color: #222; + background-color: #f5f5f5; + overflow: auto; + box-sizing: border-box; + text-align: left; + font-family: Helvetica, sans-serif; + -webkit-overflow-scrolling: touch; + + .notes-placeholder { + color: #ccc; + font-style: italic; + } + + &:focus { + outline: none; + } + + &:before { + content: 'Speaker notes'; + display: block; + margin-bottom: 10px; + opacity: 0.5; + } +} + + +.reveal.show-notes { + max-width: 75vw; + overflow: visible; +} + +.reveal.show-notes .speaker-notes { + display: block; +} + +@media screen and (min-width: 1600px) { + .reveal .speaker-notes { + font-size: 20px; + } +} + +@media screen and (max-width: 1024px) { + .reveal.show-notes { + border-left: 0; + max-width: none; + max-height: 70%; + overflow: visible; + } + + .reveal.show-notes .speaker-notes { + top: 100%; + left: 0; + width: 100%; + height: (30/0.7)*1%; + } +} + +@media screen and (max-width: 600px) { + .reveal.show-notes { + max-height: 60%; + } + + .reveal.show-notes .speaker-notes { + top: 100%; + height: (40/0.6)*1%; + } + + .reveal .speaker-notes { + font-size: 14px; + } +} + /********************************************* * ZOOM PLUGIN @@ -1315,5 +1762,3 @@ body { .zoomed .reveal .roll span:after { visibility: hidden; } - - diff --git a/css/theme/README.md b/css/theme/README.md index 753e0c0..8ae164b 100644 --- a/css/theme/README.md +++ b/css/theme/README.md @@ -1,10 +1,10 @@ ## Dependencies -Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment including the Grunt dependencies installed before proceding: https://github.com/hakimel/reveal.js#full-setup +Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment including the Grunt dependencies installed before proceeding: https://github.com/hakimel/reveal.js#full-setup ## Creating a Theme -To create your own theme, start by duplicating any ```.scss``` file in [/css/theme/source](https://github.com/hakimel/reveal.js/blob/master/css/theme/source) and adding it to the compilation list in the [Gruntfile](https://github.com/hakimel/reveal.js/blob/master/Gruntfile.js). +To create your own theme, start by duplicating a ```.scss``` file in [/css/theme/source](https://github.com/hakimel/reveal.js/blob/master/css/theme/source). It will be automatically compiled by Grunt from Sass to CSS (see the [Gruntfile](https://github.com/hakimel/reveal.js/blob/master/Gruntfile.js)) when you run `npm run build -- css-themes`. Each theme file does four things in the following order: @@ -19,5 +19,3 @@ This is where you override the default theme. Either by specifying variables (se 4. **Include [/css/theme/template/theme.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/theme.scss)** The template theme file which will generate final CSS output based on the currently defined variables. - -When you are done, run `grunt css-themes` to compile the Sass file to CSS and you are ready to use your new theme. diff --git a/css/theme/beige.css b/css/theme/beige.css index 944dbd8..fb5f137 100644 --- a/css/theme/beige.css +++ b/css/theme/beige.css @@ -1,26 +1,26 @@ -@import url(../../lib/font/league-gothic/league-gothic.css); -@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); /** * Beige theme for reveal.js. * * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); /********************************************* * GLOBAL STYLES *********************************************/ body { background: #f7f2d3; - background: -moz-radial-gradient(center, circle cover, #ffffff 0%, #f7f2d3 100%); - background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #ffffff), color-stop(100%, #f7f2d3)); - background: -webkit-radial-gradient(center, circle cover, #ffffff 0%, #f7f2d3 100%); - background: -o-radial-gradient(center, circle cover, #ffffff 0%, #f7f2d3 100%); - background: -ms-radial-gradient(center, circle cover, #ffffff 0%, #f7f2d3 100%); - background: radial-gradient(center, circle cover, #ffffff 0%, #f7f2d3 100%); + background: -moz-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, white), color-stop(100%, #f7f2d3)); + background: -webkit-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: -o-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: -ms-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); background-color: #f7f3de; } .reveal { - font-family: 'Lato', sans-serif; - font-size: 36px; + font-family: "Lato", sans-serif; + font-size: 40px; font-weight: normal; color: #333; } @@ -29,17 +29,28 @@ body { background: rgba(79, 64, 28, 0.99); text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: rgba(79, 64, 28, 0.99); + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #333; - font-family: 'League Gothic', Impact, sans-serif; + font-family: "League Gothic", Impact, sans-serif; font-weight: normal; line-height: 1.2; letter-spacing: normal; @@ -70,17 +81,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -97,7 +113,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -107,9 +126,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -120,7 +136,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -139,16 +156,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -158,25 +174,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -193,18 +215,18 @@ body { .reveal a { color: #8b743d; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { - color: #c0a76e; + color: #c0a86e; text-shadow: none; border: none; } .reveal .roll span:after { color: #fff; - background: #564726; } + background: #564826; } /********************************************* * IMAGES @@ -215,10 +237,14 @@ body { border: 4px solid #333; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -228,44 +254,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #8b743d; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #8b743d; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #8b743d; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #8b743d; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #c0a76e; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #c0a76e; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #c0a76e; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #c0a76e; } +.reveal .controls { + color: #8b743d; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #8b743d; } .reveal .progress span { - background: #8b743d; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #8b743d; } +@media print { + .backgrounds { + background-color: #f7f3de; } } diff --git a/css/theme/black.css b/css/theme/black.css index ee2ead8..dec6385 100644 --- a/css/theme/black.css +++ b/css/theme/black.css @@ -1,9 +1,9 @@ -@import url(../../lib/font/source-sans-pro/source-sans-pro.css); /** * Black theme for reveal.js. This is the opposite of the 'white' theme. * - * Copyright (C) 2015 Hakim El Hattab, http://hakim.se + * By Hakim El Hattab, http://hakim.se */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { color: #222; } @@ -15,8 +15,8 @@ body { background-color: #222; } .reveal { - font-family: 'Source Sans Pro', Helvetica, sans-serif; - font-size: 38px; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 42px; font-weight: normal; color: #fff; } @@ -25,17 +25,28 @@ body { background: #bee4fd; text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #fff; - font-family: 'Source Sans Pro', Helvetica, sans-serif; + font-family: "Source Sans Pro", Helvetica, sans-serif; font-weight: 600; line-height: 1.2; letter-spacing: normal; @@ -66,17 +77,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -93,7 +109,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -103,9 +122,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -116,7 +132,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -135,16 +152,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -154,25 +170,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -189,9 +211,9 @@ body { .reveal a { color: #42affa; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { color: #8dcffc; @@ -200,7 +222,7 @@ body { .reveal .roll span:after { color: #fff; - background: #068ee9; } + background: #068de9; } /********************************************* * IMAGES @@ -211,10 +233,14 @@ body { border: 4px solid #fff; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -224,44 +250,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #42affa; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #42affa; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #42affa; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #42affa; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #8dcffc; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #8dcffc; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #8dcffc; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #8dcffc; } +.reveal .controls { + color: #42affa; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #42affa; } .reveal .progress span { - background: #42affa; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #42affa; } +@media print { + .backgrounds { + background-color: #222; } } diff --git a/css/theme/blood.css b/css/theme/blood.css index 952fdf2..15e6c20 100644 --- a/css/theme/blood.css +++ b/css/theme/blood.css @@ -1,4 +1,3 @@ -@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic); /** * Blood theme for reveal.js * Author: Walther http://github.com/Walther @@ -10,6 +9,7 @@ * For other themes, change $codeBackground accordingly. * */ +@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic); /********************************************* * GLOBAL STYLES *********************************************/ @@ -18,8 +18,8 @@ body { background-color: #222; } .reveal { - font-family: Ubuntu, 'sans-serif'; - font-size: 36px; + font-family: Ubuntu, "sans-serif"; + font-size: 40px; font-weight: normal; color: #eee; } @@ -28,17 +28,28 @@ body { background: #a23; text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: #a23; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #eee; - font-family: Ubuntu, 'sans-serif'; + font-family: Ubuntu, "sans-serif"; font-weight: normal; line-height: 1.2; letter-spacing: normal; @@ -69,17 +80,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -96,7 +112,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -106,9 +125,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -119,7 +135,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -138,16 +155,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -157,25 +173,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -192,18 +214,18 @@ body { .reveal a { color: #a23; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { - color: #dd5567; + color: #dd5566; text-shadow: none; border: none; } .reveal .roll span:after { color: #fff; - background: #6a1521; } + background: #6a1520; } /********************************************* * IMAGES @@ -214,10 +236,14 @@ body { border: 4px solid #eee; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -227,53 +253,38 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #a23; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #a23; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #a23; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #a23; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #dd5567; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #dd5567; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #dd5567; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #dd5567; } +.reveal .controls { + color: #a23; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #a23; } .reveal .progress span { - background: #a23; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #a23; } +@media print { + .backgrounds { + background-color: #222; } } .reveal p { font-weight: 300; text-shadow: 1px 1px #222; } -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { font-weight: 700; } .reveal p code { diff --git a/css/theme/league.css b/css/theme/league.css index 41967d2..9dfa2ce 100644 --- a/css/theme/league.css +++ b/css/theme/league.css @@ -1,5 +1,3 @@ -@import url(../../lib/font/league-gothic/league-gothic.css); -@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); /** * League theme for reveal.js. * @@ -7,6 +5,8 @@ * * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); /********************************************* * GLOBAL STYLES *********************************************/ @@ -21,8 +21,8 @@ body { background-color: #2b2b2b; } .reveal { - font-family: 'Lato', sans-serif; - font-size: 36px; + font-family: "Lato", sans-serif; + font-size: 40px; font-weight: normal; color: #eee; } @@ -31,17 +31,28 @@ body { background: #FF5E99; text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: #FF5E99; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #eee; - font-family: 'League Gothic', Impact, sans-serif; + font-family: "League Gothic", Impact, sans-serif; font-weight: normal; line-height: 1.2; letter-spacing: normal; @@ -72,17 +83,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -99,7 +115,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -109,9 +128,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -122,7 +138,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -141,16 +158,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -160,25 +176,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -195,18 +217,18 @@ body { .reveal a { color: #13DAEC; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { - color: #71ebf4; + color: #71e9f4; text-shadow: none; border: none; } .reveal .roll span:after { color: #fff; - background: #0d9ba5; } + background: #0d99a5; } /********************************************* * IMAGES @@ -217,10 +239,14 @@ body { border: 4px solid #eee; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -230,44 +256,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #13DAEC; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #13DAEC; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #13DAEC; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #13DAEC; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #71ebf4; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #71ebf4; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #71ebf4; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #71ebf4; } +.reveal .controls { + color: #13DAEC; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #13DAEC; } .reveal .progress span { - background: #13DAEC; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #13DAEC; } +@media print { + .backgrounds { + background-color: #2b2b2b; } } diff --git a/css/theme/moon.css b/css/theme/moon.css index ac93638..52b3f67 100644 --- a/css/theme/moon.css +++ b/css/theme/moon.css @@ -1,9 +1,9 @@ -@import url(../../lib/font/league-gothic/league-gothic.css); -@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); /** * Solarized Dark theme for reveal.js. * Author: Achim Staebler */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); /** * Solarized colors by Ethan Schoonover */ @@ -19,8 +19,8 @@ body { background-color: #002b36; } .reveal { - font-family: 'Lato', sans-serif; - font-size: 36px; + font-family: "Lato", sans-serif; + font-size: 40px; font-weight: normal; color: #93a1a1; } @@ -29,17 +29,28 @@ body { background: #d33682; text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #eee8d5; - font-family: 'League Gothic', Impact, sans-serif; + font-family: "League Gothic", Impact, sans-serif; font-weight: normal; line-height: 1.2; letter-spacing: normal; @@ -70,17 +81,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -97,7 +113,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -107,9 +126,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -120,7 +136,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -139,16 +156,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -158,25 +174,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -193,18 +215,18 @@ body { .reveal a { color: #268bd2; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { - color: #78bae6; + color: #78b9e6; text-shadow: none; border: none; } .reveal .roll span:after { color: #fff; - background: #1a6291; } + background: #1a6091; } /********************************************* * IMAGES @@ -215,10 +237,14 @@ body { border: 4px solid #93a1a1; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -228,44 +254,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #268bd2; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #268bd2; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #268bd2; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #268bd2; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #78bae6; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #78bae6; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #78bae6; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #78bae6; } +.reveal .controls { + color: #268bd2; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #268bd2; } .reveal .progress span { - background: #268bd2; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #268bd2; } +@media print { + .backgrounds { + background-color: #002b36; } } diff --git a/css/theme/night.css b/css/theme/night.css index 6a5ed31..51a3dd3 100644 --- a/css/theme/night.css +++ b/css/theme/night.css @@ -1,10 +1,10 @@ -@import url(https://fonts.googleapis.com/css?family=Montserrat:700); -@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic); /** * Black theme for reveal.js. * * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se */ +@import url(https://fonts.googleapis.com/css?family=Montserrat:700); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic); /********************************************* * GLOBAL STYLES *********************************************/ @@ -13,8 +13,8 @@ body { background-color: #111; } .reveal { - font-family: 'Open Sans', sans-serif; - font-size: 30px; + font-family: "Open Sans", sans-serif; + font-size: 40px; font-weight: normal; color: #eee; } @@ -23,17 +23,28 @@ body { background: #e7ad52; text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: #e7ad52; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #eee; - font-family: 'Montserrat', Impact, sans-serif; + font-family: "Montserrat", Impact, sans-serif; font-weight: normal; line-height: 1.2; letter-spacing: -0.03em; @@ -64,17 +75,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -91,7 +107,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -101,9 +120,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -114,7 +130,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -133,16 +150,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -152,25 +168,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -187,9 +209,9 @@ body { .reveal a { color: #e7ad52; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { color: #f3d7ac; @@ -198,7 +220,7 @@ body { .reveal .roll span:after { color: #fff; - background: #d0881d; } + background: #d08a1d; } /********************************************* * IMAGES @@ -209,10 +231,14 @@ body { border: 4px solid #eee; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -222,44 +248,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #e7ad52; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #e7ad52; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #e7ad52; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #e7ad52; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #f3d7ac; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #f3d7ac; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #f3d7ac; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #f3d7ac; } +.reveal .controls { + color: #e7ad52; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #e7ad52; } .reveal .progress span { - background: #e7ad52; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #e7ad52; } +@media print { + .backgrounds { + background-color: #111; } } diff --git a/css/theme/serif.css b/css/theme/serif.css index fc83e5d..ea01066 100644 --- a/css/theme/serif.css +++ b/css/theme/serif.css @@ -15,8 +15,8 @@ body { background-color: #F0F1EB; } .reveal { - font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; - font-size: 36px; + font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif; + font-size: 40px; font-weight: normal; color: #000; } @@ -25,17 +25,28 @@ body { background: #26351C; text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: #26351C; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #383D3D; - font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; + font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif; font-weight: normal; line-height: 1.2; letter-spacing: normal; @@ -66,17 +77,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -93,7 +109,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -103,9 +122,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -116,7 +132,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -135,16 +152,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -154,25 +170,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -189,12 +211,12 @@ body { .reveal a { color: #51483D; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { - color: #8b7b69; + color: #8b7c69; text-shadow: none; border: none; } @@ -211,10 +233,14 @@ body { border: 4px solid #000; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -224,44 +250,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #51483D; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #51483D; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #51483D; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #51483D; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #8b7b69; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #8b7b69; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #8b7b69; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #8b7b69; } +.reveal .controls { + color: #51483D; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #51483D; } .reveal .progress span { - background: #51483D; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #51483D; } +@media print { + .backgrounds { + background-color: #F0F1EB; } } diff --git a/css/theme/simple.css b/css/theme/simple.css index ea08a27..8432d84 100644 --- a/css/theme/simple.css +++ b/css/theme/simple.css @@ -1,5 +1,3 @@ -@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700); -@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); /** * A simple theme for reveal.js presentations, similar * to the default theme. The accent color is darkblue. @@ -7,6 +5,11 @@ * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed. * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se */ +@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { + color: #fff; } + /********************************************* * GLOBAL STYLES *********************************************/ @@ -15,8 +18,8 @@ body { background-color: #fff; } .reveal { - font-family: 'Lato', sans-serif; - font-size: 36px; + font-family: "Lato", sans-serif; + font-size: 40px; font-weight: normal; color: #000; } @@ -25,17 +28,28 @@ body { background: rgba(0, 0, 0, 0.99); text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: rgba(0, 0, 0, 0.99); + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #000; - font-family: 'News Cycle', Impact, sans-serif; + font-family: "News Cycle", Impact, sans-serif; font-weight: normal; line-height: 1.2; letter-spacing: normal; @@ -66,17 +80,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -93,7 +112,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -103,9 +125,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -116,7 +135,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -135,16 +155,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -154,25 +173,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -189,9 +214,9 @@ body { .reveal a { color: #00008B; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { color: #0000f1; @@ -211,10 +236,14 @@ body { border: 4px solid #000; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -224,44 +253,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #00008B; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #00008B; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #00008B; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #00008B; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #0000f1; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #0000f1; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #0000f1; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #0000f1; } +.reveal .controls { + color: #00008B; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #00008B; } .reveal .progress span { - background: #00008B; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #00008B; } +@media print { + .backgrounds { + background-color: #fff; } } diff --git a/css/theme/sky.css b/css/theme/sky.css index 83842c4..6f60a1d 100644 --- a/css/theme/sky.css +++ b/css/theme/sky.css @@ -1,10 +1,10 @@ -@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic); -@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); /** * Sky theme for reveal.js. * * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se */ +@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); .reveal a { line-height: 1.3em; } @@ -22,8 +22,8 @@ body { background-color: #f7fbfc; } .reveal { - font-family: 'Open Sans', sans-serif; - font-size: 36px; + font-family: "Open Sans", sans-serif; + font-size: 40px; font-weight: normal; color: #333; } @@ -32,17 +32,28 @@ body { background: #134674; text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: #134674; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #333; - font-family: 'Quicksand', sans-serif; + font-family: "Quicksand", sans-serif; font-weight: normal; line-height: 1.2; letter-spacing: -0.08em; @@ -73,17 +84,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -100,7 +116,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -110,9 +129,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -123,7 +139,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -142,16 +159,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -161,25 +177,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -196,18 +218,18 @@ body { .reveal a { color: #3b759e; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { - color: #74a8cb; + color: #74a7cb; text-shadow: none; border: none; } .reveal .roll span:after { color: #fff; - background: #264d66; } + background: #264c66; } /********************************************* * IMAGES @@ -218,10 +240,14 @@ body { border: 4px solid #333; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -231,44 +257,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #3b759e; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #3b759e; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #3b759e; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #3b759e; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #74a8cb; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #74a8cb; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #74a8cb; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #74a8cb; } +.reveal .controls { + color: #3b759e; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #3b759e; } .reveal .progress span { - background: #3b759e; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #3b759e; } +@media print { + .backgrounds { + background-color: #f7fbfc; } } diff --git a/css/theme/solarized.css b/css/theme/solarized.css index 649f7a9..fe81f09 100644 --- a/css/theme/solarized.css +++ b/css/theme/solarized.css @@ -1,9 +1,9 @@ -@import url(../../lib/font/league-gothic/league-gothic.css); -@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); /** * Solarized Light theme for reveal.js. * Author: Achim Staebler */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); /** * Solarized colors by Ethan Schoonover */ @@ -19,8 +19,8 @@ body { background-color: #fdf6e3; } .reveal { - font-family: 'Lato', sans-serif; - font-size: 36px; + font-family: "Lato", sans-serif; + font-size: 40px; font-weight: normal; color: #657b83; } @@ -29,17 +29,28 @@ body { background: #d33682; text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #586e75; - font-family: 'League Gothic', Impact, sans-serif; + font-family: "League Gothic", Impact, sans-serif; font-weight: normal; line-height: 1.2; letter-spacing: normal; @@ -70,17 +81,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -97,7 +113,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -107,9 +126,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -120,7 +136,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -139,16 +156,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -158,25 +174,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -193,18 +215,18 @@ body { .reveal a { color: #268bd2; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { - color: #78bae6; + color: #78b9e6; text-shadow: none; border: none; } .reveal .roll span:after { color: #fff; - background: #1a6291; } + background: #1a6091; } /********************************************* * IMAGES @@ -215,10 +237,14 @@ body { border: 4px solid #657b83; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -228,44 +254,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #268bd2; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #268bd2; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #268bd2; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #268bd2; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #78bae6; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #78bae6; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #78bae6; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #78bae6; } +.reveal .controls { + color: #268bd2; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #268bd2; } .reveal .progress span { - background: #268bd2; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #268bd2; } +@media print { + .backgrounds { + background-color: #fdf6e3; } } diff --git a/css/theme/source/black.scss b/css/theme/source/black.scss index 73dfecb..84e8d9a 100644 --- a/css/theme/source/black.scss +++ b/css/theme/source/black.scss @@ -1,7 +1,7 @@ /** * Black theme for reveal.js. This is the opposite of the 'white' theme. * - * Copyright (C) 2015 Hakim El Hattab, http://hakim.se + * By Hakim El Hattab, http://hakim.se */ @@ -21,7 +21,7 @@ $backgroundColor: #222; $mainColor: #fff; $headingColor: #fff; -$mainFontSize: 38px; +$mainFontSize: 42px; $mainFont: 'Source Sans Pro', Helvetica, sans-serif; $headingFont: 'Source Sans Pro', Helvetica, sans-serif; $headingTextShadow: none; diff --git a/css/theme/source/blood.scss b/css/theme/source/blood.scss index d22b53d..4533fc0 100644 --- a/css/theme/source/blood.scss +++ b/css/theme/source/blood.scss @@ -28,7 +28,6 @@ $backgroundColor: $coal; // Main text $mainFont: Ubuntu, 'sans-serif'; -$mainFontSize: 36px; $mainColor: #eee; // Headings diff --git a/css/theme/source/night.scss b/css/theme/source/night.scss index b0cb57f..d49a282 100644 --- a/css/theme/source/night.scss +++ b/css/theme/source/night.scss @@ -27,7 +27,6 @@ $headingTextShadow: none; $headingLetterSpacing: -0.03em; $headingTextTransform: none; $selectionBackgroundColor: #e7ad52; -$mainFontSize: 30px; // Theme template ------------------------------ diff --git a/css/theme/source/simple.scss b/css/theme/source/simple.scss index 84c7d9b..394c9cd 100644 --- a/css/theme/source/simple.scss +++ b/css/theme/source/simple.scss @@ -31,6 +31,11 @@ $linkColor: #00008B; $linkColorHover: lighten( $linkColor, 20% ); $selectionBackgroundColor: rgba(0, 0, 0, 0.99); +section.has-dark-background { + &, h1, h2, h3, h4, h5, h6 { + color: #fff; + } +} // Theme template ------------------------------ diff --git a/css/theme/source/white.scss b/css/theme/source/white.scss index 4c5b647..7f06ffd 100644 --- a/css/theme/source/white.scss +++ b/css/theme/source/white.scss @@ -1,7 +1,7 @@ /** * White theme for reveal.js. This is the opposite of the 'black' theme. * - * Copyright (C) 2015 Hakim El Hattab, http://hakim.se + * By Hakim El Hattab, http://hakim.se */ @@ -21,7 +21,7 @@ $backgroundColor: #fff; $mainColor: #222; $headingColor: #222; -$mainFontSize: 38px; +$mainFontSize: 42px; $mainFont: 'Source Sans Pro', Helvetica, sans-serif; $headingFont: 'Source Sans Pro', Helvetica, sans-serif; $headingTextShadow: none; diff --git a/css/theme/template/settings.scss b/css/theme/template/settings.scss index ffaac23..63c02cf 100644 --- a/css/theme/template/settings.scss +++ b/css/theme/template/settings.scss @@ -6,7 +6,7 @@ $backgroundColor: #2b2b2b; // Primary/body text $mainFont: 'Lato', sans-serif; -$mainFontSize: 36px; +$mainFontSize: 40px; $mainColor: #eee; // Vertical spacing between blocks of text diff --git a/css/theme/template/theme.scss b/css/theme/template/theme.scss index bd89d31..a8f142d 100644 --- a/css/theme/template/theme.scss +++ b/css/theme/template/theme.scss @@ -22,8 +22,14 @@ body { text-shadow: none; } -.reveal .slides>section, -.reveal .slides>section>section { +::-moz-selection { + color: $selectionColor; + background: $selectionBackgroundColor; + text-shadow: none; +} + +.reveal .slides section, +.reveal .slides section>section { line-height: 1.3; font-weight: inherit; } @@ -128,11 +134,6 @@ body { margin-left: 40px; } -.reveal q, -.reveal blockquote { - quotes: none; -} - .reveal blockquote { display: block; position: relative; @@ -168,8 +169,10 @@ body { box-shadow: 0px 0px 6px rgba(0,0,0,0.3); } + .reveal code { font-family: monospace; + text-transform: none; } .reveal pre code { @@ -178,8 +181,6 @@ body { overflow: auto; max-height: 400px; word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } .reveal table { @@ -209,15 +210,18 @@ body { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { vertical-align: super; + font-size: smaller; } .reveal sub { vertical-align: sub; + font-size: smaller; } .reveal small { @@ -269,6 +273,11 @@ body { box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + .reveal section img.plain { + border: 0; + box-shadow: none; + } + .reveal a img { -webkit-transition: all .15s linear; -moz-transition: all .15s linear; @@ -287,40 +296,8 @@ body { * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, -.reveal .controls div.navigate-left.enabled { - border-right-color: $linkColor; -} - -.reveal .controls div.navigate-right, -.reveal .controls div.navigate-right.enabled { - border-left-color: $linkColor; -} - -.reveal .controls div.navigate-up, -.reveal .controls div.navigate-up.enabled { - border-bottom-color: $linkColor; -} - -.reveal .controls div.navigate-down, -.reveal .controls div.navigate-down.enabled { - border-top-color: $linkColor; -} - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: $linkColorHover; -} - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: $linkColorHover; -} - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: $linkColorHover; -} - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: $linkColorHover; +.reveal .controls { + color: $linkColor; } @@ -330,20 +307,19 @@ body { .reveal .progress { background: rgba(0,0,0,0.2); + color: $linkColor; } .reveal .progress span { - background: $linkColor; - -webkit-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); -moz-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); - transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: $linkColor; + @media print { + .backgrounds { + background-color: $backgroundColor; + } } - - diff --git a/css/theme/white.css b/css/theme/white.css index c77d5ab..27e44a1 100644 --- a/css/theme/white.css +++ b/css/theme/white.css @@ -1,9 +1,9 @@ -@import url(../../lib/font/source-sans-pro/source-sans-pro.css); /** * White theme for reveal.js. This is the opposite of the 'black' theme. * - * Copyright (C) 2015 Hakim El Hattab, http://hakim.se + * By Hakim El Hattab, http://hakim.se */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { color: #fff; } @@ -15,8 +15,8 @@ body { background-color: #fff; } .reveal { - font-family: 'Source Sans Pro', Helvetica, sans-serif; - font-size: 38px; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 42px; font-weight: normal; color: #222; } @@ -25,17 +25,28 @@ body { background: #98bdef; text-shadow: none; } -.reveal .slides > section, .reveal .slides > section > section { +::-moz-selection { + color: #fff; + background: #98bdef; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { line-height: 1.3; font-weight: inherit; } /********************************************* * HEADERS *********************************************/ -.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { margin: 0 0 20px 0; color: #222; - font-family: 'Source Sans Pro', Helvetica, sans-serif; + font-family: "Source Sans Pro", Helvetica, sans-serif; font-weight: 600; line-height: 1.2; letter-spacing: normal; @@ -66,17 +77,22 @@ body { line-height: 1.3; } /* Ensure certain elements are never larger than the slide itself */ -.reveal img, .reveal video, .reveal iframe { +.reveal img, +.reveal video, +.reveal iframe { max-width: 95%; max-height: 95%; } -.reveal strong, .reveal b { +.reveal strong, +.reveal b { font-weight: bold; } .reveal em { font-style: italic; } -.reveal ol, .reveal dl, .reveal ul { +.reveal ol, +.reveal dl, +.reveal ul { display: inline-block; text-align: left; margin: 0 0 0 1em; } @@ -93,7 +109,10 @@ body { .reveal ul ul ul { list-style-type: circle; } -.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul { +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { display: block; margin-left: 40px; } @@ -103,9 +122,6 @@ body { .reveal dd { margin-left: 40px; } -.reveal q, .reveal blockquote { - quotes: none; } - .reveal blockquote { display: block; position: relative; @@ -116,7 +132,8 @@ body { background: rgba(255, 255, 255, 0.05); box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } -.reveal blockquote p:first-child, .reveal blockquote p:last-child { +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { display: inline-block; } .reveal q { @@ -135,16 +152,15 @@ body { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } .reveal code { - font-family: monospace; } + font-family: monospace; + text-transform: none; } .reveal pre code { display: block; padding: 5px; overflow: auto; max-height: 400px; - word-wrap: normal; - background: #3F3F3F; - color: #DCDCDC; } + word-wrap: normal; } .reveal table { margin: auto; @@ -154,25 +170,31 @@ body { .reveal table th { font-weight: bold; } -.reveal table th, .reveal table td { +.reveal table th, +.reveal table td { text-align: left; padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } -.reveal table th[align="center"], .reveal table td[align="center"] { +.reveal table th[align="center"], +.reveal table td[align="center"] { text-align: center; } -.reveal table th[align="right"], .reveal table td[align="right"] { +.reveal table th[align="right"], +.reveal table td[align="right"] { text-align: right; } -.reveal table tr:last-child td { +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { border-bottom: none; } .reveal sup { - vertical-align: super; } + vertical-align: super; + font-size: smaller; } .reveal sub { - vertical-align: sub; } + vertical-align: sub; + font-size: smaller; } .reveal small { display: inline-block; @@ -189,18 +211,18 @@ body { .reveal a { color: #2a76dd; text-decoration: none; - -webkit-transition: color 0.15s ease; - -moz-transition: color 0.15s ease; - transition: color 0.15s ease; } + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } .reveal a:hover { - color: #6ca2e8; + color: #6ca0e8; text-shadow: none; border: none; } .reveal .roll span:after { color: #fff; - background: #1a54a1; } + background: #1a53a1; } /********************************************* * IMAGES @@ -211,10 +233,14 @@ body { border: 4px solid #222; box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } +.reveal section img.plain { + border: 0; + box-shadow: none; } + .reveal a img { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - transition: all 0.15s linear; } + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } .reveal a:hover img { background: rgba(255, 255, 255, 0.2); @@ -224,44 +250,24 @@ body { /********************************************* * NAVIGATION CONTROLS *********************************************/ -.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled { - border-right-color: #2a76dd; } - -.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled { - border-left-color: #2a76dd; } - -.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled { - border-bottom-color: #2a76dd; } - -.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled { - border-top-color: #2a76dd; } - -.reveal .controls div.navigate-left.enabled:hover { - border-right-color: #6ca2e8; } - -.reveal .controls div.navigate-right.enabled:hover { - border-left-color: #6ca2e8; } - -.reveal .controls div.navigate-up.enabled:hover { - border-bottom-color: #6ca2e8; } - -.reveal .controls div.navigate-down.enabled:hover { - border-top-color: #6ca2e8; } +.reveal .controls { + color: #2a76dd; } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - background: rgba(0, 0, 0, 0.2); } + background: rgba(0, 0, 0, 0.2); + color: #2a76dd; } .reveal .progress span { - background: #2a76dd; -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* - * SLIDE NUMBER + * PRINT BACKGROUND *********************************************/ -.reveal .slide-number { - color: #2a76dd; } +@media print { + .backgrounds { + background-color: #fff; } } diff --git a/index.html b/index.html index 303caa4..a7b9d25 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ JS, ES6, lodash, ... - + @@ -214,7 +214,7 @@

Les tableaux en ES6

let arr1 = ['one', 'two'], arr2 = ['three', 'four']; arr1.push(...arr2) // => 4 arr1 // => ['one', 'two', 'three', 'four'] -//le map +//le map arr1.map(element => console.log(element)) // for…in itère sur LES PROPRIÉTÉS ÉNUMÉRABLES de N’IMPORTE QUEL OBJET var arr = ['hello', 'world', , 'cool']; @@ -282,16 +282,16 @@

Quelques pièges de comparaisons en JS ...

== ou === ?! -42 == '42' // => true -- -null == undefined // => true -- -null == 0 // => false -- -0 == undefined // => false -- -0 == false // => true -- -1 == true // => true -- -42 == true // => false -- -'0' == false // => true -- -'' == false // => true -- -NaN == NaN // => false -- +42 == '42' // => true -- +null == undefined // => true -- +null == 0 // => false -- +0 == undefined // => false -- +0 == false // => true -- +1 == true // => true -- +42 == true // => false -- +'0' == false // => true -- +'' == false // => true -- +NaN == NaN // => false -- @@ -641,7 +641,7 @@

Le problème

let obj = { name: 'Joe Lopez', greet: function greet(whom) { - console.log(this) + console.log(this) console.log(this.name + ' salue ' + whom); }, greetAll: function greetAll(first, second, last) { @@ -940,17 +940,5 @@

- - diff --git a/js/reveal.js b/js/reveal.js index ff5ea53..eaa9d60 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -1,9 +1,9 @@ /*! * reveal.js - * http://lab.hakim.se/reveal-js + * http://revealjs.com * MIT licensed * - * Copyright (C) 2015 Hakim El Hattab, http://hakim.se + * Copyright (C) 2018 Hakim El Hattab, http://hakim.se */ (function( root, factory ) { if( typeof define === 'function' && define.amd ) { @@ -25,10 +25,14 @@ var Reveal; + // The reveal.js version + var VERSION = '3.7.0'; + var SLIDES_SELECTOR = '.slides section', HORIZONTAL_SLIDES_SELECTOR = '.slides>section', VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section', HOME_SLIDE_SELECTOR = '.slides>section:first-of-type', + UA = navigator.userAgent, // Configuration defaults, can be overridden at initialization time config = { @@ -39,21 +43,39 @@ height: 700, // Factor of the display size that should remain empty around the content - margin: 0.1, + margin: 0.04, // Bounds for smallest/largest possible scale to apply to content minScale: 0.2, - maxScale: 1.5, + maxScale: 2.0, - // Display controls in the bottom right corner + // Display presentation control arrows controls: true, + // Help the user learn the controls by providing hints, for example by + // bouncing the down arrow when they first encounter a vertical slide + controlsTutorial: true, + + // Determines where controls appear, "edges" or "bottom-right" + controlsLayout: 'bottom-right', + + // Visibility rule for backwards navigation arrows; "faded", "hidden" + // or "visible" + controlsBackArrows: 'faded', + // Display a presentation progress bar progress: true, // Display the page number of the current slide slideNumber: false, + // Use 1 based indexing for # links to match slide number (default is zero + // based) + hashOneBasedIndex: false, + + // Determine which displays to show the slide number on + showSlideNumber: 'all', + // Push each slide change to the browser history history: false, @@ -66,6 +88,10 @@ // Enable the slide overview mode overview: true, + // Disables the default reveal.js slide layout so that you can use + // custom CSS layout + disableLayout: false, + // Vertical centering of slides center: true, @@ -78,28 +104,54 @@ // Change the presentation direction to be RTL rtl: false, + // Randomizes the order of slides each time the presentation loads + shuffle: false, + // Turns fragments on and off globally fragments: true, + // Flags whether to include the current fragment in the URL, + // so that reloading brings you to the same fragment position + fragmentInURL: false, + // Flags if the presentation is running in an embedded mode, // i.e. contained within a limited portion of the screen embedded: false, - // Flags if we should show a help overlay when the questionmark + // Flags if we should show a help overlay when the question-mark // key is pressed help: true, // Flags if it should be possible to pause the presentation (blackout) pause: true, - // Number of milliseconds between automatically proceeding to the - // next slide, disabled when set to 0, this value can be overwritten - // by using a data-autoslide attribute on your slides + // Flags if speaker notes should be visible to all viewers + showNotes: false, + + // Global override for autolaying embedded media (video/audio/iframe) + // - null: Media will only autoplay if data-autoplay is present + // - true: All media will autoplay, regardless of individual setting + // - false: No media will autoplay, regardless of individual setting + autoPlayMedia: null, + + // Controls automatic progression to the next slide + // - 0: Auto-sliding only happens if the data-autoslide HTML attribute + // is present on the current slide or fragment + // - 1+: All slides will progress automatically at the given interval + // - false: No auto-sliding, even if data-autoslide is present autoSlide: 0, // Stop auto-sliding after user input autoSlideStoppable: true, + // Use this method for navigation when auto-sliding (defaults to navigateNext) + autoSlideMethod: null, + + // Specify the average time in seconds that you think you will spend + // presenting each slide. This is used to show a pacing timer in the + // speaker view + defaultTiming: null, + // Enable slide navigation via mouse wheel mouseWheel: false, @@ -110,6 +162,8 @@ hideAddressBar: true, // Opens links in an iframe preview overlay + // Add `data-preview-link` and `data-preview-link="false"` to customise each link + // individually previewLinks: false, // Exposes the reveal.js API through window.postMessage @@ -118,7 +172,7 @@ // Dispatches all reveal.js events to the parent window through postMessage postMessageEvents: false, - // Focuses body when page changes visiblity to ensure keyboard shortcuts work + // Focuses body when page changes visibility to ensure keyboard shortcuts work focusBodyOnPageVisibilityChange: true, // Transition style @@ -136,24 +190,54 @@ // Parallax background size parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px" + // Parallax background repeat + parallaxBackgroundRepeat: '', // repeat/repeat-x/repeat-y/no-repeat/initial/inherit + + // Parallax background position + parallaxBackgroundPosition: '', // CSS syntax, e.g. "top left" + // Amount of pixels to move the parallax background per slide step parallaxBackgroundHorizontal: null, parallaxBackgroundVertical: null, + // The maximum number of pages a single slide can expand onto when printing + // to PDF, unlimited by default + pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY, + + // Prints each fragment on a separate slide + pdfSeparateFragments: true, + + // Offset used to reduce the height of content within exported PDF pages. + // This exists to account for environment differences based on how you + // print to PDF. CLI printing options, like phantomjs and wkpdf, can end + // on precisely the total height of the document whereas in-browser + // printing has to end one pixel before. + pdfPageHeightOffset: -1, + // Number of slides away from the current that are visible viewDistance: 3, + // The display mode that will be used to show slides + display: 'block', + // Script dependencies to load dependencies: [] }, + // Flags if Reveal.initialize() has been called + initialized = false, + // Flags if reveal.js is loaded (has dispatched the 'ready' event) loaded = false, // Flags if the overview mode is currently active overview = false, + // Holds the dimensions of our overview slides, including margins + overviewSlideWidth = null, + overviewSlideHeight = null, + // The horizontal and vertical index of the currently active slide indexh, indexv, @@ -164,6 +248,10 @@ previousBackground, + // Remember which directions that the user has navigated towards + hasNavigatedRight = false, + hasNavigatedDown = false, + // Slides may hold a data-state attribute which we pick up and apply // as a class to the body. This list contains the combined state of // all current slides. @@ -185,6 +273,9 @@ // Client is a mobile device, see #checkCapabilities() isMobileDevice, + // Client is a desktop Chrome, see #checkCapabilities() + isChrome, + // Throttles mouse wheel navigation lastMouseWheelStep = 0, @@ -226,13 +317,21 @@ 'B , .': 'Pause', 'F': 'Fullscreen', 'ESC, O': 'Slide overview' - }; + }, + + // Holds custom key code mappings + registeredKeyBindings = {}; /** * Starts up the presentation if the client is capable. */ function initialize( options ) { + // Make sure we only initialize once + if( initialized === true ) return; + + initialized = true; + checkCapabilities(); if( !features.transforms2d && !features.transforms3d ) { @@ -289,40 +388,47 @@ */ function checkCapabilities() { - features.transforms3d = 'WebkitPerspective' in document.body.style || - 'MozPerspective' in document.body.style || - 'msPerspective' in document.body.style || - 'OPerspective' in document.body.style || - 'perspective' in document.body.style; + isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( UA ); + isChrome = /chrome/i.test( UA ) && !/edge/i.test( UA ); + + var testElement = document.createElement( 'div' ); - features.transforms2d = 'WebkitTransform' in document.body.style || - 'MozTransform' in document.body.style || - 'msTransform' in document.body.style || - 'OTransform' in document.body.style || - 'transform' in document.body.style; + features.transforms3d = 'WebkitPerspective' in testElement.style || + 'MozPerspective' in testElement.style || + 'msPerspective' in testElement.style || + 'OPerspective' in testElement.style || + 'perspective' in testElement.style; + + features.transforms2d = 'WebkitTransform' in testElement.style || + 'MozTransform' in testElement.style || + 'msTransform' in testElement.style || + 'OTransform' in testElement.style || + 'transform' in testElement.style; features.requestAnimationFrameMethod = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; features.requestAnimationFrame = typeof features.requestAnimationFrameMethod === 'function'; features.canvas = !!document.createElement( 'canvas' ).getContext; - features.touch = !!( 'ontouchstart' in window ); - // Transitions in the overview are disabled in desktop and - // mobile Safari due to lag - features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( navigator.userAgent ); + // Safari due to lag + features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( UA ); - isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( navigator.userAgent ); + // Flags if we should use zoom instead of transform to scale + // up slides. Zoom produces crisper results but has a lot of + // xbrowser quirks so we only use it in whitelsited browsers. + features.zoom = 'zoom' in testElement.style && !isMobileDevice && + ( isChrome || /Version\/[\d\.]+.*Safari/.test( UA ) ); } - /** - * Loads the dependencies of reveal.js. Dependencies are - * defined via the configuration option 'dependencies' - * and will be loaded prior to starting/binding reveal.js. - * Some dependencies may have an 'async' flag, if so they - * will load after reveal.js has been started up. - */ + /** + * Loads the dependencies of reveal.js. Dependencies are + * defined via the configuration option 'dependencies' + * and will be loaded prior to starting/binding reveal.js. + * Some dependencies may have an 'async' flag, if so they + * will load after reveal.js has been started up. + */ function load() { var scripts = [], @@ -340,7 +446,7 @@ } function loadScript( s ) { - head.ready( s.src.match( /([\w\d_\-]*)\.?js$|[^\\\/]*$/i )[0], function() { + head.ready( s.src.match( /([\w\d_\-]*)\.?js(\?[\w\d.=&]*)?$|[^\\\/]*$/i )[0], function() { // Extension may contain callback functions if( typeof s.callback === 'function' ) { s.callback.apply( this ); @@ -386,14 +492,16 @@ */ function start() { + loaded = true; + // Make sure we've got all the DOM elements we need setupDOM(); // Listen to messages posted to this window setupPostMessage(); - // Prevent iframes from scrolling the slides out of view - setupIframeScrollPrevention(); + // Prevent the slides from being scrolled out of view + setupScrollPrevention(); // Resets all vertical slides so that only the first is visible resetVerticalSlides(); @@ -413,7 +521,7 @@ // Enable transitions now that we're loaded dom.slides.classList.remove( 'no-transition' ); - loaded = true; + dom.wrapper.classList.add( 'ready' ); dispatchEvent( 'ready', { 'indexh': indexh, @@ -448,6 +556,20 @@ // Prevent transitions while we're loading dom.slides.classList.add( 'no-transition' ); + if( isMobileDevice ) { + dom.wrapper.classList.add( 'no-hover' ); + } + else { + dom.wrapper.classList.remove( 'no-hover' ); + } + + if( /iphone/gi.test( UA ) ) { + dom.wrapper.classList.add( 'ua-iphone' ); + } + else { + dom.wrapper.classList.remove( 'ua-iphone' ); + } + // Background element dom.background = createSingletonNode( dom.wrapper, 'div', 'backgrounds', null ); @@ -456,21 +578,23 @@ dom.progressbar = dom.progress.querySelector( 'span' ); // Arrow controls - createSingletonNode( dom.wrapper, 'aside', 'controls', - '' + - '' + - '' + - '' ); + dom.controls = createSingletonNode( dom.wrapper, 'aside', 'controls', + '' + + '' + + '' + + '' ); // Slide number dom.slideNumber = createSingletonNode( dom.wrapper, 'div', 'slide-number', '' ); - // Overlay graphic which is displayed during the paused mode - createSingletonNode( dom.wrapper, 'div', 'pause-overlay', null ); + // Element containing notes that are visible to the audience + dom.speakerNotes = createSingletonNode( dom.wrapper, 'div', 'speaker-notes', null ); + dom.speakerNotes.setAttribute( 'data-prevent-swipe', '' ); + dom.speakerNotes.setAttribute( 'tabindex', '0' ); - // Cache references to elements - dom.controls = document.querySelector( '.reveal .controls' ); - dom.theme = document.querySelector( '#theme' ); + // Overlay graphic which is displayed during the paused mode + dom.pauseOverlay = createSingletonNode( dom.wrapper, 'div', 'pause-overlay', '' ); + dom.resumeButton = dom.pauseOverlay.querySelector( '.resume-button' ); dom.wrapper.setAttribute( 'role', 'application' ); @@ -482,6 +606,10 @@ dom.controlsPrev = toArray( document.querySelectorAll( '.navigate-prev' ) ); dom.controlsNext = toArray( document.querySelectorAll( '.navigate-next' ) ); + // The right and down arrows in the standard reveal.js controls + dom.controlsRightArrow = dom.controls.querySelector( '.navigate-right' ); + dom.controlsDownArrow = dom.controls.querySelector( '.navigate-down' ); + dom.statusDiv = createStatusDiv(); } @@ -489,6 +617,8 @@ * Creates a hidden div with role aria-live to announce the * current slide content. Hide the div off-screen to make it * available only to Assistive Technologies. + * + * @return {HTMLElement} */ function createStatusDiv() { @@ -498,7 +628,7 @@ statusDiv.style.position = 'absolute'; statusDiv.style.height = '1px'; statusDiv.style.width = '1px'; - statusDiv.style.overflow ='hidden'; + statusDiv.style.overflow = 'hidden'; statusDiv.style.clip = 'rect( 1px, 1px, 1px, 1px )'; statusDiv.setAttribute( 'id', 'aria-status-div' ); statusDiv.setAttribute( 'aria-live', 'polite' ); @@ -509,6 +639,38 @@ } + /** + * Converts the given HTML element into a string of text + * that can be announced to a screen reader. Hidden + * elements are excluded. + */ + function getStatusText( node ) { + + var text = ''; + + // Text node + if( node.nodeType === 3 ) { + text += node.textContent; + } + // Element node + else if( node.nodeType === 1 ) { + + var isAriaHidden = node.getAttribute( 'aria-hidden' ); + var isDisplayHidden = window.getComputedStyle( node )['display'] === 'none'; + if( isAriaHidden !== 'true' && !isDisplayHidden ) { + + toArray( node.childNodes ).forEach( function( child ) { + text += getStatusText( child ); + } ); + + } + + } + + return text; + + } + /** * Configures the presentation for printing to a static * PDF. @@ -519,14 +681,14 @@ // Dimensions of the PDF pages var pageWidth = Math.floor( slideSize.width * ( 1 + config.margin ) ), - pageHeight = Math.floor( slideSize.height * ( 1 + config.margin ) ); + pageHeight = Math.floor( slideSize.height * ( 1 + config.margin ) ); // Dimensions of slides within the pages var slideWidth = slideSize.width, slideHeight = slideSize.height; // Let the browser know what page size we want to print - injectStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0;}' ); + injectStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0px;}' ); // Limit the size of certain elements to the dimensions of the slide injectStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' ); @@ -535,6 +697,22 @@ document.body.style.width = pageWidth + 'px'; document.body.style.height = pageHeight + 'px'; + // Make sure stretch elements fit on slide + layoutSlideContents( slideWidth, slideHeight ); + + // Add each slide's index as attributes on itself, we need these + // indices to generate slide numbers below + toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { + hslide.setAttribute( 'data-index-h', h ); + + if( hslide.classList.contains( 'stack' ) ) { + toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) { + vslide.setAttribute( 'data-index-h', h ); + vslide.setAttribute( 'data-index-v', v ); + } ); + } + } ); + // Slide and slide background layout toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { @@ -545,56 +723,150 @@ var left = ( pageWidth - slideWidth ) / 2, top = ( pageHeight - slideHeight ) / 2; - var contentHeight = getAbsoluteHeight( slide ); + var contentHeight = slide.scrollHeight; var numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 ); + // Adhere to configured pages per slide limit + numberOfPages = Math.min( numberOfPages, config.pdfMaxPagesPerSlide ); + // Center slides vertically if( numberOfPages === 1 && config.center || slide.classList.contains( 'center' ) ) { top = Math.max( ( pageHeight - contentHeight ) / 2, 0 ); } + // Wrap the slide in a page element and hide its overflow + // so that no page ever flows onto another + var page = document.createElement( 'div' ); + page.className = 'pdf-page'; + page.style.height = ( ( pageHeight + config.pdfPageHeightOffset ) * numberOfPages ) + 'px'; + slide.parentNode.insertBefore( page, slide ); + page.appendChild( slide ); + // Position the slide inside of the page slide.style.left = left + 'px'; slide.style.top = top + 'px'; slide.style.width = slideWidth + 'px'; - // TODO Backgrounds need to be multiplied when the slide - // stretches over multiple pages - var background = slide.querySelector( '.slide-background' ); - if( background ) { - background.style.width = pageWidth + 'px'; - background.style.height = ( pageHeight * numberOfPages ) + 'px'; - background.style.top = -top + 'px'; - background.style.left = -left + 'px'; + if( slide.slideBackgroundElement ) { + page.insertBefore( slide.slideBackgroundElement, slide ); + } + + // Inject notes if `showNotes` is enabled + if( config.showNotes ) { + + // Are there notes for this slide? + var notes = getSlideNotes( slide ); + if( notes ) { + + var notesSpacing = 8; + var notesLayout = typeof config.showNotes === 'string' ? config.showNotes : 'inline'; + var notesElement = document.createElement( 'div' ); + notesElement.classList.add( 'speaker-notes' ); + notesElement.classList.add( 'speaker-notes-pdf' ); + notesElement.setAttribute( 'data-layout', notesLayout ); + notesElement.innerHTML = notes; + + if( notesLayout === 'separate-page' ) { + page.parentNode.insertBefore( notesElement, page.nextSibling ); + } + else { + notesElement.style.left = notesSpacing + 'px'; + notesElement.style.bottom = notesSpacing + 'px'; + notesElement.style.width = ( pageWidth - notesSpacing*2 ) + 'px'; + page.appendChild( notesElement ); + } + + } + + } + + // Inject slide numbers if `slideNumbers` are enabled + if( config.slideNumber && /all|print/i.test( config.showSlideNumber ) ) { + var slideNumberH = parseInt( slide.getAttribute( 'data-index-h' ), 10 ) + 1, + slideNumberV = parseInt( slide.getAttribute( 'data-index-v' ), 10 ) + 1; + + var numberElement = document.createElement( 'div' ); + numberElement.classList.add( 'slide-number' ); + numberElement.classList.add( 'slide-number-pdf' ); + numberElement.innerHTML = formatSlideNumber( slideNumberH, '.', slideNumberV ); + page.appendChild( numberElement ); + } + + // Copy page and show fragments one after another + if( config.pdfSeparateFragments ) { + + // Each fragment 'group' is an array containing one or more + // fragments. Multiple fragments that appear at the same time + // are part of the same group. + var fragmentGroups = sortFragments( page.querySelectorAll( '.fragment' ), true ); + + var previousFragmentStep; + var previousPage; + + fragmentGroups.forEach( function( fragments ) { + + // Remove 'current-fragment' from the previous group + if( previousFragmentStep ) { + previousFragmentStep.forEach( function( fragment ) { + fragment.classList.remove( 'current-fragment' ); + } ); + } + + // Show the fragments for the current index + fragments.forEach( function( fragment ) { + fragment.classList.add( 'visible', 'current-fragment' ); + } ); + + // Create a separate page for the current fragment state + var clonedPage = page.cloneNode( true ); + page.parentNode.insertBefore( clonedPage, ( previousPage || page ).nextSibling ); + + previousFragmentStep = fragments; + previousPage = clonedPage; + + } ); + + // Reset the first/original page so that all fragments are hidden + fragmentGroups.forEach( function( fragments ) { + fragments.forEach( function( fragment ) { + fragment.classList.remove( 'visible', 'current-fragment' ); + } ); + } ); + } + // Show all fragments + else { + toArray( page.querySelectorAll( '.fragment:not(.fade-out)' ) ).forEach( function( fragment ) { + fragment.classList.add( 'visible' ); + } ); + } + } } ); - // Show all fragments - toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' .fragment' ) ).forEach( function( fragment ) { - fragment.classList.add( 'visible' ); - } ); + // Notify subscribers that the PDF layout is good to go + dispatchEvent( 'pdf-ready' ); } /** - * This is an unfortunate necessity. Iframes can trigger the - * parent window to scroll, for example by focusing an input. + * This is an unfortunate necessity. Some actions – such as + * an input field being focused in an iframe or using the + * keyboard to expand text selection beyond the bounds of + * a slide – can trigger our content to be pushed out of view. * This scrolling can not be prevented by hiding overflow in - * CSS so we have to resort to repeatedly checking if the - * browser has decided to offset our slides :( + * CSS (we already do) so we have to resort to repeatedly + * checking if the slides have been offset :( */ - function setupIframeScrollPrevention() { + function setupScrollPrevention() { - if( dom.slides.querySelector( 'iframe' ) ) { - setInterval( function() { - if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) { - dom.wrapper.scrollTop = 0; - dom.wrapper.scrollLeft = 0; - } - }, 500 ); - } + setInterval( function() { + if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) { + dom.wrapper.scrollTop = 0; + dom.wrapper.scrollLeft = 0; + } + }, 1000 ); } @@ -602,6 +874,13 @@ * Creates an HTML element and returns a reference to it. * If the element already exists the existing instance will * be returned. + * + * @param {HTMLElement} container + * @param {string} tagname + * @param {string} classname + * @param {string} innerHTML + * + * @return {HTMLElement} */ function createSingletonNode( container, tagname, classname, innerHTML ) { @@ -619,7 +898,7 @@ // If no node was found, create it now var node = document.createElement( tagname ); - node.classList.add( classname ); + node.className = classname; if( typeof innerHTML === 'string' ) { node.innerHTML = innerHTML; } @@ -645,24 +924,12 @@ // Iterate over all horizontal slides toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( slideh ) { - var backgroundStack; - - if( printMode ) { - backgroundStack = createBackground( slideh, slideh ); - } - else { - backgroundStack = createBackground( slideh, dom.background ); - } + var backgroundStack = createBackground( slideh, dom.background ); // Iterate over all vertical slides toArray( slideh.querySelectorAll( 'section' ) ).forEach( function( slidev ) { - if( printMode ) { - createBackground( slidev, slidev ); - } - else { - createBackground( slidev, backgroundStack ); - } + createBackground( slidev, backgroundStack ); backgroundStack.classList.add( 'stack' ); @@ -675,6 +942,8 @@ dom.background.style.backgroundImage = 'url("' + config.parallaxBackgroundImage + '")'; dom.background.style.backgroundSize = config.parallaxBackgroundSize; + dom.background.style.backgroundRepeat = config.parallaxBackgroundRepeat; + dom.background.style.backgroundPosition = config.parallaxBackgroundPosition; // Make sure the below properties are set on the element - these properties are // needed for proper transitions to be set on the element via CSS. To remove @@ -700,9 +969,61 @@ * @param {HTMLElement} slide * @param {HTMLElement} container The element that the background * should be appended to + * @return {HTMLElement} New background div */ function createBackground( slide, container ) { + + // Main slide background element + var element = document.createElement( 'div' ); + element.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' ); + + // Inner background element that wraps images/videos/iframes + var contentElement = document.createElement( 'div' ); + contentElement.className = 'slide-background-content'; + + element.appendChild( contentElement ); + container.appendChild( element ); + + slide.slideBackgroundElement = element; + slide.slideBackgroundContentElement = contentElement; + + // Syncs the background to reflect all current background settings + syncBackground( slide ); + + return element; + + } + + /** + * Renders all of the visual properties of a slide background + * based on the various background attributes. + * + * @param {HTMLElement} slide + */ + function syncBackground( slide ) { + + var element = slide.slideBackgroundElement, + contentElement = slide.slideBackgroundContentElement; + + // Reset the prior background state in case this is not the + // initial sync + slide.classList.remove( 'has-dark-background' ); + slide.classList.remove( 'has-light-background' ); + + element.removeAttribute( 'data-loaded' ); + element.removeAttribute( 'data-background-hash' ); + element.removeAttribute( 'data-background-size' ); + element.removeAttribute( 'data-background-transition' ); + element.style.backgroundColor = ''; + + contentElement.style.backgroundSize = ''; + contentElement.style.backgroundRepeat = ''; + contentElement.style.backgroundPosition = ''; + contentElement.style.backgroundImage = ''; + contentElement.style.opacity = ''; + contentElement.innerHTML = ''; + var data = { background: slide.getAttribute( 'data-background' ), backgroundSize: slide.getAttribute( 'data-background-size' ), @@ -712,17 +1033,13 @@ backgroundColor: slide.getAttribute( 'data-background-color' ), backgroundRepeat: slide.getAttribute( 'data-background-repeat' ), backgroundPosition: slide.getAttribute( 'data-background-position' ), - backgroundTransition: slide.getAttribute( 'data-background-transition' ) + backgroundTransition: slide.getAttribute( 'data-background-transition' ), + backgroundOpacity: slide.getAttribute( 'data-background-opacity' ) }; - var element = document.createElement( 'div' ); - - // Carry over custom classes from the slide to the background - element.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' ); - if( data.background ) { // Auto-wrap image urls in url(...) - if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)$/gi.test( data.background ) ) { + if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#\s]|$)/gi.test( data.background ) ) { slide.setAttribute( 'data-background-image', data.background ); } else { @@ -742,34 +1059,33 @@ data.backgroundColor + data.backgroundRepeat + data.backgroundPosition + - data.backgroundTransition ); + data.backgroundTransition + + data.backgroundOpacity ); } // Additional and optional background properties - if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize; + if( data.backgroundSize ) element.setAttribute( 'data-background-size', data.backgroundSize ); if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor; - if( data.backgroundRepeat ) element.style.backgroundRepeat = data.backgroundRepeat; - if( data.backgroundPosition ) element.style.backgroundPosition = data.backgroundPosition; if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition ); - container.appendChild( element ); - - // If backgrounds are being recreated, clear old classes - slide.classList.remove( 'has-dark-background' ); - slide.classList.remove( 'has-light-background' ); + // Background image options are set on the content wrapper + if( data.backgroundSize ) contentElement.style.backgroundSize = data.backgroundSize; + if( data.backgroundRepeat ) contentElement.style.backgroundRepeat = data.backgroundRepeat; + if( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition; + if( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity; // If this slide has a background color, add a class that // signals if it is light or dark. If the slide has no background // color, no class will be set - var computedBackgroundColor = window.getComputedStyle( element ).backgroundColor; - if( computedBackgroundColor ) { - var rgb = colorToRgb( computedBackgroundColor ); + var computedBackgroundStyle = window.getComputedStyle( element ); + if( computedBackgroundStyle && computedBackgroundStyle.backgroundColor ) { + var rgb = colorToRgb( computedBackgroundStyle.backgroundColor ); // Ignore fully transparent backgrounds. Some browsers return // rgba(0,0,0,0) when reading the computed background color of // an element with no background if( rgb && rgb.a !== 0 ) { - if( colorBrightness( computedBackgroundColor ) < 128 ) { + if( colorBrightness( computedBackgroundStyle.backgroundColor ) < 128 ) { slide.classList.add( 'has-dark-background' ); } else { @@ -778,8 +1094,6 @@ } } - return element; - } /** @@ -815,17 +1129,27 @@ /** * Applies the configuration settings from the config * object. May be called multiple times. + * + * @param {object} options */ function configure( options ) { - var numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length; - - dom.wrapper.classList.remove( config.transition ); + var oldTransition = config.transition; // New config options may be passed when this method // is invoked through the API after initialization if( typeof options === 'object' ) extend( config, options ); + // Abort if reveal.js hasn't finished loading, config + // changes will be applied automatically once loading + // finishes + if( loaded === false ) return; + + var numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length; + + // Remove the previously configured transition class + dom.wrapper.classList.remove( oldTransition ); + // Force linear transition based on browser capabilities if( features.transforms3d === false ) config.transition = 'linear'; @@ -837,6 +1161,13 @@ dom.controls.style.display = config.controls ? 'block' : 'none'; dom.progress.style.display = config.progress ? 'block' : 'none'; + dom.controls.setAttribute( 'data-controls-layout', config.controlsLayout ); + dom.controls.setAttribute( 'data-controls-back-arrows', config.controlsBackArrows ); + + if( config.shuffle ) { + shuffle(); + } + if( config.rtl ) { dom.wrapper.classList.add( 'rtl' ); } @@ -856,6 +1187,10 @@ resume(); } + if( config.showNotes ) { + dom.speakerNotes.setAttribute( 'data-layout', typeof config.showNotes === 'string' ? config.showNotes : 'inline' ); + } + if( config.mouseWheel ) { document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF document.addEventListener( 'mousewheel', onDocumentMouseScroll, false ); @@ -876,10 +1211,11 @@ // Iframe link previews if( config.previewLinks ) { enablePreviewLinks(); + disablePreviewLinks( '[data-preview-link=false]' ); } else { disablePreviewLinks(); - enablePreviewLinks( '[data-preview-link]' ); + enablePreviewLinks( '[data-preview-link]:not([data-preview-link=false])' ); } // Remove existing auto-slide controls @@ -906,6 +1242,19 @@ } ); } + // Slide numbers + var slideNumberDisplay = 'none'; + if( config.slideNumber && !isPrintingPDF() ) { + if( config.showSlideNumber === 'all' ) { + slideNumberDisplay = 'block'; + } + else if( config.showSlideNumber === 'speaker' && isSpeakerNotes() ) { + slideNumberDisplay = 'block'; + } + } + + dom.slideNumber.style.display = slideNumberDisplay; + sync(); } @@ -921,13 +1270,8 @@ window.addEventListener( 'resize', onWindowResize, false ); if( config.touch ) { - dom.wrapper.addEventListener( 'touchstart', onTouchStart, false ); - dom.wrapper.addEventListener( 'touchmove', onTouchMove, false ); - dom.wrapper.addEventListener( 'touchend', onTouchEnd, false ); - - // Support pointer-style touch interaction as well - if( window.navigator.pointerEnabled ) { - // IE 11 uses un-prefixed version of pointer events + if( 'onpointerdown' in window ) { + // Use W3C pointer events dom.wrapper.addEventListener( 'pointerdown', onPointerDown, false ); dom.wrapper.addEventListener( 'pointermove', onPointerMove, false ); dom.wrapper.addEventListener( 'pointerup', onPointerUp, false ); @@ -938,6 +1282,12 @@ dom.wrapper.addEventListener( 'MSPointerMove', onPointerMove, false ); dom.wrapper.addEventListener( 'MSPointerUp', onPointerUp, false ); } + else { + // Fall back to touch events + dom.wrapper.addEventListener( 'touchstart', onTouchStart, false ); + dom.wrapper.addEventListener( 'touchmove', onTouchMove, false ); + dom.wrapper.addEventListener( 'touchend', onTouchEnd, false ); + } } if( config.keyboard ) { @@ -949,6 +1299,8 @@ dom.progress.addEventListener( 'click', onProgressClicked, false ); } + dom.resumeButton.addEventListener( 'click', resume, false ); + if( config.focusBodyOnPageVisibilityChange ) { var visibilityChange; @@ -973,7 +1325,7 @@ // Only support touch for Android, fixes double navigations in // stock browser - if( navigator.userAgent.match( /android/gi ) ) { + if( UA.match( /android/gi ) ) { pointerEvents = [ 'touchstart' ]; } @@ -1000,22 +1352,19 @@ window.removeEventListener( 'hashchange', onWindowHashChange, false ); window.removeEventListener( 'resize', onWindowResize, false ); + dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false ); + dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false ); + dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false ); + + dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false ); + dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false ); + dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false ); + dom.wrapper.removeEventListener( 'touchstart', onTouchStart, false ); dom.wrapper.removeEventListener( 'touchmove', onTouchMove, false ); dom.wrapper.removeEventListener( 'touchend', onTouchEnd, false ); - // IE11 - if( window.navigator.pointerEnabled ) { - dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false ); - dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false ); - dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false ); - } - // IE10 - else if( window.navigator.msPointerEnabled ) { - dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false ); - dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false ); - dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false ); - } + dom.resumeButton.removeEventListener( 'click', resume, false ); if ( config.progress && dom.progress ) { dom.progress.removeEventListener( 'click', onProgressClicked, false ); @@ -1032,9 +1381,44 @@ } + /** + * Add a custom key binding with optional description to + * be added to the help screen. + */ + function addKeyBinding( binding, callback ) { + + if( typeof binding === 'object' && binding.keyCode ) { + registeredKeyBindings[binding.keyCode] = { + callback: callback, + key: binding.key, + description: binding.description + }; + } + else { + registeredKeyBindings[binding] = { + callback: callback, + key: null, + description: null + }; + } + + } + + /** + * Removes the specified custom key binding. + */ + function removeKeyBinding( keyCode ) { + + delete registeredKeyBindings[keyCode]; + + } + /** * Extend object a with the properties of object b. * If there's a conflict, object b takes precedence. + * + * @param {object} a + * @param {object} b */ function extend( a, b ) { @@ -1042,10 +1426,15 @@ a[ i ] = b[ i ]; } + return a; + } /** * Converts the target object to an array. + * + * @param {object} o + * @return {object[]} */ function toArray( o ) { @@ -1055,6 +1444,9 @@ /** * Utility for deserializing a value. + * + * @param {*} value + * @return {*} */ function deserialize( value ) { @@ -1062,7 +1454,7 @@ if( value === 'null' ) return null; else if( value === 'true' ) return true; else if( value === 'false' ) return false; - else if( value.match( /^\d+$/ ) ) return parseFloat( value ); + else if( value.match( /^-?[\d\.]+$/ ) ) return parseFloat( value ); } return value; @@ -1073,8 +1465,10 @@ * Measures the distance in pixels between point a * and point b. * - * @param {Object} a point with x/y properties - * @param {Object} b point with x/y properties + * @param {object} a point with x/y properties + * @param {object} b point with x/y properties + * + * @return {number} */ function distanceBetween( a, b ) { @@ -1087,6 +1481,9 @@ /** * Applies a CSS transform to the target element. + * + * @param {HTMLElement} element + * @param {string} transform */ function transformElement( element, transform ) { @@ -1101,6 +1498,8 @@ * Applies CSS transforms to the slides container. The container * is transformed from two separate sources: layout and the overview * mode. + * + * @param {object} transforms */ function transformSlides( transforms ) { @@ -1120,6 +1519,8 @@ /** * Injects the given CSS styles into the DOM. + * + * @param {string} value */ function injectStyleSheet( value ) { @@ -1135,14 +1536,56 @@ } + /** + * Find the closest parent that matches the given + * selector. + * + * @param {HTMLElement} target The child element + * @param {String} selector The CSS selector to match + * the parents against + * + * @return {HTMLElement} The matched parent or null + * if no matching parent was found + */ + function closestParent( target, selector ) { + + var parent = target.parentNode; + + while( parent ) { + + // There's some overhead doing this each time, we don't + // want to rewrite the element prototype but should still + // be enough to feature detect once at startup... + var matchesMethod = parent.matches || parent.matchesSelector || parent.msMatchesSelector; + + // If we find a match, we're all set + if( matchesMethod && matchesMethod.call( parent, selector ) ) { + return parent; + } + + // Keep searching + parent = parent.parentNode; + + } + + return null; + + } + /** * Converts various color input formats to an {r:0,g:0,b:0} object. * - * @param {String} color The string representation of a color, - * the following formats are supported: - * - #000 - * - #000000 - * - rgb(0,0,0) + * @param {string} color The string representation of a color + * @example + * colorToRgb('#000'); + * @example + * colorToRgb('#000000'); + * @example + * colorToRgb('rgb(0,0,0)'); + * @example + * colorToRgb('rgba(0,0,0)'); + * + * @return {{r: number, g: number, b: number, [a]: number}|null} */ function colorToRgb( color ) { @@ -1192,7 +1635,8 @@ /** * Calculates brightness on a scale of 0-255. * - * @param color See colorStringToRgb for supported formats. + * @param {string} color See colorToRgb for supported formats. + * @see {@link colorToRgb} */ function colorBrightness( color ) { @@ -1206,46 +1650,14 @@ } - /** - * Retrieves the height of the given element by looking - * at the position and height of its immediate children. - */ - function getAbsoluteHeight( element ) { - - var height = 0; - - if( element ) { - var absoluteChildren = 0; - - toArray( element.childNodes ).forEach( function( child ) { - - if( typeof child.offsetTop === 'number' && child.style ) { - // Count # of abs children - if( window.getComputedStyle( child ).position === 'absolute' ) { - absoluteChildren += 1; - } - - height = Math.max( height, child.offsetTop + child.offsetHeight ); - } - - } ); - - // If there are no absolute children, use offsetHeight - if( absoluteChildren === 0 ) { - height = element.offsetHeight; - } - - } - - return height; - - } - /** * Returns the remaining height within the parent of the * target element. * * remaining height = [ configured parent height ] - [ current parent height ] + * + * @param {HTMLElement} element + * @param {number} [height] */ function getRemainingHeight( element, height ) { @@ -1278,6 +1690,15 @@ } + /** + * Check if this instance is being used to print a PDF with fragments. + */ + function isPrintingPDFFragments() { + + return ( /print-pdf-fragments/gi ).test( window.location.search ); + + } + /** * Hides the address bar if we're on a mobile device. */ @@ -1368,6 +1789,8 @@ /** * Bind preview frame links. + * + * @param {string} [selector=a] - selector for anchors */ function enablePreviewLinks( selector ) { @@ -1384,9 +1807,9 @@ /** * Unbind preview frame links. */ - function disablePreviewLinks() { + function disablePreviewLinks( selector ) { - var anchors = toArray( document.querySelectorAll( 'a' ) ); + var anchors = toArray( document.querySelectorAll( selector ? selector : 'a' ) ); anchors.forEach( function( element ) { if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) { @@ -1398,6 +1821,8 @@ /** * Opens a preview window for the target URL. + * + * @param {string} url - url for preview iframe src */ function showPreview( url ) { @@ -1416,6 +1841,9 @@ '
', '
', '', + '', + 'Unable to load iframe. This is likely due to the site\'s policy (x-frame-options).', + '', '
' ].join(''); @@ -1439,7 +1867,29 @@ } /** - * Opens a overlay window with help material. + * Open or close help overlay window. + * + * @param {Boolean} [override] Flag which overrides the + * toggle logic and forcibly sets the desired state. True means + * help is open, false means it's closed. + */ + function toggleHelp( override ){ + + if( typeof override === 'boolean' ) { + override ? showHelp() : closeOverlay(); + } + else { + if( dom.overlay ) { + closeOverlay(); + } + else { + showHelp(); + } + } + } + + /** + * Opens an overlay window with help material. */ function showHelp() { @@ -1459,6 +1909,13 @@ html += '' + key + '' + keyboardShortcuts[ key ] + ''; } + // Add custom key bindings that have associated descriptions + for( var binding in registeredKeyBindings ) { + if( registeredKeyBindings[binding].key && registeredKeyBindings[binding].description ) { + html += '' + registeredKeyBindings[binding].key + '' + registeredKeyBindings[binding].description + ''; + } + } + html += ''; dom.overlay.innerHTML = [ @@ -1503,71 +1960,80 @@ if( dom.wrapper && !isPrintingPDF() ) { - var size = getComputedSlideSize(); + if( !config.disableLayout ) { - var slidePadding = 20; // TODO Dig this out of DOM + var size = getComputedSlideSize(); - // Layout the contents of the slides - layoutSlideContents( config.width, config.height, slidePadding ); + // Layout the contents of the slides + layoutSlideContents( config.width, config.height ); - dom.slides.style.width = size.width + 'px'; - dom.slides.style.height = size.height + 'px'; + dom.slides.style.width = size.width + 'px'; + dom.slides.style.height = size.height + 'px'; - // Determine scale of content to fit within available space - scale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height ); + // Determine scale of content to fit within available space + scale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height ); - // Respect max/min scale settings - scale = Math.max( scale, config.minScale ); - scale = Math.min( scale, config.maxScale ); + // Respect max/min scale settings + scale = Math.max( scale, config.minScale ); + scale = Math.min( scale, config.maxScale ); - // Don't apply any scaling styles if scale is 1 - if( scale === 1 ) { - dom.slides.style.zoom = ''; - dom.slides.style.left = ''; - dom.slides.style.top = ''; - dom.slides.style.bottom = ''; - dom.slides.style.right = ''; - transformSlides( { layout: '' } ); - } - else { - // Prefer zooming in desktop Chrome so that content remains crisp - if( !isMobileDevice && /chrome/i.test( navigator.userAgent ) && typeof dom.slides.style.zoom !== 'undefined' ) { - dom.slides.style.zoom = scale; + // Don't apply any scaling styles if scale is 1 + if( scale === 1 ) { + dom.slides.style.zoom = ''; + dom.slides.style.left = ''; + dom.slides.style.top = ''; + dom.slides.style.bottom = ''; + dom.slides.style.right = ''; transformSlides( { layout: '' } ); } - // Apply scale transform as a fallback else { - dom.slides.style.left = '50%'; - dom.slides.style.top = '50%'; - dom.slides.style.bottom = 'auto'; - dom.slides.style.right = 'auto'; - transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } ); + // Prefer zoom for scaling up so that content remains crisp. + // Don't use zoom to scale down since that can lead to shifts + // in text layout/line breaks. + if( scale > 1 && features.zoom ) { + dom.slides.style.zoom = scale; + dom.slides.style.left = ''; + dom.slides.style.top = ''; + dom.slides.style.bottom = ''; + dom.slides.style.right = ''; + transformSlides( { layout: '' } ); + } + // Apply scale transform as a fallback + else { + dom.slides.style.zoom = ''; + dom.slides.style.left = '50%'; + dom.slides.style.top = '50%'; + dom.slides.style.bottom = 'auto'; + dom.slides.style.right = 'auto'; + transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } ); + } } - } - // Select all slides, vertical and horizontal - var slides = toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ); + // Select all slides, vertical and horizontal + var slides = toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ); - for( var i = 0, len = slides.length; i < len; i++ ) { - var slide = slides[ i ]; + for( var i = 0, len = slides.length; i < len; i++ ) { + var slide = slides[ i ]; - // Don't bother updating invisible slides - if( slide.style.display === 'none' ) { - continue; - } + // Don't bother updating invisible slides + if( slide.style.display === 'none' ) { + continue; + } - if( config.center || slide.classList.contains( 'center' ) ) { - // Vertical stacks are not centred since their section - // children will be - if( slide.classList.contains( 'stack' ) ) { - slide.style.top = 0; + if( config.center || slide.classList.contains( 'center' ) ) { + // Vertical stacks are not centred since their section + // children will be + if( slide.classList.contains( 'stack' ) ) { + slide.style.top = 0; + } + else { + slide.style.top = Math.max( ( size.height - slide.scrollHeight ) / 2, 0 ) + 'px'; + } } else { - slide.style.top = Math.max( ( ( size.height - getAbsoluteHeight( slide ) ) / 2 ) - slidePadding, 0 ) + 'px'; + slide.style.top = ''; } - } - else { - slide.style.top = ''; + } } @@ -1575,6 +2041,10 @@ updateProgress(); updateParallax(); + if( isOverview() ) { + updateOverview(); + } + } } @@ -1582,8 +2052,11 @@ /** * Applies layout logic to the contents of all slides in * the presentation. + * + * @param {string|number} width + * @param {string|number} height */ - function layoutSlideContents( width, height, padding ) { + function layoutSlideContents( width, height ) { // Handle sizing of elements with the 'stretch' class toArray( dom.slides.querySelectorAll( 'section > .stretch' ) ).forEach( function( element ) { @@ -1615,6 +2088,9 @@ * Calculates the computed pixel size of our slides. These * values are based on the width and height configuration * options. + * + * @param {number} [presentationWidth=dom.wrapper.offsetWidth] + * @param {number} [presentationHeight=dom.wrapper.offsetHeight] */ function getComputedSlideSize( presentationWidth, presentationHeight ) { @@ -1652,7 +2128,7 @@ * from the stack. * * @param {HTMLElement} stack The vertical stack element - * @param {int} v Index to memorize + * @param {string|number} [v=0] Index to memorize */ function setPreviousVerticalIndex( stack, v ) { @@ -1716,6 +2192,17 @@ } } ); + // Calculate slide sizes + var margin = 70; + var slideSize = getComputedSlideSize(); + overviewSlideWidth = slideSize.width + margin; + overviewSlideHeight = slideSize.height + margin; + + // Reverse in RTL mode + if( config.rtl ) { + overviewSlideWidth = -overviewSlideWidth; + } + updateSlidesVisibility(); layoutOverview(); updateOverview(); @@ -1739,19 +2226,10 @@ */ function layoutOverview() { - var margin = 70; - var slideWidth = config.width + margin, - slideHeight = config.height + margin; - - // Reverse in RTL mode - if( config.rtl ) { - slideWidth = -slideWidth; - } - // Layout slides toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { hslide.setAttribute( 'data-index-h', h ); - transformElement( hslide, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' ); + transformElement( hslide, 'translate3d(' + ( h * overviewSlideWidth ) + 'px, 0, 0)' ); if( hslide.classList.contains( 'stack' ) ) { @@ -1759,7 +2237,7 @@ vslide.setAttribute( 'data-index-h', h ); vslide.setAttribute( 'data-index-v', v ); - transformElement( vslide, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' ); + transformElement( vslide, 'translate3d(0, ' + ( v * overviewSlideHeight ) + 'px, 0)' ); } ); } @@ -1767,10 +2245,10 @@ // Layout slide backgrounds toArray( dom.background.childNodes ).forEach( function( hbackground, h ) { - transformElement( hbackground, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' ); + transformElement( hbackground, 'translate3d(' + ( h * overviewSlideWidth ) + 'px, 0, 0)' ); toArray( hbackground.querySelectorAll( '.slide-background' ) ).forEach( function( vbackground, v ) { - transformElement( vbackground, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' ); + transformElement( vbackground, 'translate3d(0, ' + ( v * overviewSlideHeight ) + 'px, 0)' ); } ); } ); @@ -1782,20 +2260,14 @@ */ function updateOverview() { - var margin = 70; - var slideWidth = config.width + margin, - slideHeight = config.height + margin; - - // Reverse in RTL mode - if( config.rtl ) { - slideWidth = -slideWidth; - } + var vmin = Math.min( window.innerWidth, window.innerHeight ); + var scale = Math.max( vmin / 5, 150 ) / vmin; transformSlides( { overview: [ - 'translateX('+ ( -indexh * slideWidth ) +'px)', - 'translateY('+ ( -indexv * slideHeight ) +'px)', - 'translateZ('+ ( window.innerWidth < 400 ? -1000 : -2500 ) +'px)' + 'scale('+ scale +')', + 'translateX('+ ( -indexh * overviewSlideWidth ) +'px)', + 'translateY('+ ( -indexv * overviewSlideHeight ) +'px)' ].join( ' ' ) } ); @@ -1860,7 +2332,7 @@ /** * Toggles the slide overview mode on and off. * - * @param {Boolean} override Optional flag which overrides the + * @param {Boolean} [override] Flag which overrides the * toggle logic and forcibly sets the desired state. True means * overview is open, false means it's closed. */ @@ -1887,12 +2359,48 @@ } + /** + * Return a hash URL that will resolve to the current slide location. + */ + function locationHash() { + + var url = '/'; + + // Attempt to create a named link based on the slide's ID + var id = currentSlide ? currentSlide.getAttribute( 'id' ) : null; + if( id ) { + id = encodeURIComponent( id ); + } + + var indexf; + if( config.fragmentInURL ) { + indexf = getIndices().f; + } + + // If the current slide has an ID, use that as a named link, + // but we don't support named links with a fragment index + if( typeof id === 'string' && id.length && indexf === undefined ) { + url = '/' + id; + } + // Otherwise use the /h/v index + else { + var hashIndexBase = config.hashOneBasedIndex ? 1 : 0; + if( indexh > 0 || indexv > 0 || indexf !== undefined ) url += indexh + hashIndexBase; + if( indexv > 0 || indexf !== undefined ) url += '/' + (indexv + hashIndexBase ); + if( indexf !== undefined ) url += '/' + indexf; + } + + return url; + + } + /** * Checks if the current or specified slide is vertical * (nested within another slide). * - * @param {HTMLElement} slide [optional] The slide to check + * @param {HTMLElement} [slide=currentSlide] The slide to check * orientation of + * @return {Boolean} */ function isVerticalSlide( slide ) { @@ -1911,10 +2419,10 @@ */ function enterFullscreen() { - var element = document.body; + var element = document.documentElement; // Check which implementation is available - var requestMethod = element.requestFullScreen || + var requestMethod = element.requestFullscreen || element.webkitRequestFullscreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || @@ -1977,6 +2485,8 @@ /** * Checks if we are currently in the paused mode. + * + * @return {Boolean} */ function isPaused() { @@ -1987,7 +2497,7 @@ /** * Toggles the auto slide mode on and off. * - * @param {Boolean} override Optional flag which sets the desired state. + * @param {Boolean} [override] Flag which sets the desired state. * True means autoplay starts, false means it stops. */ @@ -2005,6 +2515,8 @@ /** * Checks if the auto slide mode is currently on. + * + * @return {Boolean} */ function isAutoSliding() { @@ -2017,11 +2529,11 @@ * slide which matches the specified horizontal and vertical * indices. * - * @param {int} h Horizontal index of the target slide - * @param {int} v Vertical index of the target slide - * @param {int} f Optional index of a fragment within the + * @param {number} [h=indexh] Horizontal index of the target slide + * @param {number} [v=indexv] Vertical index of the target slide + * @param {number} [f] Index of a fragment within the * target slide to activate - * @param {int} o Optional origin for use in multimaster environments + * @param {number} [o] Origin for use in multimaster environments */ function slide( h, v, f, o ) { @@ -2031,6 +2543,9 @@ // Query all horizontal slides in the deck var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ); + // Abort if there are no slides + if( horizontalSlides.length === 0 ) return; + // If no vertical index is specified and the upcoming slide is a // stack, resume at its previous vertical index if( v === undefined && !isOverview() ) { @@ -2103,16 +2618,7 @@ // Dispatch an event if the slide changed var slideChanged = ( indexh !== indexhBefore || indexv !== indexvBefore ); - if( slideChanged ) { - dispatchEvent( 'slidechanged', { - 'indexh': indexh, - 'indexv': indexv, - 'previousSlide': previousSlide, - 'currentSlide': currentSlide, - 'origin': o - } ); - } - else { + if (!slideChanged) { // Ensure that the previous slide is never the same as the current previousSlide = null; } @@ -2120,7 +2626,7 @@ // Solves an edge case where the previous slide maintains the // 'present' class when navigating between adjacent vertical // stacks - if( previousSlide ) { + if( previousSlide && previousSlide !== currentSlide ) { previousSlide.classList.remove( 'present' ); previousSlide.setAttribute( 'aria-hidden', 'true' ); @@ -2140,6 +2646,16 @@ } } + if( slideChanged ) { + dispatchEvent( 'slidechanged', { + 'indexh': indexh, + 'indexv': indexv, + 'previousSlide': previousSlide, + 'currentSlide': currentSlide, + 'origin': o + } ); + } + // Handle embedded content if( slideChanged || !previousSlide ) { stopEmbeddedContent( previousSlide ); @@ -2147,13 +2663,14 @@ } // Announce the current slide contents, for screen readers - dom.statusDiv.textContent = currentSlide.textContent; + dom.statusDiv.textContent = getStatusText( currentSlide ); updateControls(); updateProgress(); updateBackground(); updateParallax(); updateSlideNumber(); + updateNotes(); // Update the URL hash writeURL(); @@ -2192,12 +2709,21 @@ updateControls(); updateProgress(); - updateBackground( true ); updateSlideNumber(); updateSlidesVisibility(); + updateBackground( true ); + updateNotesVisibility(); + updateNotes(); formatEmbeddedContent(); - startEmbeddedContent( currentSlide ); + + // Start or stop embedded content depending on global config + if( config.autoPlayMedia === false ) { + stopEmbeddedContent( currentSlide, { unloadIframes: false } ); + } + else { + startEmbeddedContent( currentSlide ); + } if( isOverview() ) { layoutOverview(); @@ -2205,6 +2731,41 @@ } + /** + * Updates reveal.js to keep in sync with new slide attributes. For + * example, if you add a new `data-background-image` you can call + * this to have reveal.js render the new background image. + * + * Similar to #sync() but more efficient when you only need to + * refresh a specific slide. + * + * @param {HTMLElement} slide + */ + function syncSlide( slide ) { + + syncBackground( slide ); + syncFragments( slide ); + + updateBackground(); + updateNotes(); + + loadSlide( slide ); + + } + + /** + * Formats the fragments on the given slide so that they have + * valid indices. Call this if fragments are changed in the DOM + * after reveal.js has already initialized. + * + * @param {HTMLElement} slide + */ + function syncFragments( slide ) { + + sortFragments( slide.querySelectorAll( '.fragment' ) ); + + } + /** * Resets all vertical slides so that only the first * is visible. @@ -2252,16 +2813,33 @@ } + /** + * Randomly shuffles all slides in the deck. + */ + function shuffle() { + + var slides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ); + + slides.forEach( function( slide ) { + + // Insert this slide next to another random slide. This may + // cause the slide to insert before itself but that's fine. + dom.slides.insertBefore( slide, slides[ Math.floor( Math.random() * slides.length ) ] ); + + } ); + + } + /** * Updates one dimension of slides by showing the slide * with the specified index. * - * @param {String} selector A CSS selector that will fetch + * @param {string} selector A CSS selector that will fetch * the group of slides we are working with - * @param {Number} index The index of the slide that should be + * @param {number} index The index of the slide that should be * shown * - * @return {Number} The index of the slide that is now shown, + * @return {number} The index of the slide that is now shown, * might differ from the passed in index if it was out of * bounds. */ @@ -2413,10 +2991,10 @@ // Show the horizontal slide if it's within the view distance if( distanceX < viewDistance ) { - showSlide( horizontalSlide ); + loadSlide( horizontalSlide ); } else { - hideSlide( horizontalSlide ); + unloadSlide( horizontalSlide ); } if( verticalSlidesLength ) { @@ -2428,18 +3006,77 @@ distanceY = x === ( indexh || 0 ) ? Math.abs( ( indexv || 0 ) - y ) : Math.abs( y - oy ); - if( distanceX + distanceY < viewDistance ) { - showSlide( verticalSlide ); - } - else { - hideSlide( verticalSlide ); - } - } + if( distanceX + distanceY < viewDistance ) { + loadSlide( verticalSlide ); + } + else { + unloadSlide( verticalSlide ); + } + } + + } + } + + // Flag if there are ANY vertical slides, anywhere in the deck + if( dom.wrapper.querySelectorAll( '.slides>section>section' ).length ) { + dom.wrapper.classList.add( 'has-vertical-slides' ); + } + else { + dom.wrapper.classList.remove( 'has-vertical-slides' ); + } + + // Flag if there are ANY horizontal slides, anywhere in the deck + if( dom.wrapper.querySelectorAll( '.slides>section' ).length > 1 ) { + dom.wrapper.classList.add( 'has-horizontal-slides' ); + } + else { + dom.wrapper.classList.remove( 'has-horizontal-slides' ); + } + + } + + } + + /** + * Pick up notes from the current slide and display them + * to the viewer. + * + * @see {@link config.showNotes} + */ + function updateNotes() { + + if( config.showNotes && dom.speakerNotes && currentSlide && !isPrintingPDF() ) { + + dom.speakerNotes.innerHTML = getSlideNotes() || 'No notes on this slide.'; + + } + + } + + /** + * Updates the visibility of the speaker notes sidebar that + * is used to share annotated slides. The notes sidebar is + * only visible if showNotes is true and there are notes on + * one or more slides in the deck. + */ + function updateNotesVisibility() { + + if( config.showNotes && hasNotes() ) { + dom.wrapper.classList.add( 'show-notes' ); + } + else { + dom.wrapper.classList.remove( 'show-notes' ); + } + + } - } - } + /** + * Checks if there are speaker notes for ANY slide in the + * presentation. + */ + function hasNotes() { - } + return dom.slides.querySelectorAll( '[data-notes], aside.notes' ).length > 0; } @@ -2457,33 +3094,79 @@ } + /** * Updates the slide number div to reflect the current slide. * - * Slide number format can be defined as a string using the - * following variables: - * h: current slide's horizontal index - * v: current slide's vertical index - * c: current slide index (flattened) - * t: total number of slides (flattened) + * The following slide number formats are available: + * "h.v": horizontal . vertical slide number (default) + * "h/v": horizontal / vertical slide number + * "c": flattened slide number + * "c/t": flattened slide number / total slides */ function updateSlideNumber() { // Update slide number if enabled - if( config.slideNumber && dom.slideNumber) { + if( config.slideNumber && dom.slideNumber ) { - // Default to only showing the current slide number - var format = 'c'; + var value = []; + var format = 'h.v'; - // Check if a custom slide number format is available + // Check if a custom number format is available if( typeof config.slideNumber === 'string' ) { format = config.slideNumber; } - dom.slideNumber.innerHTML = format.replace( /h/g, indexh ) - .replace( /v/g, indexv ) - .replace( /c/g, getSlidePastCount() + 1 ) - .replace( /t/g, getTotalSlides() ); + // If there are ONLY vertical slides in this deck, always use + // a flattened slide number + if( !/c/.test( format ) && dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ).length === 1 ) { + format = 'c'; + } + + switch( format ) { + case 'c': + value.push( getSlidePastCount() + 1 ); + break; + case 'c/t': + value.push( getSlidePastCount() + 1, '/', getTotalSlides() ); + break; + case 'h/v': + value.push( indexh + 1 ); + if( isVerticalSlide() ) value.push( '/', indexv + 1 ); + break; + default: + value.push( indexh + 1 ); + if( isVerticalSlide() ) value.push( '.', indexv + 1 ); + } + + dom.slideNumber.innerHTML = formatSlideNumber( value[0], value[1], value[2] ); + } + + } + + /** + * Applies HTML formatting to a slide number before it's + * written to the DOM. + * + * @param {number} a Current slide + * @param {string} delimiter Character to separate slide numbers + * @param {(number|*)} b Total slides + * @return {string} HTML string fragment + */ + function formatSlideNumber( a, delimiter, b ) { + + var url = '#' + locationHash(); + if( typeof b === 'number' && !isNaN( b ) ) { + return '
' + + ''+ a +'' + + ''+ delimiter +'' + + ''+ b +'' + + ''; + } + else { + return '' + + ''+ a +'' + + ''; } } @@ -2504,34 +3187,57 @@ .concat( dom.controlsNext ).forEach( function( node ) { node.classList.remove( 'enabled' ); node.classList.remove( 'fragmented' ); + + // Set 'disabled' attribute on all directions + node.setAttribute( 'disabled', 'disabled' ); } ); - // Add the 'enabled' class to the available routes - if( routes.left ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'enabled' ); } ); - if( routes.right ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'enabled' ); } ); - if( routes.up ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'enabled' ); } ); - if( routes.down ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'enabled' ); } ); + // Add the 'enabled' class to the available routes; remove 'disabled' attribute to enable buttons + if( routes.left ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.right ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.up ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.down ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); // Prev/next buttons - if( routes.left || routes.up ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'enabled' ); } ); - if( routes.right || routes.down ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'enabled' ); } ); + if( routes.left || routes.up ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.right || routes.down ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); // Highlight fragment directions if( currentSlide ) { // Always apply fragment decorator to prev/next buttons - if( fragments.prev ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); - if( fragments.next ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); + if( fragments.prev ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( fragments.next ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); // Apply fragment decorators to directional buttons based on // what slide axis they are in if( isVerticalSlide( currentSlide ) ) { - if( fragments.prev ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); - if( fragments.next ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); + if( fragments.prev ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( fragments.next ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + } + else { + if( fragments.prev ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( fragments.next ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + } + + } + + if( config.controlsTutorial ) { + + // Highlight control arrows with an animation to ensure + // that the viewer knows how to navigate + if( !hasNavigatedDown && routes.down ) { + dom.controlsDownArrow.classList.add( 'highlight' ); } else { - if( fragments.prev ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); - if( fragments.next ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); + dom.controlsDownArrow.classList.remove( 'highlight' ); + + if( !hasNavigatedRight && routes.right && indexv === 0 ) { + dom.controlsRightArrow.classList.add( 'highlight' ); + } + else { + dom.controlsRightArrow.classList.remove( 'highlight' ); + } } } @@ -2542,7 +3248,7 @@ * Updates the background elements to reflect the current * slide. * - * @param {Boolean} includeAll If true, the backgrounds of + * @param {boolean} includeAll If true, the backgrounds of * all vertical slides (not just the present) will be updated. */ function updateBackground( includeAll ) { @@ -2599,30 +3305,30 @@ } ); - // Stop any currently playing video background + // Stop content inside of previous backgrounds if( previousBackground ) { - var previousVideo = previousBackground.querySelector( 'video' ); - if( previousVideo ) previousVideo.pause(); + stopEmbeddedContent( previousBackground ); } + // Start content in the current background if( currentBackground ) { - // Start video playback - var currentVideo = currentBackground.querySelector( 'video' ); - if( currentVideo ) { - currentVideo.currentTime = 0; - currentVideo.play(); - } + startEmbeddedContent( currentBackground ); + + var currentBackgroundContent = currentBackground.querySelector( '.slide-background-content' ); + if( currentBackgroundContent ) { - var backgroundImageURL = currentBackground.style.backgroundImage || ''; + var backgroundImageURL = currentBackgroundContent.style.backgroundImage || ''; + + // Restart GIFs (doesn't work in Firefox) + if( /\.gif/i.test( backgroundImageURL ) ) { + currentBackgroundContent.style.backgroundImage = ''; + window.getComputedStyle( currentBackgroundContent ).opacity; + currentBackgroundContent.style.backgroundImage = backgroundImageURL; + } - // Restart GIFs (doesn't work in Firefox) - if( /\.gif/i.test( backgroundImageURL ) ) { - currentBackground.style.backgroundImage = ''; - window.getComputedStyle( currentBackground ).opacity; - currentBackground.style.backgroundImage = backgroundImageURL; } // Don't transition between identical backgrounds. This @@ -2688,7 +3394,7 @@ horizontalOffsetMultiplier = config.parallaxBackgroundHorizontal; } else { - horizontalOffsetMultiplier = ( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 ); + horizontalOffsetMultiplier = horizontalSlideCount > 1 ? ( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 ) : 0; } horizontalOffset = horizontalOffsetMultiplier * indexh * -1; @@ -2705,7 +3411,7 @@ verticalOffsetMultiplier = ( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 ); } - verticalOffset = verticalSlideCount > 0 ? verticalOffsetMultiplier * indexv * 1 : 0; + verticalOffset = verticalSlideCount > 0 ? verticalOffsetMultiplier * indexv : 0; dom.background.style.backgroundPosition = horizontalOffset + 'px ' + -verticalOffset + 'px'; @@ -2717,15 +3423,20 @@ * Called when the given slide is within the configured view * distance. Shows the slide element and loads any content * that is set to load lazily (data-src). + * + * @param {HTMLElement} slide Slide to show */ - function showSlide( slide ) { + function loadSlide( slide, options ) { + + options = options || {}; // Show the slide element - slide.style.display = 'block'; + slide.style.display = config.display; // Media elements with data-src attributes toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src]' ) ).forEach( function( element ) { element.setAttribute( 'src', element.getAttribute( 'data-src' ) ); + element.setAttribute( 'data-lazy-loaded', '' ); element.removeAttribute( 'data-src' ); } ); @@ -2736,6 +3447,7 @@ toArray( media.querySelectorAll( 'source[data-src]' ) ).forEach( function( source ) { source.setAttribute( 'src', source.getAttribute( 'data-src' ) ); source.removeAttribute( 'data-src' ); + source.setAttribute( 'data-lazy-loaded', '' ); sources += 1; } ); @@ -2748,11 +3460,12 @@ // Show the corresponding background element - var indices = getIndices( slide ); - var background = getSlideBackground( indices.h, indices.v ); + var background = slide.slideBackgroundElement; if( background ) { background.style.display = 'block'; + var backgroundContent = slide.slideBackgroundContentElement; + // If the background contains media, load it if( background.hasAttribute( 'data-loaded' ) === false ) { background.setAttribute( 'data-loaded', 'true' ); @@ -2760,11 +3473,12 @@ var backgroundImage = slide.getAttribute( 'data-background-image' ), backgroundVideo = slide.getAttribute( 'data-background-video' ), backgroundVideoLoop = slide.hasAttribute( 'data-background-video-loop' ), + backgroundVideoMuted = slide.hasAttribute( 'data-background-video-muted' ), backgroundIframe = slide.getAttribute( 'data-background-iframe' ); // Images if( backgroundImage ) { - background.style.backgroundImage = 'url('+ backgroundImage +')'; + backgroundContent.style.backgroundImage = 'url('+ encodeURI( backgroundImage ) +')'; } // Videos else if ( backgroundVideo && !isSpeakerNotes() ) { @@ -2774,51 +3488,90 @@ video.setAttribute( 'loop', '' ); } + if( backgroundVideoMuted ) { + video.muted = true; + } + + // Inline video playback works (at least in Mobile Safari) as + // long as the video is muted and the `playsinline` attribute is + // present + if( isMobileDevice ) { + video.muted = true; + video.autoplay = true; + video.setAttribute( 'playsinline', '' ); + } + // Support comma separated lists of video sources backgroundVideo.split( ',' ).forEach( function( source ) { video.innerHTML += ''; } ); - background.appendChild( video ); + backgroundContent.appendChild( video ); } // Iframes - else if( backgroundIframe ) { + else if( backgroundIframe && options.excludeIframes !== true ) { var iframe = document.createElement( 'iframe' ); + iframe.setAttribute( 'allowfullscreen', '' ); + iframe.setAttribute( 'mozallowfullscreen', '' ); + iframe.setAttribute( 'webkitallowfullscreen', '' ); + + // Only load autoplaying content when the slide is shown to + // avoid having it play in the background + if( /autoplay=(1|true|yes)/gi.test( backgroundIframe ) ) { + iframe.setAttribute( 'data-src', backgroundIframe ); + } + else { iframe.setAttribute( 'src', backgroundIframe ); - iframe.style.width = '100%'; - iframe.style.height = '100%'; - iframe.style.maxHeight = '100%'; - iframe.style.maxWidth = '100%'; + } - background.appendChild( iframe ); + iframe.style.width = '100%'; + iframe.style.height = '100%'; + iframe.style.maxHeight = '100%'; + iframe.style.maxWidth = '100%'; + + backgroundContent.appendChild( iframe ); } } + } } /** - * Called when the given slide is moved outside of the - * configured view distance. + * Unloads and hides the given slide. This is called when the + * slide is moved outside of the configured view distance. + * + * @param {HTMLElement} slide */ - function hideSlide( slide ) { + function unloadSlide( slide ) { // Hide the slide element slide.style.display = 'none'; // Hide the corresponding background element - var indices = getIndices( slide ); - var background = getSlideBackground( indices.h, indices.v ); + var background = getSlideBackground( slide ); if( background ) { background.style.display = 'none'; } + // Reset lazy-loaded media elements with src attributes + toArray( slide.querySelectorAll( 'video[data-lazy-loaded][src], audio[data-lazy-loaded][src]' ) ).forEach( function( element ) { + element.setAttribute( 'data-src', element.getAttribute( 'src' ) ); + element.removeAttribute( 'src' ); + } ); + + // Reset lazy-loaded media elements with children + toArray( slide.querySelectorAll( 'video[data-lazy-loaded] source[src], audio source[src]' ) ).forEach( function( source ) { + source.setAttribute( 'data-src', source.getAttribute( 'src' ) ); + source.removeAttribute( 'src' ); + } ); + } /** * Determine what available routes there are for navigation. * - * @return {Object} containing four booleans: left/right/up/down + * @return {{left: boolean, right: boolean, up: boolean, down: boolean}} */ function availableRoutes() { @@ -2826,13 +3579,27 @@ verticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR ); var routes = { - left: indexh > 0 || config.loop, - right: indexh < horizontalSlides.length - 1 || config.loop, + left: indexh > 0, + right: indexh < horizontalSlides.length - 1, up: indexv > 0, down: indexv < verticalSlides.length - 1 }; - // reverse horizontal controls for rtl + // Looped presentations can always be navigated as long as + // there are slides available + if( config.loop ) { + if( horizontalSlides.length > 1 ) { + routes.left = true; + routes.right = true; + } + + if( verticalSlides.length > 1 ) { + routes.up = true; + routes.down = true; + } + } + + // Reverse horizontal controls for rtl if( config.rtl ) { var left = routes.left; routes.left = routes.right; @@ -2847,7 +3614,7 @@ * Returns an object describing the available fragment * directions. * - * @return {Object} two boolean properties: prev/next + * @return {{prev: boolean, next: boolean}} */ function availableFragments() { @@ -2888,65 +3655,154 @@ _appendParamToIframeSource( 'src', 'player.vimeo.com/', 'api=1' ); _appendParamToIframeSource( 'data-src', 'player.vimeo.com/', 'api=1' ); + // Always show media controls on mobile devices + if( isMobileDevice ) { + toArray( dom.slides.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { + el.controls = true; + } ); + } + } /** * Start playback of any embedded content inside of - * the targeted slide. + * the given element. + * + * @param {HTMLElement} element */ - function startEmbeddedContent( slide ) { + function startEmbeddedContent( element ) { + + if( element && !isSpeakerNotes() ) { - if( slide && !isSpeakerNotes() ) { // Restart GIFs - toArray( slide.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) { + toArray( element.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) { // Setting the same unchanged source like this was confirmed // to work in Chrome, FF & Safari el.setAttribute( 'src', el.getAttribute( 'src' ) ); } ); // HTML5 media elements - toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { - if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) { - el.play(); + toArray( element.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { + if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { + return; + } + + // Prefer an explicit global autoplay setting + var autoplay = config.autoPlayMedia; + + // If no global setting is available, fall back on the element's + // own autoplay setting + if( typeof autoplay !== 'boolean' ) { + autoplay = el.hasAttribute( 'data-autoplay' ) || !!closestParent( el, '.slide-background' ); + } + + if( autoplay && typeof el.play === 'function' ) { + + // If the media is ready, start playback + if( el.readyState > 1 ) { + startEmbeddedMedia( { target: el } ); + } + // Mobile devices never fire a loaded event so instead + // of waiting, we initiate playback + else if( isMobileDevice ) { + el.play(); + } + // If the media isn't loaded, wait before playing + else { + el.removeEventListener( 'loadeddata', startEmbeddedMedia ); // remove first to avoid dupes + el.addEventListener( 'loadeddata', startEmbeddedMedia ); + } + } } ); // Normal iframes - toArray( slide.querySelectorAll( 'iframe[src]' ) ).forEach( function( el ) { + toArray( element.querySelectorAll( 'iframe[src]' ) ).forEach( function( el ) { + if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { + return; + } + startEmbeddedIframe( { target: el } ); } ); // Lazy loading iframes - toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { + toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { + if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { + return; + } + if( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) { el.removeEventListener( 'load', startEmbeddedIframe ); // remove first to avoid dupes el.addEventListener( 'load', startEmbeddedIframe ); el.setAttribute( 'src', el.getAttribute( 'data-src' ) ); } } ); + + } + + } + + /** + * Starts playing an embedded video/audio element after + * it has finished loading. + * + * @param {object} event + */ + function startEmbeddedMedia( event ) { + + var isAttachedToDOM = !!closestParent( event.target, 'html' ), + isVisible = !!closestParent( event.target, '.present' ); + + if( isAttachedToDOM && isVisible ) { + event.target.currentTime = 0; + event.target.play(); } + event.target.removeEventListener( 'loadeddata', startEmbeddedMedia ); + } /** * "Starts" the content of an embedded iframe using the - * postmessage API. + * postMessage API. + * + * @param {object} event */ function startEmbeddedIframe( event ) { var iframe = event.target; - // YouTube postMessage API - if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) { - iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' ); - } - // Vimeo postMessage API - else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) { - iframe.contentWindow.postMessage( '{"method":"play"}', '*' ); - } - // Generic postMessage API - else { - iframe.contentWindow.postMessage( 'slide:start', '*' ); + if( iframe && iframe.contentWindow ) { + + var isAttachedToDOM = !!closestParent( event.target, 'html' ), + isVisible = !!closestParent( event.target, '.present' ); + + if( isAttachedToDOM && isVisible ) { + + // Prefer an explicit global autoplay setting + var autoplay = config.autoPlayMedia; + + // If no global setting is available, fall back on the element's + // own autoplay setting + if( typeof autoplay !== 'boolean' ) { + autoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closestParent( iframe, '.slide-background' ); + } + + // YouTube postMessage API + if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) { + iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' ); + } + // Vimeo postMessage API + else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) { + iframe.contentWindow.postMessage( '{"method":"play"}', '*' ); + } + // Generic postMessage API + else { + iframe.contentWindow.postMessage( 'slide:start', '*' ); + } + + } + } } @@ -2954,44 +3810,54 @@ /** * Stop playback of any embedded content inside of * the targeted slide. + * + * @param {HTMLElement} element */ - function stopEmbeddedContent( slide ) { + function stopEmbeddedContent( element, options ) { + + options = extend( { + // Defaults + unloadIframes: true + }, options || {} ); - if( slide && slide.parentNode ) { + if( element && element.parentNode ) { // HTML5 media elements - toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { + toArray( element.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) { + el.setAttribute('data-paused-by-reveal', ''); el.pause(); } } ); // Generic postMessage API for non-lazy loaded iframes - toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) { - el.contentWindow.postMessage( 'slide:stop', '*' ); + toArray( element.querySelectorAll( 'iframe' ) ).forEach( function( el ) { + if( el.contentWindow ) el.contentWindow.postMessage( 'slide:stop', '*' ); el.removeEventListener( 'load', startEmbeddedIframe ); }); // YouTube postMessage API - toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) { - if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) { + toArray( element.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) { + if( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) { el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' ); } }); // Vimeo postMessage API - toArray( slide.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) { - if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) { + toArray( element.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) { + if( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) { el.contentWindow.postMessage( '{"method":"pause"}', '*' ); } }); - // Lazy loading iframes - toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { - // Only removing the src doesn't actually unload the frame - // in all browsers (Firefox) so we set it to blank first - el.setAttribute( 'src', 'about:blank' ); - el.removeAttribute( 'src' ); - } ); + if( options.unloadIframes === true ) { + // Unload lazy-loaded iframes + toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { + // Only removing the src doesn't actually unload the frame + // in all browsers (Firefox) so we set it to blank first + el.setAttribute( 'src', 'about:blank' ); + el.removeAttribute( 'src' ); + } ); + } } } @@ -2999,6 +3865,8 @@ /** * Returns the number of past slides. This can be used as a global * flattened index for slides. + * + * @return {number} Past slide count */ function getSlidePastCount() { @@ -3043,6 +3911,8 @@ /** * Returns a value ranging from 0-1 that represents * how far into the presentation we have navigated. + * + * @return {number} */ function getProgress() { @@ -3076,6 +3946,8 @@ /** * Checks if this presentation is running inside of the * speaker notes window. + * + * @return {boolean} */ function isSpeakerNotes() { @@ -3100,12 +3972,15 @@ var element; // Ensure the named link is a valid HTML ID attribute - if( /^[a-zA-Z][\w:.-]*$/.test( name ) ) { - // Find the slide with the specified ID - element = document.getElementById( name ); + try { + element = document.getElementById( decodeURIComponent( name ) ); } + catch ( error ) { } + + // Ensure that we're not already on a slide with the same name + var isSameNameAsCurrentSlide = currentSlide ? currentSlide.getAttribute( 'id' ) === name : false; - if( element ) { + if( element && !isSameNameAsCurrentSlide ) { // Find the position of the named slide and navigate to it var indices = Reveal.getIndices( element ); slide( indices.h, indices.v ); @@ -3116,12 +3991,22 @@ } } else { + var hashIndexBase = config.hashOneBasedIndex ? 1 : 0; + // Read the index components of the hash - var h = parseInt( bits[0], 10 ) || 0, - v = parseInt( bits[1], 10 ) || 0; + var h = ( parseInt( bits[0], 10 ) - hashIndexBase ) || 0, + v = ( parseInt( bits[1], 10 ) - hashIndexBase ) || 0, + f; + + if( config.fragmentInURL ) { + f = parseInt( bits[2], 10 ); + if( isNaN( f ) ) { + f = undefined; + } + } - if( h !== indexh || v !== indexv ) { - slide( h, v ); + if( h !== indexh || v !== indexv || f !== undefined ) { + slide( h, v, f ); } } @@ -3131,7 +4016,7 @@ * Updates the page URL (hash) to reflect the current * state. * - * @param {Number} delay The time in ms to wait before + * @param {number} delay The time in ms to wait before * writing the hash */ function writeURL( delay ) { @@ -3146,40 +4031,20 @@ writeURLTimeout = setTimeout( writeURL, delay ); } else if( currentSlide ) { - var url = '/'; - - // Attempt to create a named link based on the slide's ID - var id = currentSlide.getAttribute( 'id' ); - if( id ) { - id = id.toLowerCase(); - id = id.replace( /[^a-zA-Z0-9\-\_\:\.]/g, '' ); - } - - // If the current slide has an ID, use that as a named link - if( typeof id === 'string' && id.length ) { - url = '/' + id; - } - // Otherwise use the /h/v index - else { - if( indexh > 0 || indexv > 0 ) url += indexh; - if( indexv > 0 ) url += '/' + indexv; - } - - window.location.hash = url; + window.location.hash = locationHash(); } } } - /** - * Retrieves the h/v location of the current, or specified, - * slide. + * Retrieves the h/v location and fragment of the current, + * or specified, slide. * - * @param {HTMLElement} slide If specified, the returned + * @param {HTMLElement} [slide] If specified, the returned * index will be for this slide rather than the currently * active one * - * @return {Object} { h: , v: , f: } + * @return {{h: number, v: number, f: number}} */ function getIndices( slide ) { @@ -3225,17 +4090,30 @@ } + /** + * Retrieves all slides in this presentation. + */ + function getSlides() { + + return toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack)' )); + + } + /** * Retrieves the total number of slides in this presentation. + * + * @return {number} */ function getTotalSlides() { - return dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack)' ).length; + return getSlides().length; } /** * Returns the slide element matching the specified index. + * + * @return {HTMLElement} */ function getSlide( x, y ) { @@ -3255,31 +4133,49 @@ * All slides, even the ones with no background properties * defined, have a background element so as long as the * index is valid an element will be returned. + * + * @param {mixed} x Horizontal background index OR a slide + * HTML element + * @param {number} y Vertical background index + * @return {(HTMLElement[]|*)} */ function getSlideBackground( x, y ) { - // When printing to PDF the slide backgrounds are nested - // inside of the slides - if( isPrintingPDF() ) { - var slide = getSlide( x, y ); - if( slide ) { - var background = slide.querySelector( '.slide-background' ); - if( background && background.parentNode === slide ) { - return background; - } - } - - return undefined; + var slide = typeof x === 'number' ? getSlide( x, y ) : x; + if( slide ) { + return slide.slideBackgroundElement; } - var horizontalBackground = dom.wrapper.querySelectorAll( '.backgrounds>.slide-background' )[ x ]; - var verticalBackgrounds = horizontalBackground && horizontalBackground.querySelectorAll( '.slide-background' ); + return undefined; + + } + + /** + * Retrieves the speaker notes from a slide. Notes can be + * defined in two ways: + * 1. As a data-notes attribute on the slide
+ * 2. As an
+ +
+ +
+ diff --git a/plugin/markdown/example.md b/plugin/markdown/example.md index 6f6f577..89c7534 100644 --- a/plugin/markdown/example.md +++ b/plugin/markdown/example.md @@ -29,3 +29,8 @@ Content 3.1 ## External 3.2 Content 3.2 + + +## External 3.3 + +![External Image](https://s3.amazonaws.com/static.slid.es/logo/v2/slides-symbol-512x512.png) diff --git a/plugin/markdown/markdown.js b/plugin/markdown/markdown.js index 15e3b40..aa08ee5 100644 --- a/plugin/markdown/markdown.js +++ b/plugin/markdown/markdown.js @@ -4,33 +4,26 @@ * of external markdown documents. */ (function( root, factory ) { - if( typeof exports === 'object' ) { + if (typeof define === 'function' && define.amd) { + root.marked = require( './marked' ); + root.RevealMarkdown = factory( root.marked ); + root.RevealMarkdown.initialize(); + } else if( typeof exports === 'object' ) { module.exports = factory( require( './marked' ) ); - } - else { + } else { // Browser globals (root is window) root.RevealMarkdown = factory( root.marked ); root.RevealMarkdown.initialize(); } }( this, function( marked ) { - if( typeof marked === 'undefined' ) { - throw 'The reveal.js Markdown plugin requires marked to be loaded'; - } - - if( typeof hljs !== 'undefined' ) { - marked.setOptions({ - highlight: function( lang, code ) { - return hljs.highlightAuto( lang, code ).value; - } - }); - } - var DEFAULT_SLIDE_SEPARATOR = '^\r?\n---\r?\n$', - DEFAULT_NOTES_SEPARATOR = 'note:', + DEFAULT_NOTES_SEPARATOR = 'notes?:', DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$', DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$'; + var SCRIPT_END_PLACEHOLDER = '__SCRIPT_END__'; + /** * Retrieves the markdown contents of a slide section @@ -38,11 +31,15 @@ */ function getMarkdownFromSlide( section ) { - var template = section.querySelector( 'script' ); + // look for a ' ); + var leadingWs = text.match( /^\n?(\s*)/ )[1].length, leadingTabs = text.match( /^\n?(\t*)/ )[1].length; @@ -112,9 +109,13 @@ var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) ); if( notesMatch.length === 2 ) { - content = notesMatch[0] + ''; + content = notesMatch[0] + ''; } + // prevent script end tags in the content from interfering + // with parsing + content = content.replace( /<\/script>/g, SCRIPT_END_PLACEHOLDER ); + return ''; } @@ -177,7 +178,7 @@ markdownSections += '
'; sectionStack[i].forEach( function( child ) { - markdownSections += '
' + createMarkdownSlide( child, options ) + '
'; + markdownSections += '
' + createMarkdownSlide( child, options ) + '
'; } ); markdownSections += '
'; @@ -379,6 +380,24 @@ return { initialize: function() { + if( typeof marked === 'undefined' ) { + throw 'The reveal.js Markdown plugin requires marked to be loaded'; + } + + if( typeof hljs !== 'undefined' ) { + marked.setOptions({ + highlight: function( code, lang ) { + return hljs.highlightAuto( code, [lang] ).value; + } + }); + } + + var options = Reveal.getConfig().markdown; + + if ( options ) { + marked.setOptions( options ); + } + processSlides(); convertSlides(); }, diff --git a/plugin/markdown/marked.js b/plugin/markdown/marked.js index 70af29b..555c1dc 100644 --- a/plugin/markdown/marked.js +++ b/plugin/markdown/marked.js @@ -3,4 +3,4 @@ * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) * https://github.com/chjj/marked */ -(function(){function e(e){this.tokens=[],this.tokens.links={},this.options=e||a.defaults,this.rules=p.normal,this.options.gfm&&(this.rules=this.options.tables?p.tables:p.gfm)}function t(e,t){if(this.options=t||a.defaults,this.links=e,this.rules=u.normal,this.renderer=this.options.renderer||new n,this.renderer.options=this.options,!this.links)throw new Error("Tokens array requires a `links` property.");this.options.gfm?this.rules=this.options.breaks?u.breaks:u.gfm:this.options.pedantic&&(this.rules=u.pedantic)}function n(e){this.options=e||{}}function r(e){this.tokens=[],this.token=null,this.options=e||a.defaults,this.options.renderer=this.options.renderer||new n,this.renderer=this.options.renderer,this.renderer.options=this.options}function s(e,t){return e.replace(t?/&/g:/&(?!#?\w+;)/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function i(e){return e.replace(/&([#\w]+);/g,function(e,t){return t=t.toLowerCase(),"colon"===t?":":"#"===t.charAt(0)?String.fromCharCode("x"===t.charAt(1)?parseInt(t.substring(2),16):+t.substring(1)):""})}function l(e,t){return e=e.source,t=t||"",function n(r,s){return r?(s=s.source||s,s=s.replace(/(^|[^\[])\^/g,"$1"),e=e.replace(r,s),n):new RegExp(e,t)}}function o(){}function h(e){for(var t,n,r=1;rAn error occured:

"+s(c.message+"",!0)+"
";throw c}}var p={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:o,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:o,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:o,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};p.bullet=/(?:[*+-]|\d+\.)/,p.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,p.item=l(p.item,"gm")(/bull/g,p.bullet)(),p.list=l(p.list)(/bull/g,p.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+p.def.source+")")(),p.blockquote=l(p.blockquote)("def",p.def)(),p._tag="(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b",p.html=l(p.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,p._tag)(),p.paragraph=l(p.paragraph)("hr",p.hr)("heading",p.heading)("lheading",p.lheading)("blockquote",p.blockquote)("tag","<"+p._tag)("def",p.def)(),p.normal=h({},p),p.gfm=h({},p.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/}),p.gfm.paragraph=l(p.paragraph)("(?!","(?!"+p.gfm.fences.source.replace("\\1","\\2")+"|"+p.list.source.replace("\\1","\\3")+"|")(),p.tables=h({},p.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/}),e.rules=p,e.lex=function(t,n){var r=new e(n);return r.lex(t)},e.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},e.prototype.token=function(e,t,n){for(var r,s,i,l,o,h,a,u,c,e=e.replace(/^ +$/gm,"");e;)if((i=this.rules.newline.exec(e))&&(e=e.substring(i[0].length),i[0].length>1&&this.tokens.push({type:"space"})),i=this.rules.code.exec(e))e=e.substring(i[0].length),i=i[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",text:this.options.pedantic?i:i.replace(/\n+$/,"")});else if(i=this.rules.fences.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"code",lang:i[2],text:i[3]});else if(i=this.rules.heading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"heading",depth:i[1].length,text:i[2]});else if(t&&(i=this.rules.nptable.exec(e))){for(e=e.substring(i[0].length),h={type:"table",header:i[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3].replace(/\n$/,"").split("\n")},u=0;u ?/gm,""),this.token(i,t,!0),this.tokens.push({type:"blockquote_end"});else if(i=this.rules.list.exec(e)){for(e=e.substring(i[0].length),l=i[2],this.tokens.push({type:"list_start",ordered:l.length>1}),i=i[0].match(this.rules.item),r=!1,c=i.length,u=0;c>u;u++)h=i[u],a=h.length,h=h.replace(/^ *([*+-]|\d+\.) +/,""),~h.indexOf("\n ")&&(a-=h.length,h=this.options.pedantic?h.replace(/^ {1,4}/gm,""):h.replace(new RegExp("^ {1,"+a+"}","gm"),"")),this.options.smartLists&&u!==c-1&&(o=p.bullet.exec(i[u+1])[0],l===o||l.length>1&&o.length>1||(e=i.slice(u+1).join("\n")+e,u=c-1)),s=r||/\n\n(?!\s*$)/.test(h),u!==c-1&&(r="\n"===h.charAt(h.length-1),s||(s=r)),this.tokens.push({type:s?"loose_item_start":"list_item_start"}),this.token(h,!1,n),this.tokens.push({type:"list_item_end"});this.tokens.push({type:"list_end"})}else if(i=this.rules.html.exec(e))e=e.substring(i[0].length),this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:"pre"===i[1]||"script"===i[1]||"style"===i[1],text:i[0]});else if(!n&&t&&(i=this.rules.def.exec(e)))e=e.substring(i[0].length),this.tokens.links[i[1].toLowerCase()]={href:i[2],title:i[3]};else if(t&&(i=this.rules.table.exec(e))){for(e=e.substring(i[0].length),h={type:"table",header:i[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3].replace(/(?: *\| *)?\n$/,"").split("\n")},u=0;u])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:o,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:o,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/,u.link=l(u.link)("inside",u._inside)("href",u._href)(),u.reflink=l(u.reflink)("inside",u._inside)(),u.normal=h({},u),u.pedantic=h({},u.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/}),u.gfm=h({},u.normal,{escape:l(u.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:l(u.text)("]|","~]|")("|","|https?://|")()}),u.breaks=h({},u.gfm,{br:l(u.br)("{2,}","*")(),text:l(u.gfm.text)("{2,}","*")()}),t.rules=u,t.output=function(e,n,r){var s=new t(n,r);return s.output(e)},t.prototype.output=function(e){for(var t,n,r,i,l="";e;)if(i=this.rules.escape.exec(e))e=e.substring(i[0].length),l+=i[1];else if(i=this.rules.autolink.exec(e))e=e.substring(i[0].length),"@"===i[2]?(n=this.mangle(":"===i[1].charAt(6)?i[1].substring(7):i[1]),r=this.mangle("mailto:")+n):(n=s(i[1]),r=n),l+=this.renderer.link(r,null,n);else if(this.inLink||!(i=this.rules.url.exec(e))){if(i=this.rules.tag.exec(e))!this.inLink&&/^/i.test(i[0])&&(this.inLink=!1),e=e.substring(i[0].length),l+=this.options.sanitize?s(i[0]):i[0];else if(i=this.rules.link.exec(e))e=e.substring(i[0].length),this.inLink=!0,l+=this.outputLink(i,{href:i[2],title:i[3]}),this.inLink=!1;else if((i=this.rules.reflink.exec(e))||(i=this.rules.nolink.exec(e))){if(e=e.substring(i[0].length),t=(i[2]||i[1]).replace(/\s+/g," "),t=this.links[t.toLowerCase()],!t||!t.href){l+=i[0].charAt(0),e=i[0].substring(1)+e;continue}this.inLink=!0,l+=this.outputLink(i,t),this.inLink=!1}else if(i=this.rules.strong.exec(e))e=e.substring(i[0].length),l+=this.renderer.strong(this.output(i[2]||i[1]));else if(i=this.rules.em.exec(e))e=e.substring(i[0].length),l+=this.renderer.em(this.output(i[2]||i[1]));else if(i=this.rules.code.exec(e))e=e.substring(i[0].length),l+=this.renderer.codespan(s(i[2],!0));else if(i=this.rules.br.exec(e))e=e.substring(i[0].length),l+=this.renderer.br();else if(i=this.rules.del.exec(e))e=e.substring(i[0].length),l+=this.renderer.del(this.output(i[1]));else if(i=this.rules.text.exec(e))e=e.substring(i[0].length),l+=s(this.smartypants(i[0]));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else e=e.substring(i[0].length),n=s(i[1]),r=n,l+=this.renderer.link(r,null,n);return l},t.prototype.outputLink=function(e,t){var n=s(t.href),r=t.title?s(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,s(e[1]))},t.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/--/g,"—").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},t.prototype.mangle=function(e){for(var t,n="",r=e.length,s=0;r>s;s++)t=e.charCodeAt(s),Math.random()>.5&&(t="x"+t.toString(16)),n+="&#"+t+";";return n},n.prototype.code=function(e,t,n){if(this.options.highlight){var r=this.options.highlight(e,t);null!=r&&r!==e&&(n=!0,e=r)}return t?'
'+(n?e:s(e,!0))+"\n
\n":"
"+(n?e:s(e,!0))+"\n
"},n.prototype.blockquote=function(e){return"
\n"+e+"
\n"},n.prototype.html=function(e){return e},n.prototype.heading=function(e,t,n){return"'+e+"\n"},n.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},n.prototype.list=function(e,t){var n=t?"ol":"ul";return"<"+n+">\n"+e+"\n"},n.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},n.prototype.paragraph=function(e){return"

    "+e+"

    \n"},n.prototype.table=function(e,t){return"\n\n"+e+"\n\n"+t+"\n
    \n"},n.prototype.tablerow=function(e){return"\n"+e+"\n"},n.prototype.tablecell=function(e,t){var n=t.header?"th":"td",r=t.align?"<"+n+' style="text-align:'+t.align+'">':"<"+n+">";return r+e+"\n"},n.prototype.strong=function(e){return""+e+""},n.prototype.em=function(e){return""+e+""},n.prototype.codespan=function(e){return""+e+""},n.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},n.prototype.del=function(e){return""+e+""},n.prototype.link=function(e,t,n){if(this.options.sanitize){try{var r=decodeURIComponent(i(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(s){return""}if(0===r.indexOf("javascript:")||0===r.indexOf("vbscript:"))return""}var l='
    "},n.prototype.image=function(e,t,n){var r=''+n+'":">"},r.parse=function(e,t,n){var s=new r(t,n);return s.parse(e)},r.prototype.parse=function(e){this.inline=new t(e.links,this.options,this.renderer),this.tokens=e.reverse();for(var n="";this.next();)n+=this.tok();return n},r.prototype.next=function(){return this.token=this.tokens.pop()},r.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},r.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},r.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,s,i="",l="";for(n="",e=0;e[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"
    "+(escaped?code:escape(code,true))+"\n
    "}return'
    '+(escaped?code:escape(code,true))+"\n
    \n"};Renderer.prototype.blockquote=function(quote){return"
    \n"+quote+"
    \n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"'+text+"\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"
    \n":"
    \n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"\n"};Renderer.prototype.listitem=function(text){return"
  • "+text+"
  • \n"};Renderer.prototype.paragraph=function(text){return"

    "+text+"

    \n"};Renderer.prototype.table=function(header,body){return"\n"+"\n"+header+"\n"+"\n"+body+"\n"+"
    \n"};Renderer.prototype.tablerow=function(content){return"\n"+content+"\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"\n"};Renderer.prototype.strong=function(text){return""+text+""};Renderer.prototype.em=function(text){return""+text+""};Renderer.prototype.codespan=function(text){return""+text+""};Renderer.prototype.br=function(){return this.options.xhtml?"
    ":"
    "};Renderer.prototype.del=function(text){return""+text+""};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='
    ";return out};Renderer.prototype.image=function(href,title,text){var out=''+text+'":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i/g,">").replace(/"/g,""").replace(/'/g,"'")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;iAn error occured:

    "+escape(e.message+"",true)+"
    "}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); \ No newline at end of file diff --git a/plugin/math/math.js b/plugin/math/math.js index 25b7516..7867376 100644 --- a/plugin/math/math.js +++ b/plugin/math/math.js @@ -7,14 +7,17 @@ var RevealMath = window.RevealMath || (function(){ var options = Reveal.getConfig().math || {}; - options.mathjax = options.mathjax || 'https://cdn.mathjax.org/mathjax/latest/MathJax.js'; + options.mathjax = options.mathjax || 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js'; options.config = options.config || 'TeX-AMS_HTML-full'; + options.tex2jax = options.tex2jax || { + inlineMath: [['$','$'],['\\(','\\)']] , + skipTags: ['script','noscript','style','textarea','pre'] }; loadScript( options.mathjax + '?config=' + options.config, function() { MathJax.Hub.Config({ messageStyle: 'none', - tex2jax: { inlineMath: [['$','$'],['\\(','\\)']] }, + tex2jax: options.tex2jax, skipStartupTypeset: true }); diff --git a/plugin/multiplex/client.js b/plugin/multiplex/client.js index e6179f6..3ffd1e0 100644 --- a/plugin/multiplex/client.js +++ b/plugin/multiplex/client.js @@ -8,6 +8,6 @@ if (data.socketId !== socketId) { return; } if( window.location.host === 'localhost:1947' ) return; - Reveal.slide(data.indexh, data.indexv, data.indexf, 'remote'); + Reveal.setState(data.state); }); }()); diff --git a/plugin/multiplex/index.js b/plugin/multiplex/index.js index 6f5d8b1..8195f04 100644 --- a/plugin/multiplex/index.js +++ b/plugin/multiplex/index.js @@ -1,37 +1,45 @@ +var http = require('http'); var express = require('express'); var fs = require('fs'); var io = require('socket.io'); var crypto = require('crypto'); -var app = express.createServer(); -var staticDir = express.static; +var app = express(); +var staticDir = express.static; +var server = http.createServer(app); -io = io.listen(app); +io = io(server); var opts = { - port: 1948, + port: process.env.PORT || 1948, baseDir : __dirname + '/../../' }; -io.sockets.on('connection', function(socket) { - socket.on('slidechanged', function(slideData) { - if (typeof slideData.secret == 'undefined' || slideData.secret == null || slideData.secret === '') return; - if (createHash(slideData.secret) === slideData.socketId) { - slideData.secret = null; - socket.broadcast.emit(slideData.socketId, slideData); +io.on( 'connection', function( socket ) { + socket.on('multiplex-statechanged', function(data) { + if (typeof data.secret == 'undefined' || data.secret == null || data.secret === '') return; + if (createHash(data.secret) === data.socketId) { + data.secret = null; + socket.broadcast.emit(data.socketId, data); }; }); }); -app.configure(function() { - [ 'css', 'js', 'plugin', 'lib' ].forEach(function(dir) { - app.use('/' + dir, staticDir(opts.baseDir + dir)); - }); +[ 'css', 'js', 'plugin', 'lib' ].forEach(function(dir) { + app.use('/' + dir, staticDir(opts.baseDir + dir)); }); app.get("/", function(req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); - fs.createReadStream(opts.baseDir + '/index.html').pipe(res); + + var stream = fs.createReadStream(opts.baseDir + '/index.html'); + stream.on('error', function( error ) { + res.write('

    reveal.js multiplex server.

    Generate token'); + res.end(); + }); + stream.on('readable', function() { + stream.pipe(res); + }); }); app.get("/token", function(req,res) { @@ -47,7 +55,7 @@ var createHash = function(secret) { }; // Actually listen -app.listen(opts.port || null); +server.listen( opts.port || null ); var brown = '\033[33m', green = '\033[32m', diff --git a/plugin/multiplex/master.js b/plugin/multiplex/master.js index b6a7eb7..7f4bf45 100644 --- a/plugin/multiplex/master.js +++ b/plugin/multiplex/master.js @@ -1,51 +1,34 @@ (function() { + // Don't emit events from inside of notes windows if ( window.location.search.match( /receiver/gi ) ) { return; } var multiplex = Reveal.getConfig().multiplex; - var socket = io.connect(multiplex.url); - - var notify = function( slideElement, indexh, indexv, origin ) { - if( typeof origin === 'undefined' && origin !== 'remote' ) { - var nextindexh; - var nextindexv; - - var fragmentindex = Reveal.getIndices().f; - if (typeof fragmentindex == 'undefined') { - fragmentindex = 0; - } - - if (slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION') { - nextindexh = indexh; - nextindexv = indexv + 1; - } else { - nextindexh = indexh + 1; - nextindexv = 0; - } - - var slideData = { - indexh : indexh, - indexv : indexv, - indexf : fragmentindex, - nextindexh : nextindexh, - nextindexv : nextindexv, - secret: multiplex.secret, - socketId : multiplex.id - }; - - socket.emit('slidechanged', slideData); - } - } - - Reveal.addEventListener( 'slidechanged', function( event ) { - notify( event.currentSlide, event.indexh, event.indexv, event.origin ); - } ); - - var fragmentNotify = function( event ) { - notify( Reveal.getCurrentSlide(), Reveal.getIndices().h, Reveal.getIndices().v, event.origin ); + var socket = io.connect( multiplex.url ); + + function post() { + + var messageData = { + state: Reveal.getState(), + secret: multiplex.secret, + socketId: multiplex.id + }; + + socket.emit( 'multiplex-statechanged', messageData ); + }; - Reveal.addEventListener( 'fragmentshown', fragmentNotify ); - Reveal.addEventListener( 'fragmenthidden', fragmentNotify ); -}()); \ No newline at end of file + // post once the page is loaded, so the client follows also on "open URL". + window.addEventListener( 'load', post ); + + // Monitor events that trigger a change in state + Reveal.addEventListener( 'slidechanged', post ); + Reveal.addEventListener( 'fragmentshown', post ); + Reveal.addEventListener( 'fragmenthidden', post ); + Reveal.addEventListener( 'overviewhidden', post ); + Reveal.addEventListener( 'overviewshown', post ); + Reveal.addEventListener( 'paused', post ); + Reveal.addEventListener( 'resumed', post ); + +}()); diff --git a/plugin/multiplex/package.json b/plugin/multiplex/package.json new file mode 100644 index 0000000..bbed77a --- /dev/null +++ b/plugin/multiplex/package.json @@ -0,0 +1,19 @@ +{ + "name": "reveal-js-multiplex", + "version": "1.0.0", + "description": "reveal.js multiplex server", + "homepage": "http://revealjs.com", + "scripts": { + "start": "node index.js" + }, + "engines": { + "node": "~4.1.1" + }, + "dependencies": { + "express": "~4.13.3", + "grunt-cli": "~0.1.13", + "mustache": "~2.2.1", + "socket.io": "~1.3.7" + }, + "license": "MIT" +} diff --git a/plugin/notes-server/client.js b/plugin/notes-server/client.js index 628586f..00b277b 100644 --- a/plugin/notes-server/client.js +++ b/plugin/notes-server/client.js @@ -41,10 +41,15 @@ } // When a new notes window connects, post our current state - socket.on( 'connect', function( data ) { + socket.on( 'new-subscriber', function( data ) { post(); } ); + // When the state changes from inside of the speaker view + socket.on( 'statechanged-speaker', function( data ) { + Reveal.setState( data.state ); + } ); + // Monitor events that trigger a change in state Reveal.addEventListener( 'slidechanged', post ); Reveal.addEventListener( 'fragmentshown', post ); diff --git a/plugin/notes-server/index.js b/plugin/notes-server/index.js index df917f1..b95f071 100644 --- a/plugin/notes-server/index.js +++ b/plugin/notes-server/index.js @@ -1,39 +1,42 @@ +var http = require('http'); var express = require('express'); var fs = require('fs'); var io = require('socket.io'); -var _ = require('underscore'); var Mustache = require('mustache'); -var app = express.createServer(); +var app = express(); var staticDir = express.static; +var server = http.createServer(app); -io = io.listen(app); +io = io(server); var opts = { port : 1947, baseDir : __dirname + '/../../' }; -io.sockets.on( 'connection', function( socket ) { +io.on( 'connection', function( socket ) { - socket.on( 'connect', function( data ) { - socket.broadcast.emit( 'connect', data ); + socket.on( 'new-subscriber', function( data ) { + socket.broadcast.emit( 'new-subscriber', data ); }); socket.on( 'statechanged', function( data ) { + delete data.state.overview; socket.broadcast.emit( 'statechanged', data ); }); -}); - -app.configure( function() { - - [ 'css', 'js', 'images', 'plugin', 'lib' ].forEach( function( dir ) { - app.use( '/' + dir, staticDir( opts.baseDir + dir ) ); + socket.on( 'statechanged-speaker', function( data ) { + delete data.state.overview; + socket.broadcast.emit( 'statechanged-speaker', data ); }); }); +[ 'css', 'js', 'images', 'plugin', 'lib' ].forEach( function( dir ) { + app.use( '/' + dir, staticDir( opts.baseDir + dir ) ); +}); + app.get('/', function( req, res ) { res.writeHead( 200, { 'Content-Type': 'text/html' } ); @@ -52,7 +55,7 @@ app.get( '/notes/:socketId', function( req, res ) { }); // Actually listen -app.listen( opts.port || null ); +server.listen( opts.port || null ); var brown = '\033[33m', green = '\033[32m', @@ -62,5 +65,5 @@ var slidesLocation = 'http://localhost' + ( opts.port ? ( ':' + opts.port ) : '' console.log( brown + 'reveal.js - Speaker Notes' + reset ); console.log( '1. Open the slides at ' + green + slidesLocation + reset ); -console.log( '2. Click on the link your JS console to go to the notes page' ); +console.log( '2. Click on the link in your JS console to go to the notes page' ); console.log( '3. Advance through your slides and your notes will advance automatically' ); diff --git a/plugin/notes-server/notes.html b/plugin/notes-server/notes.html index 72d0317..ab8c5b1 100644 --- a/plugin/notes-server/notes.html +++ b/plugin/notes-server/notes.html @@ -8,6 +8,7 @@ @@ -152,7 +247,7 @@
    -
    UPCOMING:
    +
    Upcoming

    Time Click to Reset

    @@ -170,6 +265,10 @@

    Notes

    +
    + + +
    @@ -182,11 +281,20 @@

    Notes

    currentState, currentSlide, upcomingSlide, + layoutLabel, + layoutDropdown, connected = false; var socket = io.connect( window.location.origin ), socketId = '{{socketId}}'; + var SPEAKER_LAYOUTS = { + 'default': 'Default', + 'wide': 'Wide', + 'tall': 'Tall', + 'notes-only': 'Notes only' + }; + socket.on( 'statechanged', function( data ) { // ignore data from sockets that aren't ours @@ -195,7 +303,6 @@

    Notes

    if( connected === false ) { connected = true; - setupIframes( data ); setupKeyboard(); setupNotes(); setupTimer(); @@ -206,13 +313,28 @@

    Notes

    } ); + setupLayout(); + + // Load our presentation iframes + setupIframes(); + + // Once the iframes have loaded, emit a signal saying there's + // a new subscriber which will trigger a 'statechanged' + // message to be sent back window.addEventListener( 'message', function( event ) { var data = JSON.parse( event.data ); if( data && data.namespace === 'reveal' ) { if( /ready/.test( data.eventName ) ) { - socket.emit( 'connect', { socketId: socketId } ); + socket.emit( 'new-subscriber', { socketId: socketId } ); + } + } + + // Messages sent by reveal.js inside of the current slide preview + if( data && data.namespace === 'reveal' ) { + if( /slidechanged|fragmentshown|fragmenthidden|overviewshown|overviewhidden|paused|resumed/.test( data.eventName ) && currentState !== JSON.stringify( data.state ) ) { + socket.emit( 'statechanged-speaker', { state: data.state } ); } } @@ -267,7 +389,7 @@

    Notes

    /** * Creates the preview iframes. */ - function setupIframes( data ) { + function setupIframes() { var params = [ 'receiver', @@ -277,9 +399,8 @@

    Notes

    'backgroundTransition=none' ].join( '&' ); - var hash = '#/' + data.state.indexh + '/' + data.state.indexv; - var currentURL = '/?' + params + '&postMessageEvents=true' + hash; - var upcomingURL = '/?' + params + '&controls=false' + hash; + var currentURL = '/?' + params + '&postMessageEvents=true'; + var upcomingURL = '/?' + params + '&controls=false'; currentSlide = document.createElement( 'iframe' ); currentSlide.setAttribute( 'width', 1280 ); @@ -351,6 +472,74 @@

    Notes

    } + /** + * Sets up the speaker view layout and layout selector. + */ + function setupLayout() { + + layoutDropdown = document.querySelector( '.speaker-layout-dropdown' ); + layoutLabel = document.querySelector( '.speaker-layout-label' ); + + // Render the list of available layouts + for( var id in SPEAKER_LAYOUTS ) { + var option = document.createElement( 'option' ); + option.setAttribute( 'value', id ); + option.textContent = SPEAKER_LAYOUTS[ id ]; + layoutDropdown.appendChild( option ); + } + + // Monitor the dropdown for changes + layoutDropdown.addEventListener( 'change', function( event ) { + + setLayout( layoutDropdown.value ); + + }, false ); + + // Restore any currently persisted layout + setLayout( getLayout() ); + + } + + /** + * Sets a new speaker view layout. The layout is persisted + * in local storage. + */ + function setLayout( value ) { + + var title = SPEAKER_LAYOUTS[ value ]; + + layoutLabel.innerHTML = 'Layout' + ( title ? ( ': ' + title ) : '' ); + layoutDropdown.value = value; + + document.body.setAttribute( 'data-speaker-layout', value ); + + // Persist locally + if( window.localStorage ) { + window.localStorage.setItem( 'reveal-speaker-layout', value ); + } + + } + + /** + * Returns the ID of the most recently set speaker layout + * or our default layout if none has been set. + */ + function getLayout() { + + if( window.localStorage ) { + var layout = window.localStorage.getItem( 'reveal-speaker-layout' ); + if( layout ) { + return layout; + } + } + + // Default to the first record in the layouts hash + for( var id in SPEAKER_LAYOUTS ) { + return id; + } + + } + function zeroPadInteger( num ) { var str = '00' + parseInt( num ); diff --git a/plugin/notes/notes.html b/plugin/notes/notes.html index 0cc8cf6..0c4eca5 100644 --- a/plugin/notes/notes.html +++ b/plugin/notes/notes.html @@ -8,6 +8,7 @@ -

    JS !== jQuery

    +

    Javascript

    http://kleegroup.github.io/formation-js/#/
    +
    +

    Présentation

    +
    +

    Les bases du langage

    +
    +
    +

    De l'utilisation du JS

    +
    +
    +

    ECMAScript

    +
    + +
    +

    Les bases

    +

    Types primitifs

    +

    Objets

    +

    Strings

    +
    +

    Tableaux

    +
    +

    Dates

    +

    Operateurs

    +

    truthy/falsy

    +

    Destruct

    +

    Interpolation de strings

    +

    Pièges

    +
    + +
    +
    +

    Les fonctions

    +
    +
    +

    Variables

    +
    +
    +

    Scope

    +
    +
    +

    Déclaration

    +
    +
    +

    Boucles

    +
    +
    +

    Closure

    +
    +
    +

    Binding

    +
    +
    + +
    +
    +

    Prototypes et classes

    +
    +
    +

    Prototype

    +
    +
    +

    Constructeur

    +
    +
    +

    Classe

    +
    +
    +

    Chaine d'appel

    +
    +
    + +
    +
    +

    Structure d'une application

    +
    +
    +

    Déclarer un module

    +
    +
    +

    Utiliser un module

    +
    +
    + +
    +
    +

    Gestion de l'asynchrone

    +
    +
    +

    Callbacks

    +
    +
    +

    Promesses

    +
    +
    +

    Async/await

    +
    +
    + +
    +
    +

    L'éco-système JS

    +
    +
    +

    lodash

    +
    +
    +

    moment

    +
    +
    +

    i18n

    +
    +
    +

    node.js

    +
    +
    +

    babel

    +
    +
    +

    webpack

    +
    +
    +

    npm

    +
    +
    +
    -

    Les bases

    +

    Les types de base

    ## Les variables From d50af0fc58f375f9cedc481eba1649f00eb5222a Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Mon, 25 Feb 2019 15:56:57 +0100 Subject: [PATCH 04/23] =?UTF-8?q?feat:=20Pr=C3=A9sentation=20du=20langage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 8878017..654ff9f 100644 --- a/index.html +++ b/index.html @@ -36,6 +36,11 @@ + @@ -45,15 +50,56 @@

    Javascript

    http://kleegroup.github.io/formation-js/#/
    -

    Présentation

    -

    Les bases du langage

    +

    Présentation

    +
    +
    +

    Kesako?

    +
      +
    • Langage créé en 1995 pour réaliser des petits scripts dans des pages Web dans le but de les dynamiser
    • +
    • Le langage respecte l'ensemble des paradigme orienté objet, et est basé sur un principe de prototype
    • +
    • Langage nativement supporté par tous les navigateurs Web, ce qui le rend extrèmement populaire
    • +
    • Chaque navigateur à cependant son propre moteur JS
    • +

    De l'utilisation du JS

    +
      +
    • Utilisation au sens premier du langage: dynamiser une page HTML avec quelques scripts côté client
    • +
    • Utilisation de Jquery: simplification de fonction complexe (écoute d'vènement, manipulation du DOM ...)
    • +
    • Attention! JS !== JQuery
    • +
    • Avènement des SPA: React, Angular, Backbone, Vue ...
    • +
    • Multiplication des usages +
        +
      • Application desktop (Electron)
      • +
      • Application mobile (Cordova, Phonegap)
      • +
      • Application mobile "native" (React native)
      • +
      • Serveur web (NodeJS)
      • +
      • ...
      • +
      +
    • +
    +
    +
    +

    Standard ECMAScript (ECMA-262)

    +

    Il s'agit des normes Javascript écrites au cours des années.

    + + + + + +
    ES5 (2009)version la plus connu, supportée par tous les navigateurs
    ES 2016Ajoute énormément de modification au langage
    ES 2017version actuelle de la norme très semblable à 2016
    ES nextversion destinée à devenir la nouvelle norme
    + +
    On voit beaucoup de « ES7 » ou « ES8 » qui traînent : en général ça fait référence à l’« ES next » du moment.
    -

    ECMAScript

    +

    Transpilage

    +

    Le langage évoluant rapidement (tous les ans depuis 2015), les moteurs JS ne suivent pas toujours. Une étape de transpilage nous permet d'écrire notre code + avec toutes les avancées du langages, et rend cela compréhensible pour les différents moteurs JS

    +
      +
    • Babel: Implémente les normes ES2017 et ESnext, les publie sous forme de module pour le développeur.
    • +
    • TypeScript: Implemente tout ou parti des normes ES2017 et ESnext. Ajoute un sucre syntaxique de typage pour le langage, ainsi qu'un jeu de fonctions avancées propre à ce typage.
    • +
    From 31995a04deeef9d5adf294c910671ae12edcbadd Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Mon, 25 Feb 2019 18:02:22 +0100 Subject: [PATCH 05/23] =?UTF-8?q?feat(Les=20bases):=20Cr=C3=A9ation=20des?= =?UTF-8?q?=20partie=20Objet,=20String=20et=20Tableaux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 219 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 133 insertions(+), 86 deletions(-) diff --git a/index.html b/index.html index 654ff9f..b01350e 100644 --- a/index.html +++ b/index.html @@ -48,8 +48,8 @@
    -

    Javascript

    http://kleegroup.github.io/formation-js/#/
    -
    +

    Javascript

    http://kleegroup.github.io/formation-js/#/
    +

    Présentation

    @@ -104,17 +104,140 @@

    Transpilage

    -

    Les bases

    -

    Types primitifs

    -

    Objets

    -

    Strings

    +
    +

    Les bases

    +
    +
    +

    Types primitifs

    +

    Il y a 6 types primitifs en Javascript:

    + + +
      +
    • boolean: résultat d'une assertion logique true ou false
    • +
    • null: ne possède qu'une unique valeur null
    • +
    • undefined: représente la non-affectation d'une variable
    • +
    • number: contient l'ensemble des valeur numéraire (entier, float, NaN, +Infinity, - Infinity)
    • +
    • string: représente une chaine de caractère à partir d'un ensemble d'élements 16bits non-signés
    • +
    • symbol: type de données unique et inchangeable (souvent utilisé pour créer des identifiants)
    • +
    +

    Tout le reste est "Objet" (oui oui même les tableaux...)

    +

    Un objet avec une "call signature" est une fonction

    +
    +
    +

    Objets

    +

    JavaScript est conçu autour d'un paradigme simple, basé sur les objets.

    +

    Un objet est un ensemble de propriétés et une propriété est une association entre un nom (aussi appelé clé) et une valeur.

    +

    La valeur d'une propriété peut être une fonction, auquel cas la propriété peut être appelée « méthode ».

    +
    +
    +

    Objets

    +
    +							
    +/// Création d'un objet
    +const obj = { first: 'David', last: 'Lopez', age: 77 };
    +/// Utilisation des propriétés
    +obj.first  // => 'David'
    +obj['age'] // => 77
    +/// Affectation d'une valeur à une propriété
    +obj.first = 'pierr';
    +obj.first // => 'pierr'
    +/// Attention si votre clé de propriété est un nombre!
    +obj[77] = 'roberto';
    +obj[77]   // => 'roberto'
    +obj['77'] // => 'roberto'
    +obj.77    // => SyntaxError
    +/// Parce que je fais ce que je veux depuis ES2016 :p
    +obj['a'+ 12] = 'Gino';
    +obj.a12;
    +							
    +						
    +
    +
    +

    Strings

    +

    Le type String de JavaScript est utilisé pour représenter des données textuelles.

    +

    C'est un ensemble d'"éléments" de valeurs non signées sur 16 bits (unités de codage UTF-16).

    +

    Chaque élément dans la chaîne de caractères occupe une position dans la chaîne de caractères. Le premier élément se trouve à l'indice 0, le suivant à l'indice 1 et ainsi de suite.

    +

    La longueur d'une chaîne de caractères est le nombre d'éléments qu'elle contient.

    +

    Une String est immuable il est impossible de la modifier une fois créée. Il est cependant possible de recréer une string à partir d'une autre string.

    +
    +
    +

    Strings

    +
    +								
    +var maString = 'Hello World!';
    +maString.length // => 12
    +maString[0] // => 'H'
    +maString[0] = 'X'; // Aucun effet. une string est immuable
    +maString[0] // => 'H'
    +/// Quelques fonctions
    +'déjà'.localeCompare('demain') // => -1 'déjà' est alphabétiquement avant 'demain'
    +'déjà !'.toLocaleUpperCase()      // => 'DÉJÀ !' Renvoie une nouvelle instance en majuscule
    +'ÇA POUTRE'.toLocaleLowerCase()   // => 'ça poutre' Renvoie une nouvelle instance en minuscule
    +'one,two,three'.split(',')        // => ['one', 'two', 'three'] trnsformation en tableau selon un séparateur
    +'one,,two,three'.split(/\W+/)     // => ['one', 'two'] transformation en tableau selon une expression régulière
    +'hello'.substring(1)      // => 'ello' renvoie une nouvelle instance d'une partie de la chaine
    +'hello'.slice(1, -2)      // => 'el' -> [1;length-2[
    +								
    +							
    +
    +
    +

    Les tableaux

    +

    Un Array est un ensemble ordonné de valeurs auxquelles on peut faire référence avec un nom et un indice.

    +

    JavaScript ne possède pas de type particulier pour représenter un tableau. En revanche, il est possible d'utiliser l'objet natif Array ainsi que ses méthodes pour manipuler des tableaux

    +
    +
    +

    Les tableaux

    +
    +						
    +let names = ['John', 'David', 'Rodrigo'];
    +
    +names.length
    +// => 3
    +
    +names[0]
    +// => 'John'
    +
    +names[12] = 'Pierre';
    +names.length
    +// => 13
    +
    +names[9]
    +// => undefined (comme 10 et 11): c'est appelé "sparse array"
    +								
    +							
    +
    -

    Tableaux

    +

    Les tableaux

    +
    +						
    +let data = [1, 2, 3];
    +
    +// arr1.concat(arg…) -> arr2 [déroule sur 1 niveau, ni "shallow" ni "deep"]
    +data.concat(4, 5, 6)     // => [1, 2, 3, 4, 5, 6]
    +data.concat([4, 5, 6])   // => [1, 2, 3, 4, 5, 6]
    +data.concat(4, [5, 6])   // => [1, 2, 3, 4, 5, 6]
    +data.concat([4, [5, 6]]) // => [1, 2, 3, 4, [5, 6]] -- 2 niveaux !
    +data                     // => [1, 2, 3] -- intact !
    +
    +// arr.join([sep = ',']) -> String
    +data.join()   // => '1,2,3'
    +data.join('') // => '123' -- Fréquent en construisant du HTML
    +
    +// arr1.slice(signedBegin[, signedEnd = length]) -> arr2 -- négatif ok partout !
    +data.slice(1)      // => [2, 3]
    +data.slice(1, 1)   // => []
    +data.slice(1, 2)   // => [2]
    +data.slice(1, -1)  // => [2]
    +data.slice(-2)     // => [2, 3]
    +data.slice(-2, 2)  // => [2]
    +data.slice(-2, -1) // => [2]
    +						
    +					

    Dates

    Operateurs

    -

    truthy/falsy

    -

    Destruct

    +

    Truthy / Falsy

    +

    Destructing / Spreading

    Interpolation de strings

    Pièges

    @@ -125,6 +248,7 @@

    Les fonctions

    Variables

    +

    Scope

    @@ -227,24 +351,6 @@

    npm

    > A retenir on utilise `const` au maximum et `let` dans les autres cas
    -
    -

    Les strings

    -
    -						
    -'déjà' < 'demain'              // => false
    -'déjà'.localeCompare('demain') // => -1 ('déjà' avant 'demain')
    -
    -'déjà !'.toLocaleUpperCase()      // => 'DÉJÀ !'
    -'ÇA POUTRE'.toLocaleLowerCase()   // => 'ça poutre'
    -
    -'one,two,three'.split(',')        // => ['one', 'two', 'three']
    -'one,,two,three'.split(/\W+/)     // => ['one', 'two']
    -
    -'hello'.substring(1)      // => 'ello'
    -'hello'.slice(1, -2)      // => 'el' -> [1;length-2[
    -						
    -					
    -

    Les dates

    @@ -292,21 +398,7 @@ 

    Les dates

    Les objets

    -
    -						
    -let obj = { first: 'David', last: 'Lopez', age: 77 };
    -obj.first  // => 'David'
    -obj['age'] // => 42
    -
    -obj.first = 'pierr';
    -obj['first'] // => 'pierr'
     
    -obj[77] = 'roberto';
    -obj[77]   // => 'roberto'
    -obj['77'] // => 'roberto'
    -obj.77    // => SyntaxError
    -						
    -					

    Les objets avec ES6

    @@ -323,53 +415,8 @@

    Les objets avec ES6

     				
    -

    Les tableaux

    -
    -						
    -let names = ['John', 'David', 'Rodrigo'];
    -
    -names.length
    -// => 3. R/W : astuce pour réutiliser un tableau!
    -
    -names[0]
    -// => 'John'
    -
    -names[12] = 'Pierre';
    -names.length
    -// => 13
     
    -names[9]
    -// => undefined (comme 10 et 11): c'est appelé "sparse array"
    -						
    -					
    -
    -
    -
     						

    Les tableaux

    - -let data = [1, 2, 3]; - -// arr1.concat(arg…) -> arr2 [déroule sur 1 niveau, ni "shallow" ni "deep"] -data.concat(4, 5, 6) // => [1, 2, 3, 4, 5, 6] -data.concat([4, 5, 6]) // => [1, 2, 3, 4, 5, 6] -data.concat(4, [5, 6]) // => [1, 2, 3, 4, 5, 6] -data.concat([4, [5, 6]]) // => [1, 2, 3, 4, [5, 6]] -- 2 niveaux ! -data // => [1, 2, 3] -- intact ! - -// arr.join([sep = ',']) -> String -data.join() // => '1,2,3' -data.join('') // => '123' -- Fréquent en construisant du HTML - -// arr1.slice(signedBegin[, signedEnd = length]) -> arr2 -- négatif ok partout ! -data.slice(1) // => [2, 3] -data.slice(1, 1) // => [] -data.slice(1, 2) // => [2] -data.slice(1, -1) // => [2] -data.slice(-2) // => [2, 3] -data.slice(-2, 2) // => [2] -data.slice(-2, -1) // => [2] - -
    
    From 9f69389557354a8e6e119d5280167b09e640108a Mon Sep 17 00:00:00 2001
    From: Thibault Ingargiola 
    Date: Tue, 26 Feb 2019 11:57:13 +0100
    Subject: [PATCH 06/23] =?UTF-8?q?feat(les=20bases):=20les=20op=C3=A9rateur?=
     =?UTF-8?q?s.?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    ---
     index.html | 215 ++++++++++++++++++++++++++++++++++++++---------------
     1 file changed, 155 insertions(+), 60 deletions(-)
    
    diff --git a/index.html b/index.html
    index b01350e..d04d6bf 100644
    --- a/index.html
    +++ b/index.html
    @@ -234,12 +234,163 @@ 

    Les tableaux

    -

    Dates

    -

    Operateurs

    -

    Truthy / Falsy

    +
    +

    Dates

    +

    JavaScript ne possède pas de type primitif pour représenter des dates. Cependant l'objet Date et ses méthodes permettent de manipuler des dates et des heures au sein d'une application.

    +

    L'objet Date possède de nombreuses méthodes pour définir, modifier, obtenir des dates. Il ne possède pas de propriétés

    +

    JavaScript gère les dates de façon similaire à Java. (Donc assez mal...)

    +

    Les dates sont représentées selon les nombres de millisecondes écoulées depuis le premier janvier 1970 à 00h00:00. + L'objet Date permet de représenter des dates allant de -100 000 000 jours jusqu'à +100 000 000 jours par rapport au premier janvier 1970 UTC.

    +
    +
    +

    Dates

    +
    +								
    +new Date()                  //  maintenant !
    +new Date(y,m,d[,h,m,s,ms]) // Valeur découpée. (un peu lourd...)
    +
    +date.getYear() // JAMAIS #Bug de l'an 2000 exemple: L'année 1976 renverra 76. Mais l'année 2016 renverra 116. -_-'
    +date.getFullYear()	// Mieux mais pas vraiment logique dans le nom...
    +date.getMonth()     // NAZE Java-like qui démarre à… zéro (janvier). #ugly
    +date.getDay()       // PERDUUUU ! C'est le DOW (Day Of Week), 0 = dim., 6 = sam
    +date.getDate()      // Le jour du mois.  Super logique.
    +date.getHours()
    +date.getMinutes()
    +date.getSeconds()
    +date.getMilliseconds() // "Milliseconds", un seul mot : une seule initiale.
    +
    +// Heure locale du navigateur/système.  On a les mêmes en getUTCXxx()…
    +								
    +							
    +
    Vous avez le choix dans l'implémentation de la date...
    De manière générale on préferera utiliser des library de dates type moment.js pour gérer des dates.
    +
    +
    +

    Operateurs

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ==true si les opérandes sont égaux après conversion en valeurs de mêmes types
    !=true si les opérandes sont différents.
    ===true si les opérandes sont égaux et de même type.
    !==true si les opérandes ne sont pas égaux ou pas de même type.
    >true si l'opérande gauche est supérieur (strictement) à l'opérande droit.
    >=true si l'opérande gauche est supérieur ou égal à l'opérande droit.
    <true si l'opérande gauche est inférieur (strictement) à l'opérande droit.
    <=true si l'opérande gauche est inférieur ou égal à l'opérande droit.
    +
    +
    +

    Quelques pièges de comparaisons en JS ...

    +
    +							
    +	== ou === ?!
    +
    +	42 == '42'        // => true  --
    +	null == undefined // => true  --
    +	null == 0         // => false --
    +	0 == undefined    // => false --
    +	0 == false        // => true  --
    +	1 == true         // => true  --
    +	42 == true        // => false --
    +	'0' == false      // => true  --
    +	'' == false       // => true  --
    +	NaN == NaN        // => false --
    +							
    +						
    +
    C'est franchement sale...
    +
    +
    +

    Pour éviter les écueils, utiliser ===

    +
    +							
    +	// avec ===, fini de jouer : vérif valeur ET TYPE !
    +
    +	42 === '42'        // => false
    +	null === undefined // => false
    +	null === 0         // => false
    +	0 === undefined    // => false
    +	0 === false        // => false
    +	'0' === false      // => false
    +	NaN === NaN        // => false -- rien à faire !
    +							
    +						
    +
    Toujours utiliser la comparaison stricte === et !==
    +
    +
    +

    Opérateurs

    +

    Les opérateurs javascripts font des conversions implicites.

    +

    Le javascript ne plantera jamais sur une opération. En revanche il peut vous renvoyer une valeur native comme Nan, +Infinity etc.

    +
    
    +	!42  => false
    +	!!42  => true //pratique pour convertir n'importe quelle valeur en booleen
    +	+'2'  => 2
    +	"lala" + 42 => "lala42"
    +	1/0 => Infinity
    +	"lala" - 42 => NaN
    +
    +	{} + [] => 0 // Hum ok...
    +	[] + {} => "[object Object]" // parce que why not!
    +	{} + {} => "[object Object][object Object]" // Bon ça je veux bien
    +	[] + [] => "" // Nan mais les gars...
    +	[] - {} => NaN // -_-'
    +	+[] => 0 // Ah ah
    +	+[] + [] => "0" // Vous l'avez?
    +	+[] + +[] => 0 // Bon ok j'arrete :=)
    +					
    +
    +
    +

    Opérateurs logiques

    +

    Ces opérateurs servent à resoudre des expressions logique en prenant en compte le caractère "Truthy" ou "Falsy" des valeurs de l'expression

    + + + + + + + + + + + + + +
    &&ET logique. Vrai si les deux expressions ont des valeur Truthy. S'arrête à la première valeur Falsy
    ||OU logique. Vrai si une des deux expressions a une valeur Truthy. S'arrête à la première valeur Truthy
    !NON logique. Vrai si une l'expression a une valeur Truthy. Faux sinon.
    +
    Attention les opérateurs logiques &&, || et ! fonctionnent différemment des opérateurs binaire &, | et ~.
    Pour plus d'info: La doc MDN
    +
    +
    +

    Truthy / Falsy

    +
    
    +"true" == true => false // la chaine de caratère "true" même après conversion n'est pas égale à true.
    +"true" && true => true // la chaine de caratère "true" pour ce qui est des expression logique!!
    +"true"&true => 0 // le & binaire renvoie le bit 0...
    +"1" == true => true // bah oui après converstion "1" => 1 => true donc égale à true...
    +					
    +
    +

    Destructing / Spreading

    Interpolation de strings

    -

    Pièges

    @@ -355,26 +506,6 @@

    npm

    Les dates

     						
    -new Date                   //  maintenant !
    -new Date(y,m,d[,h,m,s,ms]) // Valeur découpée. (un peu lourd...)
    -
    -date.getFullYear()  // JAMAIS
    -date.getMonth()     // NAZE Java-like qui démarre à… zéro (janvier). #ugly
    -date.getDay()       // PERDUUUU ! C'est le DOW (Day Of Week), 0 = dim., 6 = s
    -date.getDate()      // Le jour du mois.  Super logique.
    -date.getHours()
    -date.getMinutes()
    -date.getSeconds()
    -date.getMilliseconds() // "Milliseconds", un seul mot : une seule initiale.
    -
    -// Heure locale du navigateur/système.  On a les mêmes en getUTCXxx()…
    -						
    -					
    -
    -
    -

    Les dates

    -
    -						
     // "J'ai bien lu la doc"
     date.getTime()  // => ex. 1290852603042
     
    @@ -487,42 +618,6 @@ 

    Les fonctions

    - -
    -

    Quelques pièges de comparaisons en JS ...

    -
    -						
    -== ou === ?!
    -
    -42 == '42'        // => true  --
    -null == undefined // => true  --
    -null == 0         // => false --
    -0 == undefined    // => false --
    -0 == false        // => true  --
    -1 == true         // => true  --
    -42 == true        // => false --
    -'0' == false      // => true  --
    -'' == false       // => true  --
    -NaN == NaN        // => false --
    -						
    -					
    -
    -
    -

    Pour éviter les écueils, utiliser ===

    -
    -						
    -// avec ===, fini de jouer : vérif valeur ET TYPE !
    -
    -42 === '42'        // => false
    -null === undefined // => false
    -null === 0         // => false
    -0 === undefined    // => false
    -0 === false        // => false
    -'0' === false      // => false
    -NaN === NaN        // => false -- rien à faire !
    -						
    -					
    -

    in et delete

    
    From 0eb13bbe2b52cb69b86487d920c6b8cf7cfc8819 Mon Sep 17 00:00:00 2001
    From: Thibault Ingargiola 
    Date: Tue, 26 Feb 2019 14:44:54 +0100
    Subject: [PATCH 07/23] feat(Les bases): fin
    
    ---
     index.html | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
     1 file changed, 64 insertions(+), 2 deletions(-)
    
    diff --git a/index.html b/index.html
    index d04d6bf..9d2de07 100644
    --- a/index.html
    +++ b/index.html
    @@ -387,10 +387,72 @@ 

    Truthy / Falsy

    "true"&true => 0 // le & binaire renvoie le bit 0... "1" == true => true // bah oui après converstion "1" => 1 => true donc égale à true...
    +
    Globalement les valeur suivant sont Falsy: false, undefined, null, "", 0, NaN. Le reste est Truthy.
    +
    +

    Destructuring / Spreading

    +

    Des opérateurs de décomposition (Spread) et d'affectation par décomposition (Destructuring) ont fait leur apparition pour manipuler plus simplement les objets et les collections.

    +
      +
    • La syntaxe de décomposition permet d'étendre un itérable en lieu et place de plusieurs arguments (pour les appels de fonctions) ou de plusieurs éléments (pour les tableaux) ou de paires clés-valeurs (pour les objets).
    • +
    • L'affectation par décomposition est une expression JavaScript qui permet d'extraire des données d'un tableau ou d'un objet grâce à une syntaxe dont la forme ressemble à la structure du tableau ou de l'objet.
    • +
    +
    +
    +

    + Destructuring / Spreading +

    +
    +							
    +/* Arrays */
    +// Initialisation d'un array
    +const array = [1, 2, 3];
    +// On crée un nouvel array à partir de l'ancien
    +const array2 = [...array, 4, 5]; // array2 => [1,2,3,4,5]
    +function f(a, b, c) {
    +		return a + b + c;
    +}
    +// On appelle la fonction à partir de l'array
    +f(...array); // => 1+2+3
    +// On récupère des éléments précis d'un array.
    +const [a, b, c, ...rest] = array2; // a=1; b=2, c=3, rest=[4,5]
    +							
    +							
    +
    +
    +

    + Destructuring / Spreading +

    +
    +								
    +/* Objets */
    +// Initialisation d'un objet.
    +const objet = {a: 1, b: 2};
    +// On crée un nouvel objet à partir de l'ancien
    +const objet2 = {...objet, c: 3}; // objet2 = {a:1, b:2, c:3}
    +// On récupère des éléments précis d'un objet.
    +const {a, b, ...rest} = objet2; // a=1 b=2 rest={c:3}
    +// On peut aussi déstructurer directement dans une fonction :
    +function g({a, b, c: c2}) {
    +		return a + b + c2;
    +}
    +g(objet2);
    +								
    +							
    +
    +
    +

    Interpolation de strings

    +

    Les nouvelles normes ECMAScript ont permis de faire évoluer le langages et de fournir un moyen de manipuler les strings. Il est désormais possible de créer des chaine de caractères multiligne et paramétrables!

    +
    +							
    +
    +const person = {nom: Ingargiola, prenom: Thibault};
     
    -				

    Destructing / Spreading

    -

    Interpolation de strings

    +const stringAvant = 'Bonjour je suis ' + person.prenom + ' ' + person.nom; +const stringApres= `Bonjour je suis ${objet.prenom} ${objet.nom}. +Et le javascript c'était pas mieux avant!`; +
    +
    +
    From ba974845cc7df141655edd19fd7e3db941f2c6b7 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Tue, 26 Feb 2019 15:01:53 +0100 Subject: [PATCH 08/23] feat(Les base): correction de fautes d'orthographes --- index.html | 48 +++--------------------------------------------- 1 file changed, 3 insertions(+), 45 deletions(-) diff --git a/index.html b/index.html index 9d2de07..a5d3bd7 100644 --- a/index.html +++ b/index.html @@ -148,7 +148,7 @@

    Objets

    obj.77 // => SyntaxError /// Parce que je fais ce que je veux depuis ES2016 :p obj['a'+ 12] = 'Gino'; -obj.a12; +obj.a12; // => 'Gino' évidemment ;)
    @@ -170,6 +170,7 @@

    Strings

    maString[0] = 'X'; // Aucun effet. une string est immuable maString[0] // => 'H' /// Quelques fonctions +'déjà' < 'demain' // => false Cette comparaison ne fait pas du tout ce que vous pensez! 'déjà'.localeCompare('demain') // => -1 'déjà' est alphabétiquement avant 'demain' 'déjà !'.toLocaleUpperCase() // => 'DÉJÀ !' Renvoie une nouvelle instance en majuscule 'ÇA POUTRE'.toLocaleLowerCase() // => 'ça poutre' Renvoie une nouvelle instance en minuscule @@ -387,7 +388,7 @@

    Truthy / Falsy

    "true"&true => 0 // le & binaire renvoie le bit 0... "1" == true => true // bah oui après converstion "1" => 1 => true donc égale à true... -
    Globalement les valeur suivant sont Falsy: false, undefined, null, "", 0, NaN. Le reste est Truthy.
    +
    Globalement les valeurs suivantes sont Falsy: false, undefined, null, "", 0, NaN. Le reste est Truthy.

    Destructuring / Spreading

    @@ -564,49 +565,6 @@

    npm

    > A retenir on utilise `const` au maximum et `let` dans les autres cas
    -
    -

    Les dates

    -
    -						
    -// "J'ai bien lu la doc"
    -date.getTime()  // => ex. 1290852603042
    -
    -// "#superSmart"
    -+date
    -
    -// Et sinon…
    -new Date(1301733937452)
    -
    -// Mais aussi (car souci pour partir de composantes UTC) :
    -Date.UTC(y, m, d, h, mn, s, ms) // => numérique
    -
    -						
    -					
    -
    -
    -
    - A retenir : Momentjs (on voit ça plus tard...) -
    -
    - -
    -

    Les objets

    - -
    -
    -

    Les objets avec ES6

    -
    -						
    -let defaults = { first: 'John', last: 'Doe', age: 42 };
    -let trainer  = { last: 'Smith', age: 35 };
    -trainer      = { ...defaults, ...trainer, age: 36 }
    -// => { first: 'John', last: 'Smith', age: 36 }
    -trainers['a'+ 12] = 'Gino';
    -trainers.a12;
    -// Gino
    -						
    -					
    -				

    Les tableaux

    From 510c5df00ca6e38d709cc2b96c428af5ec75673f Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Tue, 26 Feb 2019 15:47:11 +0100 Subject: [PATCH 09/23] feat(fonctions): ajouts des fonctions et des closures. --- index.html | 128 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 101 insertions(+), 27 deletions(-) diff --git a/index.html b/index.html index a5d3bd7..1548cd6 100644 --- a/index.html +++ b/index.html @@ -457,24 +457,116 @@

    Interpolation de strings

    -
    +

    Les fonctions

    +

    Les fonctions sont un peu la base de toute programmation... Le Javascript n'échappe pas à la règle.

    +

    En JavaScript, les fonctions sont des objets de première classe. Cela signifie qu'elles peuvent être manipulées et échangées, qu'elles peuvent avoir des propriétés et des méthodes, comme tous les autres objets JavaScript. Les fonctions sont des objets Function

    +

    Afin de renvoyer une valeur, la fonction doit comporter une instruction return. Une fonction qui ne renvoie pas de valeur retourne undefined.

    -
    +
    +

    Déclaration

    +
    +						
    +/// Fonction standard
    +function a() {
    +	/// this = contexte appelant
    +}
    +/// Variable fonction anonyme (ne pas utiliser)
    +const b = function() {
    +	/// this = contexte appelant
    +}
    +/// Variable fonction nommée (usage assez rare)
    +const c = function c() {
    +	/// this = contexte appelant
    +}
    +/// Lambda / "fat arrow" (anonyme)
    +const d = () => {
    +	/// this = contexte de la déclaration
    +}
    +/// fonction auto-appelante (usage particulier)
    +(function(){
    +	/// this = contexte appelant
    +})()
    +						
    +					
    +
    +
    +

    Déclaration

    +
    +							
    +/// La syntaxe de a est un raccourci pour celle de b. (usage assez rare)
    +const e {
    +    a() {
    +        /// this = contexte appelant
    +    },
    +    b: function b() {
    +        /// this = contexte appelant
    +    }
    +}
    +/// Dans une classe
    +class G {
    +    a() {
    +        /// this = contexte appelant
    +		}
    +		/// Variable d'instance
    +    b = () => {
    +        /// this = instance de la classe
    +    }
    +}
    +							
    +						
    +
    +

    Variables

    -
    -
    +
    +

    Boucles

    +
    +

    Scope

    -
    -

    Déclaration

    +
    +

    Closure

    +

    Il est possible d'imbriquer une fonction au sein d'une fonction. La fonction imbriquée (interne) est privée par rapport à la fonction (externe) qui la contient. Cela forme ce qu'on appelle une Closure.

    +

    Étant donné qu'une fonction imbriquée est une closure, cela signifie que la fonction imbriquée peut « hériter » du scope de la fonction parente. Et donc avoir accès aux variables de cette fonction.

    -
    -

    Boucles

    +
    +

    Closure

    +
    
    +function externe(x) {
    +	function interne(y) {
    +			return x + y;
    +	}
    +	return interne;
    +}
    +var fn_interne = externe(3); // fn_interne est donc une fonction qui prend en parametre y en renvoie 3 + y
    +var resultat = fn_interne(5); // donc 8
    +
    +var resultat1 = externe(3)(5); // renvoie 8
    +						
    -
    +

    Closure

    +
    +							
    +function publicFx() {
    +	let dateAppel = Date.now();
    +	return function() { console.log(dateAppel); };
    +}
    +let privilegedFx1 = publicFx();
    +// Attendre un bref instant
    +let privilegedFx2 = publicFx();
    +
    +// privilegedFx(1,2) sont en fait les fonctions internes construites au
    +// sein de publicFx, qui grâce aux règles de portée "voient"
    +// dateAppel.  Elles sont *closed over* par publicFx, ce qui fait
    +// que les valeurs de dateAppel au moment où les fonctions ont été
    +// renvoyéees sont préservées
    +privilegedFx1(); // => affiche la dateAppel du moment de la création de la fonction privilegedFx1!
    +privilegedFx2(); // => affiche la dateAppel d'après !
    +							
    +						
    +
    Les closures sont un bon moyen de rendre privée une partie du code. Elles seront très utiles pour créer des modules. Mais on y reviendra plus tard...

    Binding

    @@ -918,25 +1010,7 @@

    La preuve en live...

    Closure

    Closure simple

    -
    -						
    -function publicFx() {
    -  let dateAppel = Date.now();
    -  return function() { console.log(dateAppel); };
    -}
    -let privilegedFx1 = publicFx();
    -// Attendre un bref instant
    -let privilegedFx2 = publicFx();
     
    -// privilegedFx(1,2) sont en fait les fonctions internes construites au
    -// sein de publicFx, qui grâce aux règles de portée "voient"
    -// dateAppel.  Elles sont *closed over* par publicFx, ce qui fait
    -// que les valeurs de dateAppel au moment où les fonctions ont été
    -// renvoyéees sont préservées
    -privilegedFx1(); // => affiche la dateAppel du moment de la création de la fonction privilegedFx1!
    -privilegedFx2(); // => affiche la dateAppel d'après !
    -						
    -					

    Les modules sont une utilisation des closures

    From 31cb0e0ce5f27831e7f552420e7f933ae27d0553 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Tue, 26 Feb 2019 18:09:12 +0100 Subject: [PATCH 10/23] feat(fonctions): tout sauf le binding --- index.html | 86 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/index.html b/index.html index 1548cd6..7458ee5 100644 --- a/index.html +++ b/index.html @@ -85,8 +85,9 @@

    Standard ECMAScript (ECMA-262)

    Il s'agit des normes Javascript écrites au cours des années.

    - - + + +
    ES5 (2009)version la plus connu, supportée par tous les navigateurs
    ES 2016Ajoute énormément de modification au langage
    ES 2017version actuelle de la norme très semblable à 2016
    ES 2015 (ES6)Ajoute énormément de modification au langage
    ...Evolution annuele de la norme
    ES 2019version actuelle de la norme
    ES nextversion destinée à devenir la nouvelle norme
    @@ -445,7 +446,6 @@

    Interpolation de strings

    Les nouvelles normes ECMAScript ont permis de faire évoluer le langages et de fournir un moyen de manipuler les strings. Il est désormais possible de créer des chaine de caractères multiligne et paramétrables!

     							
    -
     const person = {nom: Ingargiola, prenom: Thibault};
     
     const stringAvant = 'Bonjour je suis ' + person.prenom + ' ' + person.nom;
    @@ -455,7 +455,6 @@ 

    Interpolation de strings

    -

    Les fonctions

    @@ -518,12 +517,64 @@

    Déclaration

    Variables

    +

    Il existe trois façons de déclarer des variable en javascript:

    +
      +
    • var: On déclare une variable, éventuellement en initialisant sa valeur.
    • +
    • let: On déclare une variable dont la portée est celle du bloc courant, éventuellement en initialisant sa valeur.
    • +
    • const: On déclare une constante nommée, dont la portée est celle du bloc courant, accessible en lecture seule.
    • +
    +
    var n'est plus vraiment utilisé dans les nouvelles normes. On préfèrera utiliser const dans les 3/4 des cas, et let dans les cas ou la variables est réaffectable.

    Boucles

    +

    Depuis ECMAScript2015 le prototype ARRAY a gagné de nouvelles méthode d'itération sur les éléments. Nous allons en présenter deux ici:

    + + + + + + + + + + + +
    mapimmutableCrée un nouveau tableau avec les résultats de l'appel d'une fonction fournie sur chaque élément du tableau appelant.
    foreachmutablePermet d'exécuter une fonction donnée sur chaque élément du tableau. Ne renvoie rien
    +
    +
    +

    Boucles

    +
    +								
    +const ARRAY = [1,2,3,4];
    +for(let i = 0, _l=ARRAY.length; i < _l; i++ ){console.log(ARRAY[i])}
    +
    +ARRAY.forEach(function(element, idx){console.log(element, idx)});
    +
    +ARRAY.map(function(element, idx){console.log(element, idx)});
    +								
    +							

    Scope

    +

    Les éléments créé en javascript ont une portée. Un Scope.

    +

    Lorsqu'une variable est déclarée avec var en dehors des fonctions, elle est appelée variable globale car elle est disponible pour tout le code contenu dans le document. Lorsqu'une variable est déclarée dans une fonction, elle est appelée variable locale car elle n'est disponible qu'au sein de cette fonction.

    +

    Avant la norme ECMAScript2015 il n'existait pas d'autre manière de déclarer des variables. grâce au mot clé const et let, il est possible de restreindre la portée d'une variable au bloc en cours (un bloc if par exemple)

    +
    +
    +

    Scope

    +
    +							
    +if (true) {
    +	var x = 5;
    +}
    +console.log(x); // x vaut 5
    +
    +if (true) {
    +	let y = 5;
    +}
    +console.log(y); // ReferenceError: y is not defined
    +							
    +						

    Closure

    @@ -568,11 +619,24 @@

    Closure

    Les closures sont un bon moyen de rendre privée une partie du code. Elles seront très utiles pour créer des modules. Mais on y reviendra plus tard...
    -
    +

    Binding

    +
    +

    Binding

    +
    +						
    +['add', 'remove'].forEach((action) => {
    +  ['change', 'status', 'error'].forEach((elt) => {
    +	  this[`${action}${capitalizeDefinition}${capitalize(elt)}Listener`] = (cb) => {
    +      this[`${action}Listener`](`${def}:${elt}`, cb);
    +    }
    +  })
    +});
    +					
    +				
    +
    -

    Prototypes et classes

    @@ -705,16 +769,6 @@

    "Déguiser" un objet en tableau

    Les boucles

    -
    -						
    -const ARRAY = [1,2,3,4];
    -for(let i = 0, _l=ARRAY.length; i < _l; i++ ){console.log(ARRAY[i])}
    -
    -ARRAY.forEach(function(element, idx){console.log(element, idx)});
    -
    -ARRAY.map(function(element, idx){console.log(element, idx)});
    -						
    -					
    From 2f575d6536daaf65e8732383d4a236e6cebfca08 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Fri, 1 Mar 2019 14:03:06 +0100 Subject: [PATCH 11/23] feat(prototype): chaine d'appel --- index.html | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index 7458ee5..110a8a8 100644 --- a/index.html +++ b/index.html @@ -638,20 +638,53 @@

    Binding

    -
    +

    Prototypes et classes

    -
    +

    Prototype

    -
    +

    Constructeur

    -
    +

    Classe

    -
    -

    Chaine d'appel

    +
    +

    La chaîne d'appel d'une méthode

    + obj.prop ou obj['prop'] (c'est équivalent) +
      +
    1. On part de l’objet indexé (obj)
    2. +
    3. Si on trouve prop dans ses own properties, on s’arrête là
    4. +
    5. Sinon, on passe sur le prototype du niveau supérieur : celui du constructeur de l’objet en cours*
    6. +
    7. On reprend à l’étape 2, sauf si on était déjà sur Object.prototype, auquel cas le lookup est fini, et échoue (undefined).
    8. +
    +
    *conceptuellement, constructor.prototype ou __proto__
    +
    +
    +

    La preuve en live...

    +
    +							
    +function Person(first, last) {
    +	this.first = first;
    +	this.last = last;
    +}
    +Person.prototype.fullName = function fullName() {
    +	return this.first + ' ' + this.last;
    +};
    +const davidLopez = new Person('David', 'Lopez');
    +
    +davidLopez.first      // => 'David',         own property
    +davidLopez.fullName() // => 'David Lopez', Person.prototype
    +davidLopez.toString() // => '[object Object]', Object.prototype
    +
    +Person.prototype.toString = function personToString() {
    +	return '#Person ' + this.fullName();
    +};
    +
    +davidLopez.toString() // => "#Person David Lopez"
    +							
    +						
    From f77d2acb58ab60e392b77eb940cdcb70dfc72f97 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Fri, 1 Mar 2019 14:45:43 +0100 Subject: [PATCH 12/23] feat(le JS objet): fin. --- index.html | 266 ++++++++++++++++++++++++++--------------------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/index.html b/index.html index 110a8a8..4671571 100644 --- a/index.html +++ b/index.html @@ -456,6 +456,9 @@

    Interpolation de strings

    +
    +

    Programmation en JS

    +

    Les fonctions

    Les fonctions sont un peu la base de toute programmation... Le Javascript n'échappe pas à la règle.

    @@ -639,27 +642,150 @@

    Binding

    -

    Prototypes et classes

    +

    Le JS objet

    +
    On l'avait dit au début, mais le javascript n'a pas de de classe à proprement parler. C'est un langage prototypable!
    -

    Prototype

    -
    +

    Constructeur

    +
      +
    • Fonctions servant à initialiser un nouvel objet. Le nom du constructeur est un peu comme « le nom de la classe »…
    • +
    • Toute fonction peut servir de constructeur : il suffit de l’appeler avec l’opérateur new.
    • +
    • Elle dispose alors d’une variable implicite this, qui représente la nouvelle « instance ».
    • +
    • L’objet créé référence son constructeur : constructor.
    • +
    +
    +
    +

    Constructeur

    +
    +							
    +function Person(first, last) {
    +this.first = first;
    +this.last = last;
    +}
    +
    +var joeLopezPerson = new Person('Joe', 'Lopez');
    +var davidLopezz = new Person('David', 'lopez');
    +joeLopezPerson.first // => 'Joe'
    +davidLopezz.first   // => 'David'
    +
    +// Si on jouait aux cons ?!
    +function LopezPerson(first, last) {
    +this.first = first;
    +this.last = last;
    +return { first: 'Anne', last: 'Pas Lopez' };
    +}
    +var oops = new LopezPerson('Henry', 'Lopez');
    +oops.first // => Anne
    +							
    +						
    +
    -

    Constructeur

    -
    +

    Prototypes

    +
      +
    • Tout constructeur a un prototype : un objet qui définit les propriétés (et donc méthodes) partagées par tous les objets que produit ce constructeur.
    • +
    • Le prototype est « vivant » : si on le triture après l’appel au constructeur, ça marche quand même !
    • +
    • Techniquement, y’a plein d’autres trucs dans un prototype (réf. au constructeur, gestion de propriétés…).
    • +
    • On verra, plutôt vous verrez...
    • +
    +
    +
    +

    Prototype

    +
    +							
    +function Person(first, last) {
    +	this.first = first;
    +	this.last = last;
    +}
    +
    +// On augmente l'existant…
    +Person.prototype.fullName = function fullName() {
    +	return this.first + ' ' + this.last;
    +}
    +Person.prototype.greet = function greet() {
    +	alert('Salut je m’appelle ' + this.first);
    +}
    +
    +var john = new Person('John', 'Smith');
    +john.fullName() // => 'John Smith'
    +john.greet()    // 'Salut je m’appelle John'
    +							
    +						
    +
    +
    +

    Prototype (Don't)

    +
    +							
    +function Person(first, last) {
    +	this.first = first;
    +	this.last = last;
    +	this.fullName = function fullName() {
    +		return this.first + ' ' + this.last;
    +	}
    +	this.greet = function greet() {
    +		alert('Salut je m’appelle ' + this.first);
    +	}
    +}
    +var john = new Person('John', 'Smith');
    +john.fullName() // => 'John Smith'
    +john.greet()    // 'Salut je m’appelle John'
    +							
    +						
    +
    Mauvaise pratique: on copie la fonction dans chaque constructeur
    +
    +
    +
    +							

    "Déguiser" un objet en tableau

    + +/// Toi aussi, déguise-toi en tableau ! + +var fakeArray = { 0: '!', 1: 'ça torche', 2: 'JavaScript', length: 3 }; + +fakeArray.join = [].join; fakeArray.reverse = [].reverse; +fakeArray.reverse().join(' '); +/// => 'JavaScript ça torche !' + +// Ou alors : +fakeArray.__proto__ = Array.prototype; +fakeArray.reverse().join(' '); +// => 'JavaScript ça torche !' + +// Méthodes « génériques » utilisables: hn +// concat, join, pop, push, reverse, shift, +// slice, sort, splice, toString, unshift. + +
    +

    Classe

    +

    Bon depuis ES2015 on a tout de même un équivalent de classe. Ce n'est que du sucre sytaxique, mais c'est quand même vachement bien!

    +
    +							
    +class TodoItem extends Component {
    +	constructor(props, context) {
    +		super(props, context);
    +		this.state = {
    +			editing: false
    +		};
    +	}
    +
    +	handleDoubleClick() {
    +		this.setState({ editing: true });
    +	}
    +	…
    +}
    +							
    +						

    La chaîne d'appel d'une méthode

    - obj.prop ou obj['prop'] (c'est équivalent) +

    Supposons que l'on fasse appelle à l'attribut d'un objet: obj.prop

    1. On part de l’objet indexé (obj)
    2. Si on trouve prop dans ses own properties, on s’arrête là
    3. Sinon, on passe sur le prototype du niveau supérieur : celui du constructeur de l’objet en cours*
    4. On reprend à l’étape 2, sauf si on était déjà sur Object.prototype, auquel cas le lookup est fini, et échoue (undefined).
    -
    *conceptuellement, constructor.prototype ou __proto__
    +
    *on le trouve sous: constructor.prototype ou __proto__

    La preuve en live...

    @@ -777,29 +903,7 @@

    Les tableaux en ES6

    -
    -
    -						

    "Déguiser" un objet en tableau

    - -// Toi aussi, déguise-toi en tableau ! - -var fakeArray = { 0: '!', 1: 'ça torche', 2: 'JavaScript', length: 3 }; - -fakeArray.join = [].join; fakeArray.reverse = [].reverse; -fakeArray.reverse().join(' '); -// => 'JavaScript ça torche !' - -// Ou alors : -fakeArray.__proto__ = Array.prototype; -fakeArray.reverse().join(' '); -// => 'JavaScript ça torche !' -// Méthodes « génériques » utilisables: hn -// concat, join, pop, push, reverse, shift, -// slice, sort, splice, toString, unshift. - -

    -

    Les boucles

    @@ -947,113 +1051,9 @@

    Classes ?

  • Une propriété peut être une fonction
  • -
    -

    Constructeur

    -
      -
    • Fonctions servant à initialiser un nouvel objet. Le nom du constructeur est un peu comme « le nom de la classe »…
    • -
    • Toute fonction peut servir de constructeur : il suffit de l’appeler avec l’opérateur new.
    • -
    • Elle dispose alors d’une variable implicite this, qui représente la nouvelle « instance ».
    • -
    • L’objet créé référence son constructeur : constructor.
    • -
    -
    -
    -

    Constructeur

    -
    -						
    -function Person(first, last) {
    -  this.first = first;
    -  this.last = last;
    -}
    -
    -var joeLopezPerson = new Person('Joe', 'Lopez');
    -var davidLopezz = new Person('David', 'lopez');
    -joeLopezPerson.first // => 'Joe'
    -davidLopezz.first   // => 'David'
    -
    -// Si on jouait aux cons ?!
    -function LopezPerson(first, last) {
    -  this.first = first;
    -  this.last = last;
    -  return { first: 'Anne', last: 'Pas Lopez' };
    -}
    -var oops = new LopezPerson('Henry', 'Lopez');
    -oops.first // => Anne
    -						
    -					
    -
    - -
    -

    Prototypes

    -
      -
    • Tout constructeur a un prototype : un objet qui définit les propriétés (et donc méthodes) partagées par tous les objets que produit ce constructeur.
    • -
    • Le prototype est « vivant » : si on le triture après l’appel au constructeur, ça marche quand même !
    • -
    • Techniquement, y’a plein d’autres trucs dans un prototype (réf. au constructeur, gestion de propriétés…).
    • -
    • On verra, plutôt vous verrez...
    • -
    -
    -
    -

    Prototype

    -
    -						
    -function Person(first, last) {
    -  this.first = first;
    -  this.last = last;
    -}
    -
    -// On augmente l'existant…
    -Person.prototype.fullName = function fullName() {
    -  return this.first + ' ' + this.last;
    -}
    -Person.prototype.greet = function greet() {
    -  alert('Salut je m’appelle ' + this.first);
    -}
    -
    -var john = new Person('John', 'Smith');
    -john.fullName() // => 'John Smith'
    -john.greet()    // 'Salut je m’appelle John'
    -						
    -					
    -
    -
    -

    Prototype (Don't)

    -
    -						
    -function Person(first, last) {
    -  this.first = first;
    -  this.last = last;
    -  this.fullName = function fullName() {
    -    return this.first + ' ' + this.last;
    -  }
    -  this.greet = function greet() {
    -    alert('Salut je m’appelle ' + this.first);
    -  }
    -}
    -var john = new Person('John', 'Smith');
    -john.fullName() // => 'John Smith'
    -john.greet()    // 'Salut je m’appelle John'
    -						
    -					
    -
    Mauvaise pratique: on copie la fonction dans chaque constructeur
    -

    Les classes ES6

    -
    -						
    -class TodoItem extends Component {
    -  constructor(props, context) {
    -    super(props, context);
    -    this.state = {
    -      editing: false
    -    };
    -  }
     
    -  handleDoubleClick() {
    -    this.setState({ editing: true });
    -  }
    -  …
    -}
    -						
    -					
    Attention il s'agit de sucre syntaxique pas d'une classe comme en Java ou .NET. Le JS reste un langage prototypale.
    From a8ce3ba6693d47f1c062bd52cdf05fa8dbf9b80a Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Fri, 12 Apr 2019 14:22:58 +0200 Subject: [PATCH 13/23] feat(la programmation en JS): le contexte --- index.html | 222 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 145 insertions(+), 77 deletions(-) diff --git a/index.html b/index.html index 4671571..57216b9 100644 --- a/index.html +++ b/index.html @@ -623,22 +623,141 @@

    Closure

    Les closures sont un bon moyen de rendre privée une partie du code. Elles seront très utiles pour créer des modules. Mais on y reviendra plus tard...
    -

    Binding

    -
    -
    -

    Binding

    +

    Contexte

    +

    Le contexte d'une fonction est représenté par la variable this.

    +

    La valeur de this sera déterminée à partir de la façon dont une fonction est appelée. Il n'est pas possible de lui affecter une valeur lors de l'exécution et sa valeur peut être différente à chaque fois que la fonction est appelée.

    +

    Les différentes évolutions du langage on permis de mieux définir cette variable indépendamment de la façon dont elle est appelée (bind, fat-arrow...).

    +
    +
    +

    Binding implicite

    +

    La valeur de this dépend donc de la façon dont il est appelé. De manière générale lorsque this est utilisé dans une fonction il aura la valeur de l'appelant.

    +
    +				
    +const monObjet = {
    +	firstName: 'Thibault',
    +	lastName: 'Ingargiola',
    +	fullName: function() {
    +		console.log(this.firstName + ' ' + this.lastName)
    +	},
    +	strictFullName: function() {
    +		"use strict";
    +		console.log(this.firstName + ' ' + this.lastName)
    +	}
    +};
    +
    +monObjet.fullName(); // => log Thibault Ingargiola. Dans ce cas this === monObjet
    +monObjet.strictFullName(); // => IDEM
    +
    +const newFullName = monObjet.fullname; const newStrictFullName = monObjet.strictFullname;
    +newFullName(); // => log undefined undefined. this vaut window.
    +newStrictFullName(); // => Error!!!!!!!! this vaut undefined
    +				
    +			
    +
    +
    +

    Le problème

    +

    Comment faire si je veux utiliser this mais que je ne maitrise pas l'appelant?

    +
    +				
    +var name = 'Mr X';
    +let obj = {
    +	name: 'Joe Lopez',
    +	greet: function greet(whom) {
    +	console.log(this);
    +		console.log(this.name + ' salue ' + whom);
    +	},
    +	greetAll: function greetAll(first, second, last) {
    +	console.log(this);
    +		[first, second, last].forEach(this.greet);
    +	}
    +};
    +obj.greet("les lopezs de France");
    +// => 'Joe Lopez salut les lopezs de France !'
    +let fx = obj.greet;
    +fx("l’atelier") // => '"Mr X salue l’atelier"'
    +obj.greetAll('David', 'Joe', 'Guénolé'); // => 'Mr X salue David, Mr X salue Joe, Mr X salue Guénolé'
    +/// Le contexte est perdu au travers du foreach
    +				
    +			
    +
    +
    +

    Solution 1: la closure

    +

    On fixe le contexte et on fait un appel explicite à la fonction.

    +
    +				
    +const obj = {
    +	// …
    +	greetAll: function greetAll(first, second, last) {
    +		var that = this;
    +		[first, second, last].forEach(function(name) {
    +			that.greet(name);
    +		});
    +	}
    +}
    +				
    +			
    +
    +
    +

    Solution 2: bind

    +

    La fonction bind permet de détermnier le contexte d'une fonction qu'importe la façon dont elle est appelée.

    +
    +				
    +const obj = {
    +	// …
    +	greetAll: function greetAll(first, second, last) {
    +		[first, second, last].forEach(this.greet.bind(this));
    +	}
    +}
    +				
    +			
    +
    Ici on crée donc une nouvelle fonction pour les trois appels dont le contexte vaudra this.
    +
    +
    +

    Solution 3: la fat arrow

    +

    Cette notation permet de "binder" automatiquement le contexte englobant.

    -						
    +					
    +	const obj = {
    +		// …
    +		greetAll: function greetAll(first, second, last) {
    +			[first, second, last].forEach(name => this.greet(name));
    +		}
    +	}
    +					
    +				
    +
    +
    +

    Binding

    +

    La fat arrow c'est la vie!

    +
    +					
     ['add', 'remove'].forEach((action) => {
    -  ['change', 'status', 'error'].forEach((elt) => {
    -	  this[`${action}${capitalizeDefinition}${capitalize(elt)}Listener`] = (cb) => {
    -      this[`${action}Listener`](`${def}:${elt}`, cb);
    -    }
    -  })
    +	['change', 'status', 'error'].forEach((elt) => {
    +		this[`${action}${capitalizeDefinition}${capitalize(elt)}Listener`] = (cb) => {
    +			this[`${action}Listener`](`${def}:${elt}`, cb);
    +		}
    +	})
     });
     					
     				
    -
    +
    +
    +

    call et apply

    +

    Le fonctions call et apply permettent de fixer le contexte au travers du premier argument lors de l'appel. La fonction call prendra par la suite une liste d'argument là ou apply utilisera un tableau.

    +
    +				
    +	function ajout(c, d){
    +		return this.a + this.b + c + d;
    +	}
    +
    +	var o = {a:1, b:3};
    +
    +	ajout.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
    +
    +	ajout.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
    +				
    +			
    +
    @@ -815,112 +934,61 @@

    La preuve en live...

    -
    +

    Structure d'une application

    -
    +

    Déclarer un module

    -
    +

    Utiliser un module

    -
    +

    Gestion de l'asynchrone

    -
    +

    Callbacks

    -
    +

    Promesses

    -
    +

    Async/await

    -
    +

    L'éco-système JS

    -
    +

    lodash

    -
    +

    moment

    -
    +

    i18n

    -
    +

    node.js

    -
    +

    babel

    -
    +

    webpack

    -
    +

    npm

    Les types de base

    -
    -## Les variables - -- `const` Variable constante qui ne peut plus être modifiée -- `var` portée globale ou locale a une fonction -- `let` portée du block courant `{}` - -> A retenir on utilise `const` au maximum et `let` dans les autres cas - -
    -
    - -

    Les tableaux

    -
    -
    -
    -						

    Les tableaux en ES6

    - - -let arr1 = ['one', 'two'], arr2 = ['three', 'four']; -arr1.push(...arr2) // => 4 -arr1 // => ['one', 'two', 'three', 'four'] -//le map -arr1.map(element => console.log(element)) -// for…in itère sur LES PROPRIÉTÉS ÉNUMÉRABLES de N’IMPORTE QUEL OBJET -var arr = ['hello', 'world', , 'cool']; -for (var k in arr){ console.log(k)}; // => 0, 1, 3 -// for…of itère sur les éléments d'un objet itérable -for (var k of arr){ console.log(k)}; // => hello, world, undefined, cool - - -
    -
    - -
    -

    Les boucles

    -
    - -
    -

    Les fonctions

    -
    -						
    -function maFonction() {
    -	return 'test';
    -}
    -maFonction() // test;
    -const a = () => 'test';
    -a(); //test
    -						
    -					
    -

    in et delete

    
    From 8007cfa3a8b892e5c32ec7d17635266bc5c48cb4 Mon Sep 17 00:00:00 2001
    From: Thibault Ingargiola 
    Date: Fri, 12 Apr 2019 15:17:57 +0200
    Subject: [PATCH 14/23] feat(les modules): fin
    
    ---
     images/structure-application-2.PNG | Bin 0 -> 9953 bytes
     images/structure-application.PNG   | Bin 0 -> 8407 bytes
     index.html                         |  58 ++++++++++++++++++++++++++---
     3 files changed, 53 insertions(+), 5 deletions(-)
     create mode 100644 images/structure-application-2.PNG
     create mode 100644 images/structure-application.PNG
    
    diff --git a/images/structure-application-2.PNG b/images/structure-application-2.PNG
    new file mode 100644
    index 0000000000000000000000000000000000000000..c4f9b9a6f0dde1dffa33018e522a8e787c918114
    GIT binary patch
    literal 9953
    zcmb_?XH-*Lxa~$1^w7=$DN=2q8eg2m~piw*X1t#dGg)yz|Dp@4h$2`;n2ccCz>S)>?DTZ+>&_gqs$I9KQ+v
    z1^@tuvC$1H0ASK!eC$rMFs@99X%HA+Od(c=*MN#a;Uz}nr1ziZe*!>t5*y9!6r+9S
    zu91BR0C0Bx{4n(dz4HVB$#CNvf7(R2tY(vIU2q7ZQg+*t*>OzUox%*W5CzSJ#i`JC
    zwg*>F>$@`XaTZ=M=yrX0rW+C?K6^9sZ;y~_!rwa8BzGpxG*-5Ly1VCt%gL9z6-5c>
    ziUJBn+CL{+Ktm^eylr#W(~ysd_6|{cLm`1fn&gAa+ZnC+)dsw-61mfXI_yGih+e0#
    zTx(;GM`GN9_NP;dHwbYbF+_on1I(d$-=-{4it0D+dpBzO=Tla;EALow!C?7
    z?JoHt@wW!V?xNh@^byVz0mPiOH(ASFZ_%$o|
    z%28jX>`Hs*P^-p>#X(W@A!VkWK6m`C_h{&tj+|jL%*~Z%jhXLjk)UXa(a;+|l8~xW
    z!}9s0aKsNio3~&8@?{4J!8hLoKl>_pSc`qeB#4afdID4$i@X09(bvow(n&0
    z;uY>-LKKj*WP~%aPQRErUy@Hc_CsZDErYxxjW}HotoymRxKUovdZ$%SNpJ2%i6Vja
    z!}a6OAsR6!UZ#_Nh^tp8qZ0KCLrhD{mNGJzyYy@#+!#IGc0px=+31}Q>6#_S?pPl$
    zTMD^&Is0gy5#9)rwg}wh)JdJP`eSIz-KJ2p_zD2|b{@lL#QEAO*@+FrdQ$;$K?7KX
    z{#wBqbnJgFAq$r2>hO6D;F93a6-Sqo_Erw)ck#~m;)ak%Y_;llzhAA<1+G4klTcGu
    z7Je?OBj|#p?{0kJv5XBuQVG1^)*Y*e{h3GT0N239bu96$iI)qinYz}DKFF>Kp6kB5
    zkbN&l#W8B*V`Z$`w+L}<`p!u0R+5NTcg)lAHhR{^RLD@=5MnI^yA^(3<5G5{u|=lW
    zpkXL=&soqSOFd=Es+g07_Xj1p}Dx
    zT>1_?8V){sRZ@8*U7yPQqPs<+A(|fV`=MVybo2abY!g%Q$8x69ysz9(&-9#hb04{i
    z4-42R%}IZ-oMAMZf!dvLmnD+itILvtoeIjcXIp4neYF)n!K2?A{F)jXk--j%p(4)U
    zw!-I4oT!H=X#<#|AW8B>U3JKHAF#L>KCz>(r&m5)?ku!$TfHKQmtu@$OI>=oT-gH^
    zUwhadpXz6O=}p0`%n;>|*UAi7-6JB@7_ee#tn_1Un*MHUFKie2WFgKSl5?gTYW>o4
    zwvqc;Y~Gdmo>l+7!kSSPgtKge?mO*ULpR%IyD1sH%$E|}qa(hY-%}DOFhA+bV|v|(
    z=iwm2sjF(jQrHfn4IS#$4xWO*+WI{<<)=e~dJ`oU2=`|jFRqDS^T}{j`!=DS4zM$f{cR)eX5-j~;Gin;r_@)MDWYn%ff&4t7{bdoICG!Sg_^4Rf%6
    zF8zE!7mKHfSJ)_rkldMdaN4FJ#&*(M={&&DXiR<5}|A*&(?G5Zr*h9BFccWekQ{jnG9UneK
    zyyXP0dV5~P%v{zE{nON!62EI*)DgcVHdN(H%XGWz8uoUeW0rXTOXP?UH&6xtd<`bv
    zNp-lUrDGbHqr%hUP}}?rThFFHQtBKwzIMLl$Ejqny;0!&=YjS=CYQzzq)IX}A&Q~F
    z5Vf!x8Aq)He*sZ#wTb8pS7E?y)B{p{=V&jhY)W}fgd97&SyRo&%Zi6Z?SFhv>fB!p
    zs3^;b;8G`u4YuE1r=%vPmxfp5eeGySfKD~&5Nw9_3Ts;$6|7D|H18{59y}=a)o6-7
    z%&v0ZXZB9@%V-MU$}ssE>yV7)h2s3S*gE7fZ=F)5BsNk}I$+CWfHbNqajP^>S42DF
    zZlNw9r=XKQwee*zLt<(F9n10eGMKzQ-m(=}67sgrXAn3y?N^gf%(JNuOV2Uy?VF9N?B}qCLE&@LQu6xzn2th1Y^m#8}(5M^YL=i?6PmYWCmk4w9TGRJ1e$s&Deg+
    zfI9C^Sq!azRrDH3fVlrDUr2&S0T72P$y4VH;=$SW_1#7>+-@b=GwCUs_>jvY)?v>y
    zs}HszR?{XHh%a(qmoE({X~YzW3tyHCe0>b!y|bz2Jlsdc#@BeBx*#ryLm
    zq`CBxH1E~cELtR*^rD`8$#N6n*m@30D;$_vIK;kpmc%ZrLSj!*9j{OPOVD*
    z#jgLx*{>}63yiN;Kx&%m0&Q)#FT#;MHV`%K7iG-A7ioLrz&ozzSA<14gR
    zESktvzpNrC`G}=+d%*&{{M6#SMoi5ThGbiR@}4J|^z{2Dii1_N=lqkZhAuYwVY;*I
    zdfawlXE$$l;^6vBVZqW&r{UnFxWcy(ivv`4{sIMV?OeM3ftjm+Mauhco17%K)!BLn
    zmQ1tq^0t+ND~_Vn!(cgJF(=1#%@SXpC854)V+w;#T^3yZw!~yCcGM0I+!vqHSD~4(ZEbjvQO#FJ`7uE0ju69)6T)#JAw;s
    z98<;gqFZ_s35Cm4UFHu{pJy|&ay~{5>%5P=2oJsgo;&larb&4AX^VW)_wCRX8Vm0LA{NNyFK&Od!83GX7r0fbdXV{DrmCp-44_KoA(t^wIPXf
    zyV>w*?w3&j0KJZd(!pP#~BB;KdK2UA_v1@B{s5>-^tfYafZA#l4BEcPH8y4

    JMF#@GabySwJ#g3EM;u1 z>T)s378}C819$B%Gw{P89K}QJwu>bfYEe_(Si2we^BNnPTA+CWl6e}+@eWAM(Y>%& ztINwlRs3WOP1*|fD!`|>;rBk>_NlWbMaxWAb9TDSIDtd{UjpzKG5#B{o)<9A%?j-4 z&e4(LTH#rl{%pXP8+<6OBYIIM@o1&hplx$N99s_n=9ke7&4_h@Q59O1%N*)7CpdxE zA`@Uc%XaGAMvod&W}u?|ILhYOQ7I1Vb+RqO~3MBNdH~CRNOcZ9IP{y(fNd(n`xWQEK>a&CjW}sDyI$yFm25q&* zD&TY_`Oq6%2@(r^3*s8suevrK!A!3k7;|I6Ahtf~K*9?PTrq>itSxjKQWDDF~ zF#!TQ!ek%^$3S)J@}U*lsrGU?SSHf-`aWD>T2V)z6d(GrL=n_dB5$Ani)3+^&zq3> z;{N2t75pu95tucmAn#>{liH`gTfn7sIZ(qWV}Bko{nTeW1q_jkWaNYYklnus;~&lT zZ&tw?z&t!2x~+e!zB{a+=XPh&?Ay-H&HY6~sZMXb<`S7&n#C~N!Tsh7w`{p5FI~-K zuj=CYFySeVK~TFp{3-)DhIE@H{E52Ufi1x@S=t!+7W&@aZ`sh0fg3deBJ_(Iz&j~Z z?COM)V9tHtkchcw0W*69ySP3u)LulQ-G-pafQzR*MvXWny4D;NQ0H%6mr#8>bM=p+ z%CJbR4^a(~-@Sf;f1O`yXDfPyjV4n|pM}$!;Ms(uFmT(xdmPlEgljSbLLEGa+7KgD zM^D;)f=AVDQYV)Lh()+li)uB_72ocYLnG+BN`1FP*4v`Y=aeuJ&aBUO`VtHql2GrE9xA5o28yyyjPQ&wH3ZD z%E6`cz73V-6?Si`dbupzz(luKDdUrS3cC%|5dCyZf;ID22832-@-jlsR!(ZBvOF&x z-5!6rxSR65&kC>7GH!)nTJ)|-$;xTYR<8~)fT7Xr;J+AX3scEMZ@`6;(oJM6Q7L8G zE>4mnxFD(1simz0gJyEUa2{JZ4KSE!m?)G-vykxiaonnJ=8yTxAZAYCm#35T+NxEI z8f-5{ky1EPzdsitoXv^!GTrZMpRyU)u*ja|3v7#&Id}ceWvYF0GNgsnaz|TIBr%2C z__xwZiArPHTi~>;s-uYFAHLY&7{5)Zp}tLCP!hHG<_?ZdQGwY_{{@=enYhn7kBmH)NzTxaZ}01we$yV{gd@Pe|5WgRZ#wJ)FWE&0M@L8QBpV$%7H?DxDjDxg!&I2u6C|O|Ohktjv z4C|tI^3;{?w871qbHF#&e-$qO-UR;(Q%PYEe8* zx%7EcQ1meJf_?uu5F#OqosRfsw2vLIo_S&}Tk`(-I>J|G3gfNJek07o-;R@jxUSqf zbk4NGnzklZyd`{R*+c7(fdw51h*bj>M*>wj-g_3`-W(<~gT{MIS5` zFOP#XIeH79$$BIUqaGf;UO=H6m943frk;-!OoqmlJE{7mPAAHEoY5rZMgJs~s0^L7 zEaJAgp<`Qj0L>-9{K`%CUBj?Zg8*y#O=l4t|0>eEdaj^$);=T1j}pAUky5f!-6QI^ z;xST3Q;CiB-d&Y-3lAvGY~tF*R!Aan>!^|O3H&AUYYJXIGUSPOhIyR-t^z3hM-?Y?oYfmdeR%757dE?QGB~l8|e>_*>BqF(bj4-eku#hg6dgyN^?06Sywf%vl z=+BXGm=$QHW_{&;;2wGI(S+WEo)g6S^8z~~RV1?h%c}V=a)$Yk zM1#Ahvj2E=;P`tFZ^uG>fKfL9yvtia35n#M=65-IQ?+p2uI~0WW1%OHnr!K}~>K$eLrT!q;=kp{Bzc5in5n7MA9Go&{__J>>GckSei8tPSI&<%>wSSjJQgV6U3|h4&dqnA>FzME*qQ@ubERv2#f@1#Fi$&mX$r4+1|nC`DhF@Yv{}17I;w|; z!a2xElM!zY>uvGrJ@~ClL(rZ(_lAJJRDV#z?S+cVS5!sAS1{_*>cb#R#K!U+!W%q? zKUh}8T;|9rKi_>-E}%BINx+{;UB@022ASjXY4H!>JG7sUdp@D$g`EFUn0MJJEVu-2wO912qVj%e1L{Ta#B zsF?-Kk1~Bri$eF2(zrg)*zT)q=Ug$UY|^Vcs4SK|FUe_ke=w`wX9CAQL`K?5arw~u zwk;7fPyONTylHi1%~B52*fz6mP1lFrJke!jap%iqCA!12kjX#Nh0ldEI=Mk;BV0sG zR`U6U<-;NY)BvMG@amnd52Ku?Aq2RyoI8=_eOqzIZu!$X%yM@36*Sbv&l-P@Wd_(- zQGLMwGg!laI!h`u#0+s_wOJYS87tR zO#qOcoJvw?hu@A^E*_Yv?oo}Wu0w@>DwD?Ll1YeOx!BWLo?N>2I) zT&QFr7)qTy-1z>GToR&#CX1QL)x=P?|1NG?gw`cihY&myy2de!?$ zQw4o;@~jZR_sAb~4=dp@(@dN`>jDop-T!PT*%8mtiR)i`q&GE&`nK#Tlyp-3!Ty3X z%5-_IzqmTjl3)@ylYTWY@Do z3_4WsX0g@PA8VJHf8uS31OR;h8}a>b-SMmLM?WL&tqPUyp-23j(uyc{yWf^~@s?XS z1>hx*y^+OwN!wQM*v5}cLJ8M6z@$@r&QT}* z98;X$wlKJPN6X%*!q^k_Pm#H zww8ky9=)3a<>jqPrys_bN=aylIR>}1!2RE}-N#P2++&asdGQYNI+7z7OgjcfD?1-0 z*;LPk1FiWBsF8cOc3W>DS`4Vzu6aU3QtUbs8B!PdBm3T1P>v7t6qhT9w%hz9-EKj3 zJRo^_kuY)33TJy;aOz0__Z|Me3hB^5=5NcdF7a0Sq!qxyxsAC`JbZAtF!;(tR<6OO z_~WPuTG*`Lp{6dwz*GT(;iyE`BC+pn z70H)lS^Rtnp>O^?{AoA}PD#tzmT>i=*+X}%tTNi`tL#zOjvmvly;WW<3EtG=?6poP zVa}s;s;}=0y=#-M5@sU;wY{ekQvgbw_Z>-MJCu?*G;=HJy9H*N&v1P)cK&@qnta2o zrYMIK&J>$B0@1Z(CN?O#zuB*MffYxW1o>8y*`Si6wqJK@%LI@jrlu=xLB;zeV62H} zH3^;(#9TG%d2CiOA|^WfK!$d81lXym`7_hk`(2xk_ZD+wCWNs=dqM2P3K3lwnfkRp zFIaFcdvjab_j>>5AH^dKVbdU+|OaqH<$P7VW%Q zs&oMJm1s%tYOQAyp@BZ=#IE8@OjiW9$gq@bJ?zAA>VhS%1RVo$U4>bT1^8r^Fjq}6gcATr{}-;t|GZ~+ zF6u(bCt~6x*|3{+6%&iETD(qGU1qpGZDXf^M14NgoS!pL1z{K=k}11$_@+?vuB!J* z3kBru041~eq9ZvSiaC#hUS7*!d5$k&&uXW6Kj+$0C6J?6;qqwbWzA~=XH5?_iPsckE4jXK{e(y+ z*Tg4g$A$Xc2ovFpxWSur7kIhsbFqb@ijhD`Z^V1$tL=>CXY{agyV(6epjcCeg4nxl z#Q7ajlPnA+YZlqUG#i>EP3PH&-hQQUsw2a1Fat?3ZlInA#l$hp(1CPe3Gdpbz}VXX zR;CWXq9~~0!@fj*)opJrv%u;1Ofh?B#WfhGegB=M{tqwyw7fT58`r;9ZPF9!Yz-6BT{oqpxlhZwaw4Ik`%k#tlu6f2y!?|#>;#(4kaF`&56iE zS5G01<7C=fyT)`}0Lb9lV*gAcCMYR@$;w7M+#;^rkbRu0cq;%P39Nw6-O1cIn;wRHhFdDRCrK zOZK?-wx#|g4z*R`Gj>6ae?;R@Sx3fLk!HhETDU1AkGFiXx@iA7BWq)`IiV;ohz(#f zR8_)&owRM~dwP;`xE(*3rG%*G%6L6a`+Otv` z?M|nFUnWX-jKk3N;h!5pzEc9`uB@^+M(;1s{+GhgadiST*!J5-eI zL%8&2Gy1WOBW}Ag**;sd_)~S*&gKpH^ugaGfN@3;UmD1sS&30$XV0Ag2S&g({i&a_ z-Q0WhZ#ndY1ktS^A=q2BlU?IKQeCtKzt?A{fIOQ|Iz~QS7Sh$jjpfhJk*6n`DBipy ziT=_jWB++%WP{G{3X%HUQU z2@>9YcIX&mBSYfg#@FHD#FC2g_IRAJ@z>dL_>2*aKHzWXbIoB4mT(H*QbHL7^ zq6-=WUu^>?{~GvVfDa5D_`zwX)L5L&|ELwJ<6>-4+d9CiJK~Ez@=fP}WzLN1DAmH; zu01~WChu!+Lw$84J5PFLUd!l}iDen6A(0=QnpFNCdZbz~r^_~fL4)DHrDPR6>X!5Z z741y+Ri5EL?(udA3-l`>>zTg$xatiPoQjSyJstMeO2{!>Mx>|2k4!$$G?9hQqq5I{ z)10)Jq;1tuiE|e;V%R}y+KSEztMrzSz8RY8S5(nzZD9-jTs&dM zqCwb;qP)5!Dv#-44^LCt@{m5vgnVgJChf4VvJ^OF%n6)7^?y^O{{wQY4dYnS^{#pf z7w|gF=Hk`RO61GjpFb=xpp@_*tmar}o>hKxM0K_VU#n38;z^RjO=ixH_aj%tZqteoqiD%#lTI{8?Z-lc`vQ-r7Cq;G@!V?9$tF| zY)Vc7Gv0=P_~yQHK4@Kliy*}|S#rkg2++Yp!F7+K_p|#^o58!3$CNIf;N!5JsEL9# z=GXj;4mfOu-U+&*p6GJDd(ZNEz{zGv4{0UDgBom=v%#~Jakw`d$XVfdHSL`1MieWG zAe5<)bvfgA{S@pR_4WI@XWP7nn=kleYG0=9(YKW}oQZ3uVQ{F;k7LPrcZXv-rjj|C zxyxvf3&vq{#^NFFt6-U=u+Yl21=SC&8?lw^bJTj5({0%U(Xsqb+}yvIVf$nZ5L12k?vCDB}8e5Vbwv~w6ZJ~<~T13u9?DPtk0 zF`pqfJFZIo%du-iF>clhhS#L@qbmy*v12g1dRp19fhKNM`VLEuS@P4%996@>ruzZmApBG9g%gWuFGwp>$A}m8ZINdRD=xrAa=E_9GE4#S-SznzLQ=FK z;KRgsRpr+K_Dkt@z3IR6UO$jdcsDh9(D=mdprnZW3Mhlx=AdHT?K9G|z&zD4azu*C z^MEk>sUYGCag*B=)H78S#6q+++R|nPnqv$}d&knSEFH(J-=A%M($KH6WxSRK80%ZysJQ0(_x}KhB9i?8 literal 0 HcmV?d00001 diff --git a/images/structure-application.PNG b/images/structure-application.PNG new file mode 100644 index 0000000000000000000000000000000000000000..5675f10bdad26034925b4ca68b485b10ed905827 GIT binary patch literal 8407 zcmb7qcU)83w(dey1Qj;YRKTG0B26|;42WnznsgB9pr8~1L68tcL8S&rLJ=`EX`vXZ zA^`Rasd?mqY2d(V6O{;__UYpyag=N#i3-}uIgyJiME%5{

    RQ8Gd08jScx@dY40Px7eTW$xybI!Yl z4#5Dx-L`kIkpfCQ0YJ>x$l#)NnDau;5>nJIoD}X@8f9P;H*BQLx@cuI&2Yn@Qiuq+;4)g@u z@DB;~Wo5P%YOD7@)r2pi&ILzJoeN$feSzKY(;|oWjob7|-@19fuW34Gsi_PAGSxac zfa-^EK0#~3v^`}%8+$i+(KflE;nGv!Q=~eTg;3W1uewZ`t6AXrDpr4 zl`qD`J5_{GNir$EH+xB@M-Z2pc^F`Rs)4IzDLFM-#}~V>=7$-JL6?IU$7d_O4-^`| zmILQO&d^V_hZEYF9l`zbLQh(%dBX5<#sA zU9chYAnrO^s`ENM64gaGzJg0+SQVRLR2i#ji4~6&%;fWAWC8DkPSl!US|9h1BWECi zKmUk8RU0u9Tzo4D^Izz&42#h4SB)|d;<_rJme3ra$NBDy|DwxRd#_J#MV0W%)A$83m7E&~Ysn z5L=Awgko%SUD(eL!urWm&Ow|}kF~mCnGY45BO}iPGamU&BfS5_b7q61`Gt@>;Vy<5 zjvC{y>(^&BhJ-fPS{j-ha_Ahug48>B%>J5)wWHK{7`D+M;*aRLG(4azs-_R6RKAr1W+Cl%+GyK+78M1M}9tR!^9J^{Wgz8 z$~AP9+*#HFT(=TUpfoZTVy{<#HXnaCa=5s%m-ftCL3n5>xn%os`J}PQv^T28gOrT% zOP?YIj~uG$>zt`UY(ELIJbEVAq8r9{!C$VZnld*E&w=?lYd+d0&yqQ0 zoQJTZ3c--a^?8;yYu#vZF0rgWjQiMQi9C#DlTx95g)f|dtivEHVk{Zzl^C|0NvU15 z*4V>IZ{|-@yJ56f0`W$Lj)WkeM9@g4lwKZwub>j5@#1&ZHZ`TCy%e0oksP}lcDPKu<7*2k>P3yN&Co zu`HIf?bHo7?>3gTuka`KVuW$Bg)XD=ssHxlO2E`pfjQE+y6Cwr<~xNj58PP!0piN7 zZXv!(+vaJ5E(}U1%&M6)XXj}f0#o999eMUTkT< zG_QSs@dm!BY20FnjDXS$IIF5RO3QmEQhD^CSL7fSmWs|zny=w%(SkxkJzWm432@IE zGc>GAqLi2x(6L>Z{iy+Cv13JbEO@$0d-Dc2qq-*wLUe%e6@S7H$U_%-J@JfprM@bG zk|l45#DI!fM*hL$(&8xO&SS#8AC|Iv@Zmv<6y?JupSzXbW2~&}aN+qI1SL-M?d2D_ zHinAo4wx~iVxz90%tO8+**~3a={WP%sx&0z67?~MP`AfGaS(B*HL4-gJW{P5BS4ES ztX@3;j*yC+31l&;HjEW{2tm-H>QZvPQJ(SZMve51INF>$Jn^e%zeHW2Z+-;7_=oT3 z%-r*!w=EmOlml$178(?w&$By$i)?r1=Gfw3#0_-_mU`9bJ!#%Fb<8JSLe}9c0r*N>IYM zcoF-%q(dt4&eXsPcnXh6d`BltNmM70VqmEzyA{J|=PWkIOnX*y(&x@tD0frspw}aZ z!%NKk)GO)R^!BxiG~{ZHCMJY@i~JI%O<66?w2ta=n>ssd1=-C>;hD)-Ve*#hN|om? zB9HtYt;Ud))n(`)9u4Mc^1YOhLX)NN1mp!S3)1uUc)M(&)D62X(#D30_$+y4XP{<`E% z_*b-BLBr)v0nabus0F5->FMd+6`HjtvM$_vz?|tyek#e98*X9%<=_@E99-)jAHTuk zkGL@*qQ$hvS65s56Ti*Pg=+IZkkB{3KPMZoTN~b>4jdQdOGSpNi(JujK18sT#P%a} z>w68HvdL^f+c_213*9J$D_fE!^m^C&_U)#-^ig>7vySROfq?B**V2KAxRFbx^+G8X zuNBO1FF^=ytwBHFF-l`^S5zybrmswJ@w&b+F@cVjUfad<`~&iShx%3i6Y`!9YbURE z`*|7ZJ;FC_tkC8+NAEW*tNvK87BW$qzV3n<7&72cHo9pBEki!C$gvm@Bws{b=esWd zN;6ylC-9_d4c{6-vam~jOYg>;_9x-gSgWDg;4roD$i#`|xK*efTF=QLEbpE?_%7nu+JQ_7 zzEtvS@9M;>P<_-j4QGMkCWPu>olPF6?=)T0W-0c!KSx)b=*}MsJS)i32_KYkOn-#PiHsLZ19zsC&PjnF$~L`HKrOg!_$O+~UX9R*{oU#6BO9^RPQL_?SA@ zGGl70s^2&2RK(#Ys}|564_e{)1NJA~D(3TFd)5vfPmk*=J{nNuo$*K)%ywVAv!>kG+A_`C4=Vj$GgFII zGAWf)mB3I@eEGOb%&gy9*VH$%Y;q&q9io&eb1-s{kkmS=kikp-%AAbaCH0s`Icxu- zu`6?f+(*5M&^mPav^DQ0UGrsvtw_Y$Vg>&tk)FfGG~s2=0T^o?k>2x+R@$r$L79K7 z(w>62_J15dddu{>sX|NIHHTHGB3E8K7$-gKlEf+Y&S&DQw2^4I^`aMbnrbC^`C*_c zFYAc-DV3`%15SezCoB%x6iU_g{r-EFK(RV1wuNRT3E5nf_3=5P1j*Cc*<6o+GIS(G z>q?=k=YZqVd*(2_-^8ehOZW4c=V6WfmM=1*rNI$3OJfbbk%=^m@`14!q{k1q2~=)# zd3D>8$=mIPPuF-^oMApMZduKKT(SbR4im_~uEzlbg8Q-W zA1op|`ExlzkZAKSRq1N5TQBazy$pjKuyG6rK63G;nxoYDzIqN7Hk=h-@k!%NNJzlp zyHyk~f)*44E^|GB(CTirNj2DV)>N;^blx&#?y$hGqyI<)v zN8P5{+3@_iIp9PME|Cj{#&6rbAQlCcntEYLqXy*~ z(LM?g4rMve;Su_qjmN9Hid7bNcNiij`<~|tiYwTa_3qD|M#Hx}moyrdAi>r65VA_S9t>AL&?Gg9uRI z2|9f74o_9JsjAX5|8-96ZDCvJ_RJuDqK7U8X^Xm_cYKOl*=*03+Qrr4u1I2Kgq7HI zqdi*W)ZDC4>XOe8Gvf51Ihvc_uN;N@RZPZe`d5S^Fn#k3^MqjbaoH~G)aTw$q>8uG z4a5D?Zc~Ul`TqK&?G5&uXH$a)yGUzRJ80!b>fpPfie6(mOpgR#a0lX7FmJq7QyqI^ znr$bCwo%;CTt6|a;3K%}Nj>P<{jB$D|7NfMyJ1-UE0G%e)Rs%o`JVEa-&U@Dye zulFaMchEhwmr}ieMmB0bSjl4I*#p0S${Q^n74R_c8beVAix9u88=@!#$b45|eKAmS zlfoRS_j7#v*1oJlcvRU*|L6A{Ct6>Qe0oO4d3xClA2HW_HPy4fNJSy^)4+Zv+xI>L zYJp8RF+qqU9T}5vH#W>w9N&mR+G-J+3Hl)uGX-!&K<zV;A5V2Muo3D&Bu7U(-FB_Z7ychC9tLBFD zBbzR1Nq*fxkH`u7eB_XIxx*xSbT{PQZC99FfcR+A+pi8=A zpIY=_=U!6yI=)d?wO_(ydlrV3%YNS&C*85hsq|r83wqA(U z-rO3rZzkV{nI#}`uYH7+5DW;~ZVqtCJ-a98WL` zwe_TvK=vfpFCl86_jbmrfoVaA(s%MoH~`F`J`UjEF-#ekajr}G3=i+ig*MkF`knzb z1|EMh6I-Xyk=~my7$-DKN z+MOJ^FRygovJdJcxo^LbIu#8E=viD~TDAEXU;I0b%m*wm)<3+dI>0F&dc3eC{lkh zYrsh4aW^|l&&oRy{`}W3E<$)Ki8b(assUEw>$jK9N;fbKSnJD)xC}50AmT088QW`? zh@^rCN$+lv#YJ_cb7+ebSVXp1B$PPUbQbHrDq1mt=bo>)Ls3FAMMNjB&`_J8+RIPtR~vkKgcMq68yXf6zIEAZF&UT%XKKA=XQ?3vhvwff5Xp^iVN?5eQnH`g}ER&Q%R;KViKQf($yjITnfy8ABRRSkWC(^2e=hZE?_cuT-^rRr7 zB!*SkxBf1e7nM0>6KHz{s(kh2X{;OG=y{rnz;-9hJB_uY{>@j_F>)f{-HK03%7#?(-URf~Vi0@FkGAnSceCKpSM)AX8C(QwRxhiaX-Vus}k zZ`&LI0;1thB%F_xzKCakX!dugX^}IuiLfs>%cKq-)IvDp&J)2DlhV8Nr$w1YMjQaF zzaC<#`J7V$GLL{8Y&Ge8y8mY2&c)AV4@4p7L(6rZ+Bt{6YInIlqApxY2!@-r+)s{j z9l+ih&;n|cz)g`A?leB>yw7I!`Fi>#(#a|H5le#5<8J*0XK2~7Rvm9va%2=npn!qv zJDQs$hSj^>0968TU-6u+35M%Oi7^Y&^VI3N3hc8-$GXp23z3iJR)GF(3bN-Edwvhx z36L7P;ZkHEN`gwVN`j)eD1M`X`*;z?INar-`iG;mlWLzOpKUJfh6Q2V4OoXTv7=~M zh_<;B_Dw536OBF->VM3sOf>fgC~kp5N}@6J*kh+zndaNo#WMxX@fo!y5*sTZ1;&0| zWR*DESMu+STP^^mpipum-J+YMc*g*aii!CncsO245@KZF&Nvpw=)t!=Oa-aGF7JCOawHQ2q5J@DS!CkFn! zF)NdU1tg|}Yup9$_|5O@&4D*s?jzl6Q!{^2EfU=$;Sf)WV7XYT{7wlqXbD=b=xL3e$%< zCU2dQW`3ih#PrzbTUVhBkr?_wWf&&)w~t)ocPl?s8D7CNe^9^3{bJ9w-81cW@eWCd z(hC`g@K;)@TDgd%JEQ(fX=`EnZT3v5y&F!vf~&F47SS~<2Q`xCg0HX+Q7z398ZapL z3Nx0;UEu3SYmgg_a)2wRAO-6k6>;ic zy7u-<%F2(g#Lop}w0T0prKj9B&;f1$l^6J*NYWkb3Q5gm%b!{CK8DQ z0%igs@(?FmmOAmylxSp!y66~GCsa%DzJhh)6yus#9{gC|Mn~jh;AS)^d!QI!UKzg% z+rW^MMb|3KX8ixbe!}Cze5Eg#y8u5K)rVFLx#jSkv`e`gX2e-srgqOd6B|QE@<)-i9X$~<9t z^OrYDl~C6@S}SzzBQChUm()K*=jAhDulSRFvRD3dZpDlX zj~y-R_$W9bW-ZEvpD$dY;v({rSJ>(;0_X5<`)e8J4im}gQ={bsp%k9?VLnOlzU?;MqYAkeJuv1va(81%e|LrT zRRb|_n!{)|YG-ZNc1%F&A}i`xy!!xoXT&R=PPhw-q2d*(n>7H`;bkX{v(Sf=sTy- zQYB`zLmp_2yK@O(ErFSDG+@Nfz$$)_c!`F)>wp)dh5H0nYM62P%Fzb-@O*2y%aq_W zP!w(3dFwdi8Cck$e7bPTs58Tq`&eT4#>#eiZx1ZeM16cY+Mz(;&tL~LJhRi_z-Vwf zhT5f#-75#@5@)=NUShWFfRyB;G9L)iv;QW}HEI9n%Hv-#P&t_S_IB?mr3g7MGa0$b zQH35thuFE?_Xu3B*Ok-t&;b&kW}(PQ_x2Gt=83h*O+2M;$XR}tMnf%x_)fxM3`&BM;9fbfTGTZil&i*nMxQ0tX#~6p zYASjYIV6RBveWCes=&9x^&Yljo z&aRK0x7ygTXDcJg8_bt|9L+!Ln9QEh%D3ML#2nTBN)xd7#q#&YH}Xg?RIdn{-=khKPX2+j4I3acOJ=VgO+i*pqCY zu8|vpg~=C;K^ZissDViw=!XM$zRcPC$=OXnm|^%#P3vOBNk`f>X~@(p*>2jdq7abk z{n$m@=!M7z$jsR-q$SzvZI}+7JrA|m`Rt|? @@ -103,7 +109,6 @@

    Transpilage

    -

    Les bases

    @@ -935,14 +940,57 @@

    La preuve en live...

    -

    Structure d'une application

    +

    Structure applicative

    +

    Une application SPA est composée de plusieurs fichiers javascripts. C'est quand même plus pratique pour coder!

    +

    On découpe donc une application en modules

    +
    +
    +
    +
    -

    Déclarer un module

    +

    Module avant ES6

    +

    Les modules javascripts permettent d'isoler votre code du reste de l'application, d'organiser votre code, d'éviter les collision de noms etc.

    +
    
    +/// fichier1.js
    +const private = 5;
    +const monObjet = {
    +	name: "lala",
    +	age: 42 + private,
    +
    +}
    +
    +module.exports = monObjet;
    +
    +/// fichier2.js
    +const lala = require('./fichier1.js');
    +lala.awesomeness; // true;
    +private; // undefined
    +lala.age; // 47
    +					
    -

    Utiliser un module

    -
    +

    Module depuis ES6

    +

    Il est possible d'exporter plusieurs variables au sein d'un même fichier en les nommant.

    +
    
    +	/// fichier1.js
    +	export monObjet = {
    +		name: "lala",
    +		age: 42
    +	}
    +
    +	export monObjet2 = {
    +			name: "lola",
    +			age: 8
    +	}
    +
    +	/// fichier2.js
    +	import {monObjet, monObjet2 as renommage} from "./fichier1.js";
    +
    +	monObjet.age; // 42
    +	renommage.age; // 8
    +						
    +
    From a4ad92bcc4572e598692862e1ce54451308fdc37 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Fri, 12 Apr 2019 17:52:27 +0200 Subject: [PATCH 15/23] feat(gestion de l'asynchrone) --- index.html | 568 ++++++++--------------------------------------------- 1 file changed, 84 insertions(+), 484 deletions(-) diff --git a/index.html b/index.html index bd9a146..b08032a 100644 --- a/index.html +++ b/index.html @@ -937,7 +937,6 @@

    La preuve en live...

    -

    Structure applicative

    @@ -991,532 +990,133 @@

    Module depuis ES6

    renommage.age; // 8
    -
    - -
    -
    -

    Gestion de l'asynchrone

    -
    -
    -

    Callbacks

    -
    -
    -

    Promesses

    -
    -
    -

    Async/await

    -
    -
    - -
    -
    -

    L'éco-système JS

    -
    -
    -

    lodash

    -
    -
    -

    moment

    -
    -
    -

    i18n

    -
    -
    -

    node.js

    -
    -
    -

    babel

    -
    -
    -

    webpack

    -
    -
    -

    npm

    -
    -
    - -
    -

    Les types de base

    -
    -

    in et delete

    -
    -						
    -
    -let person = { name: 'Joe', langs: ['fr', 'en'] };
    -
    -'name' in person        // => true
    -person.age = 35;
    -'age' in person         // => true
    -person.age = null;
    -'age' in person         // => true
    -delete person.age
    -'age' in person         // => false
    -person.age              // => undefined
    -
    -0 in person.langs       // => true
    -'0' in person.langs     // => true
    -person.langs[3] = 'de';
    -2 in person.langs       // => false
    -3 in person.langs       // => true
    -delete person.langs[3]
    -person.langs            // => ['fr', 'en', undefined, undefined]
    -						
    -					
    -
    -
    -

    Falsy / Truthy

    -
    -
    -

    XML

    -
    -					
    -
    -  
    -    
    -    
    -    
    -  
    -
    -					
    -				
    - -
    -
    -

    JSON

    -
    -					
    -{
    -    "menu": {
    -        "id": "file",
    -        "value": "File",
    -        "popup": {
    -            "menuitem": [
    -                { "value": "New", "onclick": "CreateNewDoc()" },
    -                { "value": "Open", "onclick": "OpenDoc()" },
    -                { "value": "Close", "onclick": "CloseDoc()" }
    -            ]
    -        }
    -    }
    -}
    -					
    -				
    - -
    - - -
    -

    Oublions jQuery

    -
    -					
    -//Avant
    -const monElement = $('[data-my-selector]');
    +					
    +

    Module depuis ES6

    +

    Il existe différente manière d'exporter et d'importer des choses via module. Le mieux est d'aller voir la doc ;)

    +
    
    +	/// fichier1.js
    +	export default  {
    +		name: "lala",
    +		age: 42
    +	}
     
    -//Après
    -const monElement = document.querySelector('[data-my-selector]');
    -					
    -				
    + export const lolo = 28 -
    -
    -
    -
    -

    Les outils

    -
    -
    -
    -
    -

    Node.js

    -
      -
    • JS côté serveur
    • -
    • Apporte plein d'outils sous forme de modules
    • -
    • npm (node package module)
    • -
    -
    -
    -

    Node.js

    -
      -
    • package.json
    • -
    • node_modules
    • -
    • npm install -g ma-dependance-globale
    • -
    • npm install -g rimraf
    • -
    • npm install --save ma-dependance
    • -
    -
    -
    -

    Babel

    -
    -
    -

    Webpack

    -
    + /// fichier2.js + import lala from "./fichier1.js"; + import * as monModule from './fichier1.js'; -
    -

    Debug

    -
    + lala.age; // 42 + monModule.lolo; // 28 +
    +
    -
    -
    -

    Prototypes / Constructor

    -
    -
    -

    Classes ?

    -
      -
    • Avant ES6 pas de classe
    • -
    • JS est un langage prototypale
    • -
    • En JS tout est un objet
    • -
    • Une propriété est identifiée par une paire nom / valeur
    • -
    • Une propriété peut être une fonction
    • -
    -
    -
    -

    Les classes ES6

    - -
    Attention il s'agit de sucre syntaxique pas d'une classe comme en Java ou .NET. Le JS reste un langage prototypale.
    -
    +
    -

    La chaîne d'appel d'une méthode

    - obj.prop ou obj['prop'] (c'est équivalent) -
      -
    1. On part de l’objet indexé (obj)
    2. -
    3. Si on trouve prop dans ses own properties, on s’arrête là
    4. -
    5. Sinon, on passe sur le prototype du niveau supérieur : celui du constructeur de l’objet en cours*
    6. -
    7. On reprend à l’étape 2, sauf si on était déjà sur Object.prototype, auquel cas le lookup est fini, et échoue (undefined).
    8. -
    -
    *conceptuellement, constructor.prototype ou __proto__
    -
    -
    -

    La preuve en live...

    -
    -						
    -function Person(first, last) {
    -  this.first = first;
    -  this.last = last;
    -}
    -Person.prototype.fullName = function fullName() {
    -  return this.first + ' ' + this.last;
    -};
    -const davidLopez = new Person('David', 'Lopez');
    -
    -davidLopez.first      // => 'David',         own property
    -davidLopez.fullName() // => 'David Lopez', Person.prototype
    -davidLopez.toString() // => '[object Object]', Object.prototype
    -
    -Person.prototype.toString = function personToString() {
    -  return '#Person ' + this.fullName();
    -};
    -
    -davidLopez.toString() // => "#Person David Lopez"
    -						
    -					
    -
    -
    -
    -

    Closure

    -
    -

    Closure simple

    - +

    Gestion de l'asynchrone

    +

    Dans une application JS vous aurez à gérer de l'asynchrone. Ne serait-ce que pour faire des appels à une API. Il existe plusieurs manière de gérer cela.

    -

    Les modules sont une utilisation des closures

    +

    Callbacks

    
    -function yourModule(require, module, exports) {
    -
    -  let widgets = {};
    -  let util = require('util');
    -  let Widget = require('widgets/base');
    -
    -  function CoolWidget(elt) { … }
    -  util.inherits(CoolWidget, Widget);
    -  // …
    -
    -  module.exports = Widget;
    -}
    -					
    -
    Dans node on ne voit pas la fonction enrobante...
    -
    -
    -

    Le binding

    - -
    -
    -

    Le problème

    -
    -						
    -var name = 'Mr X';
    -let obj = {
    -  name: 'Joe Lopez',
    -  greet: function greet(whom) {
    -	console.log(this)
    -    console.log(this.name + ' salue ' + whom);
    -  },
    -  greetAll: function greetAll(first, second, last) {
    -	console.log(this)
    -    [first, second, last].forEach(this.greet);
    -  }
    -};
    -obj.greet("les lopezs de France");
    -// => 'Joe Lopez salut les lopezs de France !'
    -let fx = obj.greet;
    -fx("l’atelier") // => '"Mr X salue l’atelier"'
    -obj.greetAll('David', 'Joe', 'Guénolé'); // => 'Mr X salue David, Mr X salue Joe, Mr X salue undefined'
    -						
    -					
    -
    -
    -

    Comment faire ? La closure?

    -
    -						
    -const obj = {
    -  // …
    -  greetAll: function greetAll(first, second, last) {
    -    var that = this;
    -    [first, second, last].forEach(function(name) {
    -      that.greet(name);
    -    });
    -  }
    -}
    -						
    -					
    -
    -
    -

    Comment faire ? ES6 style?

    -
    -						
    -const obj = {
    -  // …
    -  greetAll(first, second, last) {
    -    [first, second, last].forEach(name => this.greet(name));
    -	//Ultra fat
    -  }
    -}
    -						
    -					
    -
    -
    -

    call et apply

    -
    -						
    -
    -
    -//let fx = obj.greet;
    -fx.call(obj, 'les singes') // Joe Lopez salue les singes
    -
    -
    -let xy = { 0: 'Zero', 1: 'One', length: 2 };
    -Array.prototype.join.call(xy, '-') // 'Zero-One'
    -
    -
    -fx.apply(obj, ['']) // => 'Joe salue l’atelier'
    -Array.prototype.push.apply(xy, ['Two', 'Three', 'Four']) // => 5
    -xy // => { 0: 'Zero', 1: 'One', 2: 'Two', 3: 'Three', 4: 'Four', length: 5 }
    -
    -
    - -
    -
    -
    -
    -

    JS et asynchronisme

    -
    -
    -

    Callback

    -
    -						
     function delayedAlert() {
    -  window.setTimeout(slowAlert, 2000);
    +	window.setTimeout(slowAlert, 2000);
     }
     
     function slowAlert() {
    -  alert("That was really slow!");
    +	alert("That was really slow!");
     }
     					
    +
    Attention le code de la callback est exécuté dans un contexte complètement différent!
    -

    Les promesses

    -

    - Une promesse a un état (pending, fullfilled, rejected).
    - Elle est asynchrone, et se termine soit par un succès soit par une erreur et renvoie une nouvelle promesse. -

    - promise.then(successCb,errorCb).then(otherSuccess, otherCb).catch(errorHandlingFn) - +

    Promesses

    +

    L'objet Promise est utilisé pour réaliser des traitements de façon asynchrone. Une promesse représente une valeur qui peut être disponible maintenant, dans le futur voire jamais.

    +

    Une promesse a un état (pending, fullfilled, rejected). En fonction de sa résolution elle appelera la callback associée via l'instruction then, qui renverra elle aussi une promesse.

    +
    promise.then(successCb,errorCb).then(otherSuccess, otherCb).catch(errorHandlingFn)
    -
    -

    Les promesses

    -
    
    -const myPromise = new Promise((resolve, reject) => {
    -	ajaxCall({success: resolve, error: reject});
    -})
    -
    -Promise.resolve([1,2,3,4]);
     
    -Promise.reject('ma super erreur')
    +				
    +

    Promesses

    +
    
    +var promise1 = new Promise(function(resolve, reject) {
    +	setTimeout(function() {
    +		resolve('foo');
    +	}, 300);
    +});
     
    +promise1.then(function(value) {
    +	console.log(value);
    +	// expected output: "foo"
    +});
     					
    -
    +
    -

    Les promesses

    -
    
    +						

    Promesses

    + +
    
     fetch('/users.json')
    -  .then(function(response) {
    -    return response.json()
    -  }).then(function(json) {
    -    console.log('parsed json', json)
    -  }).catch(function(ex) {
    -    console.log('parsing failed', ex)
    -  })					
    -
    -
    -
    -
    -

    ES6 / 2015

    -
    +.then(function(response) { + return response.json() +}).then(function(json) { + console.log('parsed json', json) +}).catch(function(ex) { + console.log('parsing failed', ex) +}) +
    +
    -

    Les modules de node

    -
    -						
    -//Dans un fichier
    -module.exports = monObjetAExporter;
    -
    -//Utilisation
    -require('./mon_module_locale');
    -//Utilisation d'un module npm
    -require('mon_module');
    -
    -
    -
    -					
    +

    Async/await

    +

    La déclaration async function définit une fonction asynchrone qui renvoie un objet AsyncFunction.

    +

    Une fonction asynchrone est une fonction qui s'exécute de façon asynchrone grâce à la boucle d'évènement en utilisant une promesse (Promise) comme valeur de retour.

    +

    L'opérateur await permet d'attendre la résolution d'une promesse. Il ne peut être utilisé qu'au sein d'une fonction asynchrone.

    +
    Au final c'est un sucre syntaxique autour d'une promesses
    -
    -

    Les modules de Papa

    -
    -						
    -import * as types from '../constants/ActionTypes';
    -
    -export function addTodo(text) {
    -  return { type: types.ADD_TODO, text };
    +			
    +

    Async/await

    +
    
    +function resolveAfter2Seconds(x) {
    +	return new Promise(resolve => {
    +		setTimeout(() => {
    +			resolve(x);
    +		}, 2000);
    +	});
     }
    -import React, { PropTypes, Component } from 'react';
    -import classnames from 'classnames';
    -import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants/TodoFilters';
    -import 'http://material.js'
    -…
    -export default Footer;
    -export const ADD_TODO = 'ADD_TODO';
    -export const DELETE_TODO = 'DELETE_TODO';
    -export const EDIT_TODO = 'EDIT_TODO';
    -
    -
    -
    -
    -					
    -
    - -
    -

    Destruct

    -
    -						
    -const { activeCount } = this.props;
    -…
    -const { filter: selectedFilter, onShow } = this.props;
    -const [, filters] = output.props.children;
    -…
    -const [,, clear] = output.props.children;
    -var { op: a, lhs: { op: b }, rhs: c } = getASTNode();
    -Détails
    -
     
    +async function f1() {
    +	var x = await resolveAfter2Seconds(10);
    +	console.log(x); // 10
    +}
    +f1();
    +				
    +
    +
    - -
    +
    -

    Les strings interpolation et multi lignes

    -
    -						
    -const person = { first: 'Thomas', last: 'Anderson', age: 25, nickname: 'Neo' };
    -
    -// Interpolation de JS quelconque
    -console.log(`${person.first} aka ${person.nickname}`)
    -// => 'Thomas aka Neo'
    -
    -// Multi-ligne !
    -const markup = `
  • -${person.first} ${person.last}, age ${person.age} -
  • `; - -
    - - -
    +

    L'éco-système JS

    -

    Valeur par défaut dans une fonction

    -
    -						
    -function add(source, numToAdd = 1){
    -	return source + numToAdd;
    -}
    -						
    -
    -
    -					
    +

    lodash

    -

    Les objets

    -
    -						
    -function editTodo(id, text) {
    -  return { type: types.EDIT_TODO, id, text };
    -  //On créé un objet avec pour clef le nom de la variable.
    -}
    -const FILTERS = {
    -  [maVar1]: 'All',
    -  [maVar2]: 'Active',
    -  [maVar3]: 'Completed'
    -};
    -						
    -
    -
    -					
    -
    -
    -
    -
    -

    LODASH / UNDERSCORE

    - +

    moment

    -

    on ne réinvente pas la roue

    +

    i18n

    -

    Les trucs utiles

    -
      -
    • Est ce que ma variable est un nombre / function / tableau lodash/lang
    • -
    • Filtrer, trier, reduce.... lodash/{collection/object/array}
    • -
    • Plein de fonctions prêtes à l'emploi lodash/function
    • -
    -
    -
    -
    -
    -

    MOMENT

    +

    node.js

    -

    on ne réinvente pas la roue

    - +

    babel

    -

    Les trucs utiles

    -
      -
    • formatter des dates moment().format('L')
    • -
    • Manipuler des dates moment(maDate).add('days', 1)
    • -
    • Timezone...
    • -
    -
    Si tu manipules des dates tu utilises momentjs
    +

    webpack

    -
    -
    -

    Exercices

    +

    npm

    From 33970a7b1c3e179b51c3e85a5a78d0131b6c5968 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Fri, 12 Apr 2019 18:01:46 +0200 Subject: [PATCH 16/23] feat(eco-systeme): lodash, moment, i18n --- index.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/index.html b/index.html index b08032a..90cc5b5 100644 --- a/index.html +++ b/index.html @@ -1099,12 +1099,26 @@

    L'éco-système JS

    lodash

    +

    Lodash est la librairie utilitaire la plus utilisé du monde JS. Vous voulez manipuler des objets/collections etc. Lodash a certainement la fonction qu'il vous faut.

    +
      +
    • Est ce que ma variable est un nombre / function / tableau lodash/lang
    • +
    • Filtrer, trier, reduce.... lodash/{collection/object/array}
    • +
    • Plein de fonctions prêtes à l'emploi lodash/function
    • +
    • ...
    • +

    moment

    +

    Les date en JS c'est pas vraiment la joie... Du coup on utilise moment. C'est bien plus pratique!

    +
      +
    • formatter des dates moment().format('L')
    • +
    • Manipuler des dates moment(maDate).add('days', 1)
    • +
    • Timezone...
    • +

    i18n

    +

    i18n vous sera utile pour gérer l'internationnalisation de votre application. L'intégralité de vous resources textuelles passeront par cette librairie pour pouvoir gérer le multilinguisme.

    node.js

    From 26cc84435694209b0266f35209a3b1201936e1e4 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Tue, 7 May 2019 10:39:49 +0200 Subject: [PATCH 17/23] fix: correction orthographique --- index.html | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/index.html b/index.html index 90cc5b5..83929e3 100644 --- a/index.html +++ b/index.html @@ -63,16 +63,16 @@

    Présentation

    Kesako?

    • Langage créé en 1995 pour réaliser des petits scripts dans des pages Web dans le but de les dynamiser
    • -
    • Le langage respecte l'ensemble des paradigme orienté objet, et est basé sur un principe de prototype
    • -
    • Langage nativement supporté par tous les navigateurs Web, ce qui le rend extrèmement populaire
    • -
    • Chaque navigateur à cependant son propre moteur JS
    • +
    • Le langage respecte l'ensemble des paradigmes orienté objet, et est basé sur un principe de prototype
    • +
    • Langage nativement supporté par tous les navigateurs Web, ce qui le rend extrêmement populaire
    • +
    • Chaque navigateur a cependant son propre moteur JS

    De l'utilisation du JS

    • Utilisation au sens premier du langage: dynamiser une page HTML avec quelques scripts côté client
    • -
    • Utilisation de Jquery: simplification de fonction complexe (écoute d'vènement, manipulation du DOM ...)
    • +
    • Utilisation de Jquery: simplification de fonction complexe (écoute d'évènement, manipulation du DOM ...)
    • Attention! JS !== JQuery
    • Avènement des SPA: React, Angular, Backbone, Vue ...
    • Multiplication des usages @@ -90,9 +90,9 @@

      De l'utilisation du JS

      Standard ECMAScript (ECMA-262)

      Il s'agit des normes Javascript écrites au cours des années.

      - - - + + +
      ES5 (2009)version la plus connu, supportée par tous les navigateurs
      ES 2015 (ES6)Ajoute énormément de modification au langage
      ...Evolution annuele de la norme
      ES5 (2009)version la plus connue, supportée par tous les navigateurs
      ES 2015 (ES6)Ajoute énormément de modifications au langage
      ...Evolution annuelle de la norme
      ES 2019version actuelle de la norme
      ES nextversion destinée à devenir la nouvelle norme
      @@ -102,10 +102,10 @@

      Standard ECMAScript (ECMA-262)

      Transpilage

      Le langage évoluant rapidement (tous les ans depuis 2015), les moteurs JS ne suivent pas toujours. Une étape de transpilage nous permet d'écrire notre code - avec toutes les avancées du langages, et rend cela compréhensible pour les différents moteurs JS

      + avec toutes les avancées du langage, et rend cela compréhensible pour les différents moteurs JS

      • Babel: Implémente les normes ES2017 et ESnext, les publie sous forme de module pour le développeur.
      • -
      • TypeScript: Implemente tout ou parti des normes ES2017 et ESnext. Ajoute un sucre syntaxique de typage pour le langage, ainsi qu'un jeu de fonctions avancées propre à ce typage.
      • +
      • TypeScript: Implemente tout ou partie des normes ES2017 et ESnext. Ajoute un sucre syntaxique de typage pour le langage, ainsi qu'un jeu de fonctions avancées propre à ce typage.
    @@ -381,7 +381,7 @@

    Opérateurs logiques

    ! - NON logique. Vrai si une l'expression a une valeur Truthy. Faux sinon. + NON logique. Faux si l'expression a une valeur Truthy. Vrai sinon.
    Attention les opérateurs logiques &&, || et ! fonctionnent différemment des opérateurs binaire &, | et ~.
    Pour plus d'info: La doc MDN
    @@ -448,7 +448,7 @@

    Interpolation de strings

    -

    Les nouvelles normes ECMAScript ont permis de faire évoluer le langages et de fournir un moyen de manipuler les strings. Il est désormais possible de créer des chaine de caractères multiligne et paramétrables!

    +

    Les nouvelles normes ECMAScript ont permis de faire évoluer le langage et de fournir un moyen de manipuler les strings. Il est désormais possible de créer des chaine de caractères multiligne et paramétrables!

     							
     const person = {nom: Ingargiola, prenom: Thibault};
    @@ -992,7 +992,7 @@ 

    Module depuis ES6

    Module depuis ES6

    -

    Il existe différente manière d'exporter et d'importer des choses via module. Le mieux est d'aller voir la doc ;)

    +

    Il existe différentes manières d'exporter et d'importer des choses via module. Le mieux est d'aller voir la doc ;)

    
     	/// fichier1.js
     	export default  {
    @@ -1071,7 +1071,7 @@ 

    Async/await

    La déclaration async function définit une fonction asynchrone qui renvoie un objet AsyncFunction.

    Une fonction asynchrone est une fonction qui s'exécute de façon asynchrone grâce à la boucle d'évènement en utilisant une promesse (Promise) comme valeur de retour.

    L'opérateur await permet d'attendre la résolution d'une promesse. Il ne peut être utilisé qu'au sein d'une fonction asynchrone.

    -
    Au final c'est un sucre syntaxique autour d'une promesses
    +
    Au final c'est un sucre syntaxique autour d'une promesse

    Async/await

    @@ -1099,7 +1099,7 @@

    L'éco-système JS

    lodash

    -

    Lodash est la librairie utilitaire la plus utilisé du monde JS. Vous voulez manipuler des objets/collections etc. Lodash a certainement la fonction qu'il vous faut.

    +

    Lodash est la librairie utilitaire la plus utilisé du monde JS. Si vous voulez manipuler des objets/collections etc. Lodash a certainement la fonction qu'il vous faut.

    • Est ce que ma variable est un nombre / function / tableau lodash/lang
    • Filtrer, trier, reduce.... lodash/{collection/object/array}
    • @@ -1118,7 +1118,7 @@

      moment

    i18n

    -

    i18n vous sera utile pour gérer l'internationnalisation de votre application. L'intégralité de vous resources textuelles passeront par cette librairie pour pouvoir gérer le multilinguisme.

    +

    i18n vous sera utile pour gérer l'internationalisation de votre application. L'intégralité de vous resources textuelles passeront par cette librairie pour pouvoir gérer le multilinguisme.

    node.js

    From 44fe2a8b8067db1552f8146b6d95221bc2f08f93 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Tue, 7 May 2019 10:51:04 +0200 Subject: [PATCH 18/23] feat(eco-systeme): Ajout Npm Babel Webpack et Nodejs --- index.html | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/index.html b/index.html index 83929e3..bdb16f3 100644 --- a/index.html +++ b/index.html @@ -1122,15 +1122,30 @@

    i18n

    node.js

    +

    + Node.js vous permet de créer des applicatifs écrits en javascript, et notamment des serveurs. On l'utilisera notamment pour éxécuter l'intégralité de la toolchain d'un projet SPA. +

    babel

    +

    + Babel est le traducteur universelle du javascript. Il permet de transpiler le langage écrit dans une version évoluée d'ECMAScript en une version compréhensible pour n'importe quel navigateur. +

    webpack

    +

    + Webpack est un ordonnanceur javascript utilisé pour builder les projet javascript. Il permet d'ajouter plusieur module à un pipeline de build. +

    +

    Au travers de ce pipeline de build, on passe d'un projet complexe avec des modules, des librairies etc. à un livrable composé de fichiers statiques à intégrer dans une page web.

    +
    transpilage --> obfuscation --> compréssion --> postCss --> ...

    npm

    +

    + Npm (Node Package Manager) est le gestionnaire de paquet qui vient avec Node.js. Il vous servira à gérer l'intégralité de vos dépendances javascripts. +

    +
    npm install internet
    From 18144814499adde162f01b0609352a0f68862759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20BOULET=20KESSLER?= Date: Tue, 7 May 2019 16:32:06 +0200 Subject: [PATCH 19/23] Apply suggestions from code review fix: correction orthographique, reformulation Co-Authored-By: Tsj- --- index.html | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/index.html b/index.html index bdb16f3..c80863f 100644 --- a/index.html +++ b/index.html @@ -122,7 +122,7 @@

    Types primitifs

  • boolean: résultat d'une assertion logique true ou false
  • null: ne possède qu'une unique valeur null
  • undefined: représente la non-affectation d'une variable
  • -
  • number: contient l'ensemble des valeur numéraire (entier, float, NaN, +Infinity, - Infinity)
  • +
  • number: contient l'ensemble des valeurs numéraires (entier, float, NaN, +Infinity, - Infinity)
  • string: représente une chaine de caractère à partir d'un ensemble d'élements 16bits non-signés
  • symbol: type de données unique et inchangeable (souvent utilisé pour créer des identifiants)
  • @@ -132,7 +132,7 @@

    Types primitifs

    Objets

    JavaScript est conçu autour d'un paradigme simple, basé sur les objets.

    -

    Un objet est un ensemble de propriétés et une propriété est une association entre un nom (aussi appelé clé) et une valeur.

    +

    Un objet est un ensemble de propriétés. Une propriété est une association entre un nom (aussi appelé clé) et une valeur.

    La valeur d'une propriété peut être une fonction, auquel cas la propriété peut être appelée « méthode ».

    @@ -162,7 +162,7 @@

    Objets

    Strings

    Le type String de JavaScript est utilisé pour représenter des données textuelles.

    C'est un ensemble d'"éléments" de valeurs non signées sur 16 bits (unités de codage UTF-16).

    -

    Chaque élément dans la chaîne de caractères occupe une position dans la chaîne de caractères. Le premier élément se trouve à l'indice 0, le suivant à l'indice 1 et ainsi de suite.

    +

    Chaque élément occupe une position dans la chaîne de caractères. Le premier élément se trouve à l'indice 0, le suivant à l'indice 1 et ainsi de suite.

    La longueur d'une chaîne de caractères est le nombre d'éléments qu'elle contient.

    Une String est immuable il est impossible de la modifier une fois créée. Il est cependant possible de recréer une string à partir d'une autre string.

    @@ -180,7 +180,7 @@

    Strings

    'déjà'.localeCompare('demain') // => -1 'déjà' est alphabétiquement avant 'demain' 'déjà !'.toLocaleUpperCase() // => 'DÉJÀ !' Renvoie une nouvelle instance en majuscule 'ÇA POUTRE'.toLocaleLowerCase() // => 'ça poutre' Renvoie une nouvelle instance en minuscule -'one,two,three'.split(',') // => ['one', 'two', 'three'] trnsformation en tableau selon un séparateur +'one,two,three'.split(',') // => ['one', 'two', 'three'] transformation en tableau selon un séparateur 'one,,two,three'.split(/\W+/) // => ['one', 'two'] transformation en tableau selon une expression régulière 'hello'.substring(1) // => 'ello' renvoie une nouvelle instance d'une partie de la chaine 'hello'.slice(1, -2) // => 'el' -> [1;length-2[ @@ -209,7 +209,7 @@

    Les tableaux

    // => 13 names[9] -// => undefined (comme 10 et 11): c'est appelé "sparse array" +// => undefined (comme de 3 à 11): c'est appelé "sparse array"
    @@ -246,8 +246,8 @@

    Dates

    JavaScript ne possède pas de type primitif pour représenter des dates. Cependant l'objet Date et ses méthodes permettent de manipuler des dates et des heures au sein d'une application.

    L'objet Date possède de nombreuses méthodes pour définir, modifier, obtenir des dates. Il ne possède pas de propriétés

    JavaScript gère les dates de façon similaire à Java. (Donc assez mal...)

    -

    Les dates sont représentées selon les nombres de millisecondes écoulées depuis le premier janvier 1970 à 00h00:00. - L'objet Date permet de représenter des dates allant de -100 000 000 jours jusqu'à +100 000 000 jours par rapport au premier janvier 1970 UTC.

    +

    Les dates sont représentées selon les nombres de millisecondes écoulées depuis le 1er janvier 1970 à 00h00:00. + L'objet Date permet de représenter des dates allant de -100 000 000 jours jusqu'à +100 000 000 jours par rapport au 1er janvier 1970 UTC.

    Dates

    @@ -280,7 +280,7 @@

    Operateurs

    != - true si les opérandes sont différents. + true si les opérandes sont différents après conversion en valeurs de mêmes types. === @@ -394,7 +394,7 @@

    Truthy / Falsy

    "true"&true => 0 // le & binaire renvoie le bit 0... "1" == true => true // bah oui après converstion "1" => 1 => true donc égale à true...
    -
    Globalement les valeurs suivantes sont Falsy: false, undefined, null, "", 0, NaN. Le reste est Truthy.
    +
    Globalement les valeurs suivantes sont Falsy :
    • false
    • undefined
    • null
    • ""
    • 0
    • NaN
    . Le reste est Truthy.

    Destructuring / Spreading

    @@ -448,10 +448,10 @@

    Interpolation de strings

    -

    Les nouvelles normes ECMAScript ont permis de faire évoluer le langage et de fournir un moyen de manipuler les strings. Il est désormais possible de créer des chaine de caractères multiligne et paramétrables!

    +

    Les nouvelles normes ECMAScript ont permis de faire évoluer le langage et de fournir un moyen de manipuler les strings. Il est désormais possible de créer des chaines de caractères multiligne et paramétrables!

     							
    -const person = {nom: Ingargiola, prenom: Thibault};
    +const person = { nom: "Ingargiola", prenom: "Thibault" };
     
     const stringAvant = 'Bonjour je suis ' + person.prenom + ' ' + person.nom;
     const stringApres= `Bonjour je suis ${objet.prenom} ${objet.nom}.
    @@ -525,7 +525,7 @@ 

    Déclaration

    Variables

    -

    Il existe trois façons de déclarer des variable en javascript:

    +

    Il existe trois façons de déclarer des variables en javascript:

    • var: On déclare une variable, éventuellement en initialisant sa valeur.
    • let: On déclare une variable dont la portée est celle du bloc courant, éventuellement en initialisant sa valeur.
    • @@ -554,7 +554,8 @@

      Boucles

       								
       const ARRAY = [1,2,3,4];
      -for(let i = 0, _l=ARRAY.length; i < _l; i++ ){console.log(ARRAY[i])}
      +
      +for(let i = 0, _l=ARRAY.length; i < _l; i++ ){console.log(ARRAY[i], i)}
       
       ARRAY.forEach(function(element, idx){console.log(element, idx)});
       
      @@ -564,9 +565,9 @@ 

      Boucles

    Scope

    -

    Les éléments créé en javascript ont une portée. Un Scope.

    +

    Les éléments créés en javascript ont une portée. Un Scope.

    Lorsqu'une variable est déclarée avec var en dehors des fonctions, elle est appelée variable globale car elle est disponible pour tout le code contenu dans le document. Lorsqu'une variable est déclarée dans une fonction, elle est appelée variable locale car elle n'est disponible qu'au sein de cette fonction.

    -

    Avant la norme ECMAScript2015 il n'existait pas d'autre manière de déclarer des variables. grâce au mot clé const et let, il est possible de restreindre la portée d'une variable au bloc en cours (un bloc if par exemple)

    +

    Avant la norme ECMAScript2015 il n'existait pas d'autre manière de déclarer des variables. grâce aux mots clés const et let, il est possible de restreindre la portée d'une variable au bloc en cours (un bloc if par exemple)

    Scope

    @@ -631,7 +632,7 @@

    Closure

    Contexte

    Le contexte d'une fonction est représenté par la variable this.

    La valeur de this sera déterminée à partir de la façon dont une fonction est appelée. Il n'est pas possible de lui affecter une valeur lors de l'exécution et sa valeur peut être différente à chaque fois que la fonction est appelée.

    -

    Les différentes évolutions du langage on permis de mieux définir cette variable indépendamment de la façon dont elle est appelée (bind, fat-arrow...).

    +

    Les différentes évolutions du langage on permis de mieux définir cette variable indépendamment de la façon dont elle est appelée : bind, fat-arrow...

    Binding implicite

    @@ -641,10 +642,10 @@

    Binding implicite

    const monObjet = { firstName: 'Thibault', lastName: 'Ingargiola', - fullName: function() { + fullName() { console.log(this.firstName + ' ' + this.lastName) }, - strictFullName: function() { + strictFullName() { "use strict"; console.log(this.firstName + ' ' + this.lastName) } @@ -667,11 +668,11 @@

    Le problème

    var name = 'Mr X'; let obj = { name: 'Joe Lopez', - greet: function greet(whom) { + greet(whom) { console.log(this); console.log(this.name + ' salue ' + whom); }, - greetAll: function greetAll(first, second, last) { + greetAll(first, second, last) { console.log(this); [first, second, last].forEach(this.greet); } @@ -692,8 +693,8 @@

    Solution 1: la closure

    const obj = { // … - greetAll: function greetAll(first, second, last) { - var that = this; + greetAll(first, second, last) { + const that = this; [first, second, last].forEach(function(name) { that.greet(name); }); @@ -709,7 +710,7 @@

    Solution 2: bind

    const obj = { // … - greetAll: function greetAll(first, second, last) { + greetAll(first, second, last) { [first, second, last].forEach(this.greet.bind(this)); } } @@ -724,7 +725,7 @@

    Solution 3: la fat arrow

    const obj = { // … - greetAll: function greetAll(first, second, last) { + greetAll(first, second, last) { [first, second, last].forEach(name => this.greet(name)); } } From 177cdfa6e7e343a83d350ea33054e4a132ca04e5 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Tue, 7 May 2019 16:36:00 +0200 Subject: [PATCH 20/23] fix: correction du lien de la formation --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index c80863f..eb3ddcc 100644 --- a/index.html +++ b/index.html @@ -54,7 +54,7 @@
    -

    Javascript

    http://kleegroup.github.io/formation-js/#/
    +

    Javascript

    http://get-focus.github.io/formation-js/#/

    Présentation

    From 24872ac0f050e4c1eedc1fe92a6aa346100ae0e9 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Tue, 7 May 2019 16:39:54 +0200 Subject: [PATCH 21/23] =?UTF-8?q?fix:=20Ajout=20de=20la=20notion=20de=20po?= =?UTF-8?q?rt=C3=A9e=20sur=20var.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index eb3ddcc..f15e641 100644 --- a/index.html +++ b/index.html @@ -527,7 +527,7 @@

    Déclaration

    Variables

    Il existe trois façons de déclarer des variables en javascript:

      -
    • var: On déclare une variable, éventuellement en initialisant sa valeur.
    • +
    • var: On déclare une variable dont la portée est celle de la fonction courante, éventuellement en initialisant sa valeur.
    • let: On déclare une variable dont la portée est celle du bloc courant, éventuellement en initialisant sa valeur.
    • const: On déclare une constante nommée, dont la portée est celle du bloc courant, accessible en lecture seule.
    From dd4efbc022a48c45ad6f5dd12d7fad964b483d6d Mon Sep 17 00:00:00 2001 From: Elodie Heslouis Date: Tue, 4 Jun 2019 11:21:53 +0200 Subject: [PATCH 22/23] fix: correction orthographique --- index.html | 56 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/index.html b/index.html index f15e641..743f266 100644 --- a/index.html +++ b/index.html @@ -90,14 +90,14 @@

    De l'utilisation du JS

    Standard ECMAScript (ECMA-262)

    Il s'agit des normes Javascript écrites au cours des années.

    - + - - + +
    ES5 (2009)version la plus connue, supportée par tous les navigateurs
    ES5 (2009)Version la plus connue, supportée par tous les navigateurs
    ES 2015 (ES6)Ajoute énormément de modifications au langage
    ...Evolution annuelle de la norme
    ES 2019version actuelle de la norme
    ES nextversion destinée à devenir la nouvelle norme
    ES 2019Version actuelle de la norme
    ES nextVersion destinée à devenir la nouvelle norme
    -
    On voit beaucoup de « ES7 » ou « ES8 » qui traînent : en général ça fait référence à l’« ES next » du moment.
    +
    On voit beaucoup de « ES7 » ou « ES8 » qui traînent : en général, ça fait référence à l’« ES next » du moment.

    Transpilage

    @@ -123,8 +123,8 @@

    Types primitifs

  • null: ne possède qu'une unique valeur null
  • undefined: représente la non-affectation d'une variable
  • number: contient l'ensemble des valeurs numéraires (entier, float, NaN, +Infinity, - Infinity)
  • -
  • string: représente une chaine de caractère à partir d'un ensemble d'élements 16bits non-signés
  • -
  • symbol: type de données unique et inchangeable (souvent utilisé pour créer des identifiants)
  • +
  • string: représente une chaine de caractères à partir d'un ensemble d'élements 16bits non-signés
  • +
  • symbol: type de données uniques et inchangeables (souvent utilisé pour créer des identifiants)
  • Tout le reste est "Objet" (oui oui même les tableaux...)

    Un objet avec une "call signature" est une fonction

    @@ -164,7 +164,7 @@

    Strings

    C'est un ensemble d'"éléments" de valeurs non signées sur 16 bits (unités de codage UTF-16).

    Chaque élément occupe une position dans la chaîne de caractères. Le premier élément se trouve à l'indice 0, le suivant à l'indice 1 et ainsi de suite.

    La longueur d'une chaîne de caractères est le nombre d'éléments qu'elle contient.

    -

    Une String est immuable il est impossible de la modifier une fois créée. Il est cependant possible de recréer une string à partir d'une autre string.

    +

    Une String est immuable: il est impossible de la modifier une fois créée. Il est cependant possible de recréer une string à partir d'une autre string.

    Strings

    @@ -269,7 +269,7 @@

    Dates

    // Heure locale du navigateur/système. On a les mêmes en getUTCXxx()…
    -
    Vous avez le choix dans l'implémentation de la date...
    De manière générale on préferera utiliser des library de dates type moment.js pour gérer des dates.
    +
    Vous avez le choix dans l'implémentation de la date...
    De manière générale, on préferera utiliser des libraries de dates type moment.js pour gérer des dates.

    Operateurs

    @@ -348,7 +348,7 @@

    Pour éviter les écueils, utiliser ===

    Opérateurs

    Les opérateurs javascripts font des conversions implicites.

    -

    Le javascript ne plantera jamais sur une opération. En revanche il peut vous renvoyer une valeur native comme Nan, +Infinity etc.

    +

    Le javascript ne plantera jamais sur une opération. En revanche, il peut vous renvoyer une valeur native comme Nan, +Infinity etc.

    
     	!42  => false
     	!!42  => true //pratique pour convertir n'importe quelle valeur en booleen
    @@ -369,7 +369,7 @@ 

    Opérateurs

    Opérateurs logiques

    -

    Ces opérateurs servent à resoudre des expressions logique en prenant en compte le caractère "Truthy" ou "Falsy" des valeurs de l'expression

    +

    Ces opérateurs servent à résoudre des expressions logiques en prenant en compte le caractère "Truthy" ou "Falsy" des valeurs de l'expression

    @@ -384,7 +384,7 @@

    Opérateurs logiques

    && NON logique. Faux si l'expression a une valeur Truthy. Vrai sinon.
    -
    Attention les opérateurs logiques &&, || et ! fonctionnent différemment des opérateurs binaire &, | et ~.
    Pour plus d'info: La doc MDN
    +
    Attention: les opérateurs logiques &&, || et ! fonctionnent différemment des opérateurs binaire &, | et ~.
    Pour plus d'info: La doc MDN

    Truthy / Falsy

    @@ -448,7 +448,7 @@

    Interpolation de strings

    -

    Les nouvelles normes ECMAScript ont permis de faire évoluer le langage et de fournir un moyen de manipuler les strings. Il est désormais possible de créer des chaines de caractères multiligne et paramétrables!

    +

    Les nouvelles normes ECMAScript ont permis de faire évoluer le langage et de fournir un moyen de manipuler les strings. Il est désormais possible de créer des chaines de caractères multilignes et paramétrables!

     							
     const person = { nom: "Ingargiola", prenom: "Thibault" };
    @@ -535,7 +535,7 @@ 

    Variables

    Boucles

    -

    Depuis ECMAScript2015 le prototype ARRAY a gagné de nouvelles méthode d'itération sur les éléments. Nous allons en présenter deux ici:

    +

    Depuis ECMAScript2015, le prototype ARRAY a gagné de nouvelles méthodes d'itération sur les éléments. Nous allons en présenter deux ici:

    @@ -567,7 +567,7 @@

    Boucles

    Scope

    Les éléments créés en javascript ont une portée. Un Scope.

    Lorsqu'une variable est déclarée avec var en dehors des fonctions, elle est appelée variable globale car elle est disponible pour tout le code contenu dans le document. Lorsqu'une variable est déclarée dans une fonction, elle est appelée variable locale car elle n'est disponible qu'au sein de cette fonction.

    -

    Avant la norme ECMAScript2015 il n'existait pas d'autre manière de déclarer des variables. grâce aux mots clés const et let, il est possible de restreindre la portée d'une variable au bloc en cours (un bloc if par exemple)

    +

    Avant la norme ECMAScript2015, il n'existait pas d'autre manière de déclarer des variables. Grâce aux mots clés const et let, il est possible de restreindre la portée d'une variable au bloc en cours (un bloc if par exemple)

    Scope

    @@ -632,11 +632,11 @@

    Closure

    Contexte

    Le contexte d'une fonction est représenté par la variable this.

    La valeur de this sera déterminée à partir de la façon dont une fonction est appelée. Il n'est pas possible de lui affecter une valeur lors de l'exécution et sa valeur peut être différente à chaque fois que la fonction est appelée.

    -

    Les différentes évolutions du langage on permis de mieux définir cette variable indépendamment de la façon dont elle est appelée : bind, fat-arrow...

    +

    Les différentes évolutions du langage ont permis de mieux définir cette variable indépendamment de la façon dont elle est appelée : bind, fat-arrow...

    Binding implicite

    -

    La valeur de this dépend donc de la façon dont il est appelé. De manière générale lorsque this est utilisé dans une fonction il aura la valeur de l'appelant.

    +

    La valeur de this dépend donc de la façon dont il est appelé. De manière générale, lorsque this est utilisé dans une fonction, il aura la valeur de l'appelant.

     				
     const monObjet = {
    @@ -705,7 +705,7 @@ 

    Solution 1: la closure

    Solution 2: bind

    -

    La fonction bind permet de détermnier le contexte d'une fonction qu'importe la façon dont elle est appelée.

    +

    La fonction bind permet de déterminer le contexte d'une fonction qu'importe la façon dont elle est appelée.

     				
     const obj = {
    @@ -716,7 +716,7 @@ 

    Solution 2: bind

    }
    -
    Ici on crée donc une nouvelle fonction pour les trois appels dont le contexte vaudra this.
    +
    Ici, on crée donc une nouvelle fonction pour les trois appels dont le contexte vaudra this.

    Solution 3: la fat arrow

    @@ -749,7 +749,7 @@

    Binding

    call et apply

    -

    Le fonctions call et apply permettent de fixer le contexte au travers du premier argument lors de l'appel. La fonction call prendra par la suite une liste d'argument là ou apply utilisera un tableau.

    +

    Les fonctions call et apply permettent de fixer le contexte au travers du premier argument lors de l'appel. La fonction call prendra par la suite une liste d'argument là ou apply utilisera un tableau.

     				
     	function ajout(c, d){
    @@ -882,7 +882,7 @@ 

    "Déguiser" un objet en tableau

    Classe

    -

    Bon depuis ES2015 on a tout de même un équivalent de classe. Ce n'est que du sucre sytaxique, mais c'est quand même vachement bien!

    +

    Bon depuis ES2015 on a tout de même un équivalent de classe. Ce n'est que du sucre syntaxique, mais c'est quand même vachement bien!

     							
     class TodoItem extends Component {
    @@ -903,7 +903,7 @@ 

    Classe

    La chaîne d'appel d'une méthode

    -

    Supposons que l'on fasse appelle à l'attribut d'un objet: obj.prop

    +

    Supposons que l'on fasse appel à l'attribut d'un objet: obj.prop

    1. On part de l’objet indexé (obj)
    2. Si on trouve prop dans ses own properties, on s’arrête là
    3. @@ -1015,7 +1015,7 @@

      Module depuis ES6

      Gestion de l'asynchrone

      -

      Dans une application JS vous aurez à gérer de l'asynchrone. Ne serait-ce que pour faire des appels à une API. Il existe plusieurs manière de gérer cela.

      +

      Dans une application JS, vous aurez à gérer de l'asynchrone. Ne serait-ce que pour faire des appels à une API. Il existe plusieurs manière de gérer cela.

      Callbacks

      @@ -1033,7 +1033,7 @@

      Callbacks

      Promesses

      L'objet Promise est utilisé pour réaliser des traitements de façon asynchrone. Une promesse représente une valeur qui peut être disponible maintenant, dans le futur voire jamais.

      -

      Une promesse a un état (pending, fullfilled, rejected). En fonction de sa résolution elle appelera la callback associée via l'instruction then, qui renverra elle aussi une promesse.

      +

      Une promesse a un état (pending, fullfilled, rejected). En fonction de sa résolution, elle appellera la callback associée via l'instruction then, qui renverra elle aussi une promesse.

      promise.then(successCb,errorCb).then(otherSuccess, otherCb).catch(errorHandlingFn)
      @@ -1072,7 +1072,7 @@

      Async/await

      La déclaration async function définit une fonction asynchrone qui renvoie un objet AsyncFunction.

      Une fonction asynchrone est une fonction qui s'exécute de façon asynchrone grâce à la boucle d'évènement en utilisant une promesse (Promise) comme valeur de retour.

      L'opérateur await permet d'attendre la résolution d'une promesse. Il ne peut être utilisé qu'au sein d'une fonction asynchrone.

      -
      Au final c'est un sucre syntaxique autour d'une promesse
      +
      Au final, c'est un sucre syntaxique autour d'une promesse

      Async/await

      @@ -1100,7 +1100,7 @@

      L'éco-système JS

      lodash

      -

      Lodash est la librairie utilitaire la plus utilisé du monde JS. Si vous voulez manipuler des objets/collections etc. Lodash a certainement la fonction qu'il vous faut.

      +

      Lodash est la librairie utilitaire la plus utilisée du monde JS. Si vous voulez manipuler des objets/collections etc. Lodash a certainement la fonction qu'il vous faut.

      • Est ce que ma variable est un nombre / function / tableau lodash/lang
      • Filtrer, trier, reduce.... lodash/{collection/object/array}
      • @@ -1110,7 +1110,7 @@

        lodash

      moment

      -

      Les date en JS c'est pas vraiment la joie... Du coup on utilise moment. C'est bien plus pratique!

      +

      Les dates en JS, c'est pas vraiment la joie... Du coup on utilise moment. C'est bien plus pratique!

      • formatter des dates moment().format('L')
      • Manipuler des dates moment(maDate).add('days', 1)
      • @@ -1119,7 +1119,7 @@

        moment

      i18n

      -

      i18n vous sera utile pour gérer l'internationalisation de votre application. L'intégralité de vous resources textuelles passeront par cette librairie pour pouvoir gérer le multilinguisme.

      +

      i18n vous sera utile pour gérer l'internationalisation de votre application. L'intégralité de vos ressources textuelles passeront par cette librairie pour pouvoir gérer le multilinguisme.

      node.js

      @@ -1136,7 +1136,7 @@

      babel

      webpack

      - Webpack est un ordonnanceur javascript utilisé pour builder les projet javascript. Il permet d'ajouter plusieur module à un pipeline de build. + Webpack est un ordonnanceur javascript utilisé pour builder les projets javascript. Il permet d'ajouter plusieurs modules à un pipeline de build.

      Au travers de ce pipeline de build, on passe d'un projet complexe avec des modules, des librairies etc. à un livrable composé de fichiers statiques à intégrer dans une page web.

      transpilage --> obfuscation --> compréssion --> postCss --> ...
      From 23c7c38495f32281f4e9fdac8b7d351d8d4b1b35 Mon Sep 17 00:00:00 2001 From: Thibault Ingargiola Date: Mon, 17 Jun 2019 15:23:57 +0200 Subject: [PATCH 23/23] maj stack --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 743f266..fe84bc6 100644 --- a/index.html +++ b/index.html @@ -957,6 +957,7 @@

      Module avant ES6

      const monObjet = { name: "lala", age: 42 + private, + awesomeness: true }
    map