asciidoctor-revealjs 1.1.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +72 -0
  3. data/Gemfile +2 -0
  4. data/HACKING.adoc +29 -14
  5. data/LICENSE.adoc +1 -1
  6. data/README.adoc +239 -23
  7. data/Rakefile +22 -1
  8. data/asciidoctor-revealjs.gemspec +6 -4
  9. data/examples/background-color.adoc +45 -0
  10. data/examples/background-color.css +18 -0
  11. data/examples/history-regression-tests.adoc +12 -2
  12. data/examples/images.adoc +32 -0
  13. data/examples/revealjs-features.adoc +23 -0
  14. data/examples/revealjs-plugin-activation.adoc +16 -0
  15. data/examples/revealjs-plugins-conf.js +10 -0
  16. data/examples/revealjs-plugins.adoc +16 -0
  17. data/examples/revealjs-plugins.js +2 -0
  18. data/examples/revealjs-plugins/chalkboard/README.md +124 -0
  19. data/examples/revealjs-plugins/chalkboard/chalkboard.js +1288 -0
  20. data/examples/revealjs-plugins/chalkboard/img/blackboard.png +0 -0
  21. data/examples/revealjs-plugins/chalkboard/img/boardmarker.png +0 -0
  22. data/examples/revealjs-plugins/chalkboard/img/chalk.png +0 -0
  23. data/examples/revealjs-plugins/chalkboard/img/sponge.png +0 -0
  24. data/examples/revealjs-plugins/chalkboard/img/whiteboard.png +0 -0
  25. data/examples/revealjs-plugins/reveal.js-menu/CONTRIBUTING.md +9 -0
  26. data/examples/revealjs-plugins/reveal.js-menu/LICENSE +19 -0
  27. data/examples/revealjs-plugins/reveal.js-menu/README.md +334 -0
  28. data/examples/revealjs-plugins/reveal.js-menu/bower.json +21 -0
  29. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/LICENSE.txt +34 -0
  30. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/css/all.css +5 -0
  31. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/css/brands.css +5 -0
  32. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/css/fontawesome.css +5 -0
  33. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/css/regular.css +5 -0
  34. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/css/solid.css +5 -0
  35. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/css/svg-with-js.css +5 -0
  36. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/css/v4-shims.css +2170 -0
  37. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/css/v4-shims.min.css +5 -0
  38. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-brands-400.eot +0 -0
  39. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-brands-400.svg +1127 -0
  40. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-brands-400.ttf +0 -0
  41. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-brands-400.woff +0 -0
  42. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-brands-400.woff2 +0 -0
  43. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-regular-400.eot +0 -0
  44. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-regular-400.svg +467 -0
  45. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-regular-400.ttf +0 -0
  46. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-regular-400.woff +0 -0
  47. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-regular-400.woff2 +0 -0
  48. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-solid-900.eot +0 -0
  49. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-solid-900.svg +2231 -0
  50. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-solid-900.ttf +0 -0
  51. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-solid-900.woff +0 -0
  52. data/examples/revealjs-plugins/reveal.js-menu/font-awesome/webfonts/fa-solid-900.woff2 +0 -0
  53. data/examples/revealjs-plugins/reveal.js-menu/menu.css +345 -0
  54. data/examples/revealjs-plugins/reveal.js-menu/menu.js +949 -0
  55. data/examples/revealjs-plugins/reveal.js-menu/package.json +22 -0
  56. data/examples/slide-numbers-custom.adoc +18 -0
  57. data/examples/slide-numbers-for-speaker.adoc +23 -0
  58. data/examples/slide-numbers-no.adoc +18 -0
  59. data/examples/slide-numbers.adoc +28 -0
  60. data/examples/source-callouts.adoc +11 -1
  61. data/examples/source-highlightjs.adoc +9 -0
  62. data/examples/speaker-notes.adoc +25 -2
  63. data/lib/asciidoctor-revealjs.rb +1 -0
  64. data/lib/asciidoctor-revealjs/converter.rb +655 -542
  65. data/lib/asciidoctor-revealjs/version.rb +1 -1
  66. data/templates/admonition.html.slim +2 -3
  67. data/templates/asciidoctor_revealjs.css.slim +14 -0
  68. data/templates/document.html.slim +69 -26
  69. data/templates/helpers.rb +23 -0
  70. data/templates/listing.html.slim +35 -35
  71. data/templates/notes.html.slim +1 -0
  72. data/templates/open.html.slim +7 -4
  73. data/templates/section.html.slim +2 -8
  74. data/templates/sidebar.html.slim +8 -5
  75. data/templates/toc.html.slim +2 -2
  76. metadata +81 -11
@@ -0,0 +1,345 @@
1
+ .slide-menu-wrapper {
2
+ font-family: "Source Sans Pro", Helvetica, sans-serif;
3
+ }
4
+
5
+ .slide-menu-wrapper .slide-menu {
6
+ background-color: #333;
7
+ z-index: 200;
8
+ position: fixed;
9
+ top: 0;
10
+ width: 300px;
11
+ height: 100%;
12
+ /*overflow-y: scroll;*/
13
+ transition: transform 0.3s;
14
+ font-size: 16px;
15
+ font-weight: normal;
16
+ }
17
+
18
+ .slide-menu-wrapper .slide-menu.slide-menu--wide {
19
+ width: 500px;
20
+ }
21
+
22
+ .slide-menu-wrapper .slide-menu.slide-menu--third {
23
+ width: 33%;
24
+ }
25
+
26
+ .slide-menu-wrapper .slide-menu.slide-menu--half {
27
+ width: 50%;
28
+ }
29
+
30
+ .slide-menu-wrapper .slide-menu.slide-menu--full {
31
+ width: 95%;
32
+ }
33
+
34
+ /*
35
+ * Slides menu
36
+ */
37
+
38
+ .slide-menu-wrapper .slide-menu-items {
39
+ margin: 0;
40
+ padding: 0;
41
+ width: 100%;
42
+ border-bottom: solid 1px #555;
43
+ }
44
+
45
+ .slide-menu-wrapper .slide-menu-item,
46
+ .slide-menu-wrapper .slide-menu-item-vertical {
47
+ display: block;
48
+ text-align: left;
49
+ padding: 10px 18px;
50
+ color: #aaa;
51
+ cursor: pointer;
52
+ }
53
+
54
+ .slide-menu-wrapper .slide-menu-item-vertical {
55
+ padding-left: 30px;
56
+ }
57
+
58
+ .slide-menu-wrapper .slide-menu--wide .slide-menu-item-vertical,
59
+ .slide-menu-wrapper .slide-menu--third .slide-menu-item-vertical,
60
+ .slide-menu-wrapper .slide-menu--half .slide-menu-item-vertical,
61
+ .slide-menu-wrapper .slide-menu--full .slide-menu-item-vertical,
62
+ .slide-menu-wrapper .slide-menu--custom .slide-menu-item-vertical {
63
+ padding-left: 50px;
64
+ }
65
+
66
+ .slide-menu-wrapper .slide-menu-item {
67
+ border-top: solid 1px #555;
68
+ }
69
+
70
+ .slide-menu-wrapper .active-menu-panel li.selected {
71
+ background-color: #222;
72
+ color: white;
73
+ }
74
+
75
+ .slide-menu-wrapper .active-menu-panel li.active {
76
+ color: #eee;
77
+ }
78
+
79
+ .slide-menu-wrapper .slide-menu-item.no-title .slide-menu-item-title,
80
+ .slide-menu-wrapper .slide-menu-item-vertical.no-title .slide-menu-item-title {
81
+ font-style: italic;
82
+ }
83
+
84
+ .slide-menu-wrapper .slide-menu-item-number {
85
+ color: #999;
86
+ padding-right:6px;
87
+ }
88
+
89
+ .slide-menu-wrapper .slide-menu-item i.far,
90
+ .slide-menu-wrapper .slide-menu-item i.fas,
91
+ .slide-menu-wrapper .slide-menu-item-vertical i.far,
92
+ .slide-menu-wrapper .slide-menu-item-vertical i.fas,
93
+ .slide-menu-wrapper .slide-menu-item svg.svg-inline--fa,
94
+ .slide-menu-wrapper .slide-menu-item-vertical svg.svg-inline--fa {
95
+ padding-right: 12px;
96
+ display: none;
97
+ }
98
+
99
+ .slide-menu-wrapper .slide-menu-item.past i.fas.past,
100
+ .slide-menu-wrapper .slide-menu-item-vertical.past i.fas.past,
101
+ .slide-menu-wrapper .slide-menu-item.active i.fas.active,
102
+ .slide-menu-wrapper .slide-menu-item-vertical.active i.fas.active,
103
+ .slide-menu-wrapper .slide-menu-item.future i.far.future,
104
+ .slide-menu-wrapper .slide-menu-item-vertical.future i.far.future,
105
+ .slide-menu-wrapper .slide-menu-item.past svg.svg-inline--fa.past,
106
+ .slide-menu-wrapper .slide-menu-item-vertical.past svg.svg-inline--fa.past,
107
+ .slide-menu-wrapper .slide-menu-item.active svg.svg-inline--fa.active,
108
+ .slide-menu-wrapper .slide-menu-item-vertical.active svg.svg-inline--fa.active,
109
+ .slide-menu-wrapper .slide-menu-item.future svg.svg-inline--fa.future,
110
+ .slide-menu-wrapper .slide-menu-item-vertical.future svg.svg-inline--fa.future {
111
+ display: inline-block;
112
+ }
113
+
114
+ .slide-menu-wrapper .slide-menu-item.past i.fas.past,
115
+ .slide-menu-wrapper .slide-menu-item-vertical.past i.fas.past,
116
+ .slide-menu-wrapper .slide-menu-item.future i.far.future,
117
+ .slide-menu-wrapper .slide-menu-item-vertical.future i.far.future,
118
+ .slide-menu-wrapper .slide-menu-item.past svg.svg-inline--fa.past,
119
+ .slide-menu-wrapper .slide-menu-item-vertical.past svg.svg-inline--fa.past,
120
+ .slide-menu-wrapper .slide-menu-item.future svg.svg-inline--fa.future,
121
+ .slide-menu-wrapper .slide-menu-item-vertical.future svg.svg-inline--fa.future {
122
+ opacity: 0.4;
123
+ }
124
+
125
+ .slide-menu-wrapper .slide-menu-item.active i.fas.active,
126
+ .slide-menu-wrapper .slide-menu-item-vertical.active i.fas.active,
127
+ .slide-menu-wrapper .slide-menu-item.active svg.svg-inline--fa.active,
128
+ .slide-menu-wrapper .slide-menu-item-vertical.active svg.svg-inline--fa.active {
129
+ opacity: 0.8;
130
+ }
131
+
132
+ .slide-menu-wrapper .slide-menu--left {
133
+ left: 0;
134
+ -webkit-transform: translateX(-100%);
135
+ -ms-transform: translateX(-100%);
136
+ transform: translateX(-100%);
137
+ }
138
+
139
+ .slide-menu-wrapper .slide-menu--left.active {
140
+ -webkit-transform: translateX(0);
141
+ -ms-transform: translateX(0);
142
+ transform: translateX(0);
143
+ }
144
+
145
+ .slide-menu-wrapper .slide-menu--right {
146
+ right: 0;
147
+ -webkit-transform: translateX(100%);
148
+ -ms-transform: translateX(100%);
149
+ transform: translateX(100%);
150
+ }
151
+
152
+ .slide-menu-wrapper .slide-menu--right.active {
153
+ -webkit-transform: translateX(0);
154
+ -ms-transform: translateX(0);
155
+ transform: translateX(0);
156
+ }
157
+
158
+ .slide-menu-wrapper {
159
+ transition: transform 0.3s;
160
+ }
161
+
162
+
163
+ /*
164
+ * Toolbar
165
+ */
166
+ .slide-menu-wrapper .slide-menu-toolbar {
167
+ height: 60px;
168
+ width: 100%;
169
+ font-size: 12px;
170
+ display: table;
171
+ table-layout: fixed; /* ensures equal width */
172
+ margin: 0;
173
+ padding: 0;
174
+ border-bottom: solid 2px #666;
175
+ }
176
+
177
+ .slide-menu-wrapper .slide-menu-toolbar > li {
178
+ display: table-cell;
179
+ line-height: 150%;
180
+ text-align: center;
181
+ vertical-align: middle;
182
+ cursor: pointer;
183
+ color: #aaa;
184
+ border-radius: 3px;
185
+ padding-top: 16px;
186
+ }
187
+
188
+ .slide-menu-wrapper .slide-menu-toolbar > li.toolbar-panel-button i,
189
+ .slide-menu-wrapper .slide-menu-toolbar > li.toolbar-panel-button svg.svg-inline--fa {
190
+ font-size: 1.7em;
191
+ }
192
+
193
+ .slide-menu-wrapper .slide-menu-toolbar > li.toolbar-panel-button span.slide-menu-toolbar-label {
194
+ visibility: hidden;
195
+ }
196
+
197
+ .slide-menu-wrapper .slide-menu-toolbar > li.active-toolbar-button {
198
+ color: white;
199
+ text-shadow: 0 1px black;
200
+ }
201
+
202
+ .slide-menu-toolbar > li.toolbar-panel-button:hover {
203
+ color: white;
204
+ }
205
+
206
+ .slide-menu-toolbar > li.toolbar-panel-button:hover span.slide-menu-toolbar-label,
207
+ .slide-menu-wrapper .slide-menu-toolbar > li.active-toolbar-button span.slide-menu-toolbar-label {
208
+ visibility: visible;
209
+ }
210
+
211
+ /*
212
+ * Panels
213
+ */
214
+ .slide-menu-wrapper .slide-menu-panel {
215
+ position: absolute;
216
+ width: 100%;
217
+ visibility: hidden;
218
+ height: calc(100% - 60px);
219
+ overflow-x: hidden;
220
+ overflow-y: auto;
221
+ color: #AAA;
222
+ }
223
+
224
+ .slide-menu-wrapper .slide-menu-panel.active-menu-panel {
225
+ visibility: visible;
226
+ }
227
+
228
+ .slide-menu-wrapper .slide-menu-panel h1,
229
+ .slide-menu-wrapper .slide-menu-panel h2,
230
+ .slide-menu-wrapper .slide-menu-panel h3,
231
+ .slide-menu-wrapper .slide-menu-panel h4,
232
+ .slide-menu-wrapper .slide-menu-panel h5,
233
+ .slide-menu-wrapper .slide-menu-panel h6 {
234
+ margin: 20px 0 10px 0;
235
+ color: #FFF;
236
+ line-height: 1.2;
237
+ letter-spacing: normal;
238
+ text-shadow: none;
239
+ }
240
+
241
+ .slide-menu-wrapper .slide-menu-panel h1 {
242
+ font-size: 1.6em;
243
+ }
244
+ .slide-menu-wrapper .slide-menu-panel h2 {
245
+ font-size: 1.4em;
246
+ }
247
+ .slide-menu-wrapper .slide-menu-panel h3 {
248
+ font-size: 1.3em;
249
+ }
250
+ .slide-menu-wrapper .slide-menu-panel h4 {
251
+ font-size: 1.1em;
252
+ }
253
+ .slide-menu-wrapper .slide-menu-panel h5 {
254
+ font-size: 1em;
255
+ }
256
+ .slide-menu-wrapper .slide-menu-panel h6 {
257
+ font-size: 0.9em;
258
+ }
259
+
260
+ .slide-menu-wrapper .slide-menu-panel p {
261
+ margin: 10px 0 5px 0;
262
+ }
263
+
264
+ .slide-menu-wrapper .slide-menu-panel a {
265
+ color: #CCC;
266
+ text-decoration: underline;
267
+ }
268
+
269
+ .slide-menu-wrapper .slide-menu-panel a:hover {
270
+ color: white;
271
+ }
272
+
273
+ .slide-menu-wrapper .slide-menu-item a {
274
+ text-decoration: none;
275
+ }
276
+
277
+ .slide-menu-wrapper .slide-menu-custom-panel {
278
+ width: calc(100% - 20px);
279
+ padding-left: 10px;
280
+ padding-right: 10px;
281
+ }
282
+
283
+ .slide-menu-wrapper .slide-menu-custom-panel .slide-menu-items {
284
+ width: calc(100% + 20px);
285
+ margin-left: -10px;
286
+ margin-right: 10px;
287
+ }
288
+
289
+
290
+ /*
291
+ * Theme and Transitions buttons
292
+ */
293
+
294
+ .slide-menu-wrapper div[data-panel="Themes"] li,
295
+ .slide-menu-wrapper div[data-panel="Transitions"] li {
296
+ display: block;
297
+ text-align: left;
298
+ cursor: pointer;
299
+ color: #848484;
300
+ }
301
+
302
+ /*
303
+ * Menu controls
304
+ */
305
+ .reveal .slide-menu-button {
306
+ position: fixed;
307
+ left: 30px;
308
+ bottom: 30px;
309
+ z-index: 30;
310
+ font-size: 24px;
311
+ }
312
+
313
+ /*
314
+ * Menu overlay
315
+ */
316
+
317
+ .slide-menu-wrapper .slide-menu-overlay {
318
+ position: fixed;
319
+ z-index: 199;
320
+ top: 0;
321
+ left: 0;
322
+ overflow: hidden;
323
+ width: 0;
324
+ height: 0;
325
+ background-color: #000;
326
+ opacity: 0;
327
+ transition: opacity 0.3s, width 0s 0.3s, height 0s 0.3s;
328
+ }
329
+
330
+ .slide-menu-wrapper .slide-menu-overlay.active {
331
+ width: 100%;
332
+ height: 100%;
333
+ opacity: 0.7;
334
+ transition: opacity 0.3s;
335
+ }
336
+
337
+ /*
338
+ * Hide menu for pdf printing
339
+ */
340
+ body.print-pdf .slide-menu-wrapper .slide-menu,
341
+ body.print-pdf .reveal .slide-menu-button,
342
+ body.print-pdf .slide-menu-wrapper .slide-menu-overlay
343
+ {
344
+ display: none;
345
+ }
@@ -0,0 +1,949 @@
1
+ /*
2
+ * Reveal.js menu plugin
3
+ * MIT licensed
4
+ * (c) Greg Denehy 2015
5
+ */
6
+
7
+ var RevealMenu = window.RevealMenu || (function(){
8
+ var config = Reveal.getConfig();
9
+ var options = config.menu || {};
10
+ options.path = options.path || scriptPath() || 'plugin/menu/';
11
+ if (!options.path.endsWith('/')) {
12
+ options.path += '/';
13
+ }
14
+ var loadIcons = options.loadIcons;
15
+ if (typeof loadIcons === "undefined") loadIcons = true;
16
+ var initialised = false;
17
+
18
+ var module = {};
19
+
20
+ loadResource(options.path + 'menu.css', 'stylesheet', function() {
21
+ if (loadIcons) {
22
+ loadResource(options.path + 'font-awesome/css/all.css', 'stylesheet', loadPlugin)
23
+ } else {
24
+ loadPlugin();
25
+ }
26
+ })
27
+
28
+ function loadPlugin() {
29
+ // does not support IE8 or below
30
+ var initialise = !ieVersion || ieVersion >= 9;
31
+
32
+ // do not load the menu in the upcoming slide panel in the speaker notes
33
+ if (Reveal.isSpeakerNotes() && window.location.search.endsWith('controls=false')) {
34
+ initialise = false;
35
+ }
36
+
37
+ if (initialise) {
38
+ //
39
+ // Set option defaults
40
+ //
41
+ var side = options.side || 'left'; // 'left' or 'right'
42
+ var width = options.width;
43
+ var numbers = options.numbers || false;
44
+ var titleSelector = 'h1, h2, h3, h4, h5';
45
+ if (typeof options.titleSelector === 'string') titleSelector = options.titleSelector;
46
+ var hideMissingTitles = options.hideMissingTitles || false;
47
+ var useTextContentForMissingTitles = options.useTextContentForMissingTitles || false;
48
+ var markers = options.markers;
49
+ if (typeof markers === "undefined") markers = true;
50
+ var custom = options.custom;
51
+ var themesPath = typeof options.themesPath === 'string' ? options.themesPath : 'css/theme/';
52
+ if (!themesPath.endsWith('/')) themesPath += '/';
53
+ var themes = select('link#theme') ? options.themes : false;
54
+ if (themes === true) {
55
+ themes = [
56
+ { name: 'Black', theme: themesPath + 'black.css' },
57
+ { name: 'White', theme: themesPath + 'white.css' },
58
+ { name: 'League', theme: themesPath + 'league.css' },
59
+ { name: 'Sky', theme: themesPath + 'sky.css' },
60
+ { name: 'Beige', theme: themesPath + 'beige.css' },
61
+ { name: 'Simple', theme: themesPath + 'simple.css' },
62
+ { name: 'Serif', theme: themesPath + 'serif.css' },
63
+ { name: 'Blood', theme: themesPath + 'blood.css' },
64
+ { name: 'Night', theme: themesPath + 'night.css' },
65
+ { name: 'Moon', theme: themesPath + 'moon.css' },
66
+ { name: 'Solarized', theme: themesPath + 'solarized.css' }
67
+ ];
68
+ } else if (!Array.isArray(themes)) {
69
+ themes = false;
70
+ }
71
+ var transitions = options.transitions || false;
72
+ if (transitions === true) {
73
+ transitions = ['None', 'Fade', 'Slide', 'Convex', 'Concave', 'Zoom'];
74
+ } else if (transitions !== false && (!Array.isArray(transitions) || !transitions.every(function(e) { return typeof e === "string" }))) {
75
+ console.error("reveal.js-menu error: transitions config value must be 'true' or an array of strings, eg ['None', 'Fade', 'Slide')");
76
+ transitions = false;
77
+ }
78
+ if (ieVersion && ieVersion <= 9) {
79
+ // transitions aren't support in IE9 anyway, so no point in showing them
80
+ transitions = false;
81
+ }
82
+ var openButton = options.openButton;
83
+ if (typeof openButton === "undefined") openButton = true;
84
+ var openSlideNumber = options.openSlideNumber;
85
+ if (typeof openSlideNumber === "undefined") openSlideNumber = false;
86
+ var keyboard = options.keyboard;
87
+ if (typeof keyboard === "undefined") keyboard = true;
88
+ var sticky = options.sticky;
89
+ if (typeof sticky === "undefined") sticky = false;
90
+ var autoOpen = options.autoOpen;
91
+ if (typeof autoOpen === "undefined") autoOpen = true;
92
+ var delayInit = options.delayInit;
93
+ if (typeof delayInit === "undefined") delayInit = false;
94
+ var openOnInit = options.openOnInit || false;
95
+
96
+ var mouseSelectionEnabled = true;
97
+ function disableMouseSelection() {
98
+ mouseSelectionEnabled = false;
99
+ }
100
+
101
+ function reenableMouseSelection() {
102
+ // wait until the mouse has moved before re-enabling mouse selection
103
+ // to avoid selections on scroll
104
+ select('nav.slide-menu').addEventListener('mousemove', function fn(e) {
105
+ select('nav.slide-menu').removeEventListener('mousemove', fn);
106
+ //XXX this should select the item under the mouse
107
+ mouseSelectionEnabled = true;
108
+ });
109
+ }
110
+
111
+ //
112
+ // Keyboard handling
113
+ //
114
+ function getOffset(el) {
115
+ var _x = 0;
116
+ var _y = 0;
117
+ while(el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
118
+ _x += el.offsetLeft - el.scrollLeft;
119
+ _y += el.offsetTop - el.scrollTop;
120
+ el = el.offsetParent;
121
+ }
122
+ return { top: _y, left: _x };
123
+ }
124
+
125
+ function visibleOffset(el) {
126
+ var offsetFromTop = getOffset(el).top - el.offsetParent.offsetTop;
127
+ if (offsetFromTop < 0) return -offsetFromTop
128
+ var offsetFromBottom = el.offsetParent.offsetHeight - (el.offsetTop - el.offsetParent.scrollTop + el.offsetHeight);
129
+ if (offsetFromBottom < 0) return offsetFromBottom;
130
+ return 0;
131
+ }
132
+
133
+ function keepVisible(el) {
134
+ var offset = visibleOffset(el);
135
+ if (offset) {
136
+ disableMouseSelection();
137
+ el.scrollIntoView(offset > 0);
138
+ reenableMouseSelection();
139
+ }
140
+ }
141
+
142
+ function scrollItemToTop(el) {
143
+ disableMouseSelection();
144
+ el.offsetParent.scrollTop = el.offsetTop;
145
+ reenableMouseSelection();
146
+ }
147
+
148
+ function scrollItemToBottom(el) {
149
+ disableMouseSelection();
150
+ el.offsetParent.scrollTop = el.offsetTop - el.offsetParent.offsetHeight + el.offsetHeight
151
+ reenableMouseSelection();
152
+ }
153
+
154
+ function selectItem(el) {
155
+ el.classList.add('selected');
156
+ keepVisible(el);
157
+ if (sticky && autoOpen) openItem(el);
158
+ }
159
+
160
+ function onDocumentKeyDown(event) {
161
+ if (event.keyCode === 77) {
162
+ toggleMenu();
163
+ } else if (isOpen()) {
164
+ event.stopImmediatePropagation();
165
+ switch( event.keyCode ) {
166
+ // h, left - change panel
167
+ case 72: case 37:
168
+ prevPanel();
169
+ break;
170
+ // l, right - change panel
171
+ case 76: case 39:
172
+ nextPanel();
173
+ break;
174
+ // k, up
175
+ case 75: case 38:
176
+ var currItem = select('.active-menu-panel .slide-menu-items li.selected') || select('.active-menu-panel .slide-menu-items li.active');
177
+ if (currItem) {
178
+ selectAll('.active-menu-panel .slide-menu-items li').forEach(function(item) { item.classList.remove('selected') });
179
+ var nextItem = select('.active-menu-panel .slide-menu-items li[data-item="' + (parseInt(currItem.getAttribute('data-item')) - 1) + '"]') || currItem;
180
+ selectItem(nextItem);
181
+ } else {
182
+ var item = select('.active-menu-panel .slide-menu-items li.slide-menu-item');
183
+ if (item) selectItem(item);
184
+ }
185
+ break;
186
+ // j, down
187
+ case 74: case 40:
188
+ var currItem = select('.active-menu-panel .slide-menu-items li.selected') || select('.active-menu-panel .slide-menu-items li.active');
189
+ if (currItem) {
190
+ selectAll('.active-menu-panel .slide-menu-items li').forEach(function(item) { item.classList.remove('selected') });
191
+ var nextItem = select('.active-menu-panel .slide-menu-items li[data-item="' + (parseInt(currItem.getAttribute('data-item')) + 1) + '"]') || currItem;
192
+ selectItem(nextItem);
193
+ } else {
194
+ var item = select('.active-menu-panel .slide-menu-items li.slide-menu-item');
195
+ if (item) selectItem(item);
196
+ }
197
+ break;
198
+ // pageup, u
199
+ case 33: case 85:
200
+ var itemsAbove = selectAll('.active-menu-panel .slide-menu-items li').filter(function(item) { return visibleOffset(item) > 0; });
201
+ var visibleItems = selectAll('.active-menu-panel .slide-menu-items li').filter(function(item) { return visibleOffset(item) == 0; });
202
+
203
+ var firstVisible = (itemsAbove.length > 0 && Math.abs(visibleOffset(itemsAbove[itemsAbove.length-1])) < itemsAbove[itemsAbove.length-1].clientHeight ? itemsAbove[itemsAbove.length-1] : visibleItems[0]);
204
+ if (firstVisible) {
205
+ if (firstVisible.classList.contains('selected') && itemsAbove.length > 0) {
206
+ // at top of viewport already, page scroll (if not at start)
207
+ // ...move selected item to bottom, and change selection to last fully visible item at top
208
+ scrollItemToBottom(firstVisible);
209
+ visibleItems = selectAll('.active-menu-panel .slide-menu-items li').filter(function(item) { return visibleOffset(item) == 0; });
210
+ if (visibleItems[0] == firstVisible) {
211
+ // prev item is still beyond the viewport (for custom panels)
212
+ firstVisible = itemsAbove[itemsAbove.length-1];
213
+ } else {
214
+ firstVisible = visibleItems[0];
215
+ }
216
+ }
217
+ selectAll('.active-menu-panel .slide-menu-items li').forEach(function(item) { item.classList.remove('selected') });
218
+ selectItem(firstVisible);
219
+ // ensure selected item is positioned at the top of the viewport
220
+ scrollItemToTop(firstVisible);
221
+ }
222
+ break;
223
+ // pagedown, d
224
+ case 34: case 68:
225
+ var visibleItems = selectAll('.active-menu-panel .slide-menu-items li').filter(function(item) { return visibleOffset(item) == 0; });
226
+ var itemsBelow = selectAll('.active-menu-panel .slide-menu-items li').filter(function(item) { return visibleOffset(item) < 0; });
227
+
228
+ var lastVisible = (itemsBelow.length > 0 && Math.abs(visibleOffset(itemsBelow[0])) < itemsBelow[0].clientHeight ? itemsBelow[0] : visibleItems[visibleItems.length-1]);
229
+ if (lastVisible) {
230
+ if (lastVisible.classList.contains('selected') && itemsBelow.length > 0) {
231
+ // at bottom of viewport already, page scroll (if not at end)
232
+ // ...move selected item to top, and change selection to last fully visible item at bottom
233
+ scrollItemToTop(lastVisible);
234
+ visibleItems = selectAll('.active-menu-panel .slide-menu-items li').filter(function(item) { return visibleOffset(item) == 0; });
235
+ if (visibleItems[visibleItems.length-1] == lastVisible) {
236
+ // next item is still beyond the viewport (for custom panels)
237
+ lastVisible = itemsBelow[0];
238
+ } else {
239
+ lastVisible = visibleItems[visibleItems.length-1];
240
+ }
241
+ }
242
+ selectAll('.active-menu-panel .slide-menu-items li').forEach(function(item) { item.classList.remove('selected') });
243
+ selectItem(lastVisible);
244
+ // ensure selected item is positioned at the bottom of the viewport
245
+ scrollItemToBottom(lastVisible);
246
+ }
247
+ break;
248
+ // home
249
+ case 36:
250
+ selectAll('.active-menu-panel .slide-menu-items li').forEach(function(item) { item.classList.remove('selected') });
251
+ var item = select('.active-menu-panel .slide-menu-items li:first-of-type');
252
+ if (item) {
253
+ item.classList.add('selected');
254
+ keepVisible(item);
255
+ }
256
+ break;
257
+ // end
258
+ case 35:
259
+ selectAll('.active-menu-panel .slide-menu-items li').forEach(function(item) { item.classList.remove('selected') });
260
+ var item = select('.active-menu-panel .slide-menu-items:last-of-type li:last-of-type');
261
+ if (item) {
262
+ item.classList.add('selected');
263
+ keepVisible(item);
264
+ }
265
+ break;
266
+ // space, return
267
+ case 32: case 13:
268
+ var currItem = select('.active-menu-panel .slide-menu-items li.selected');
269
+ if (currItem) {
270
+ openItem(currItem, true);
271
+ }
272
+ break;
273
+ // esc
274
+ case 27: closeMenu(null, true); break;
275
+ }
276
+ }
277
+ }
278
+
279
+ if (keyboard) {
280
+ //XXX add keyboard option for custom key codes, etc.
281
+
282
+ document.addEventListener('keydown', onDocumentKeyDown, false);
283
+
284
+ // handle key presses within speaker notes
285
+ window.addEventListener( 'message', function( event ) {
286
+ var data;
287
+ try {
288
+ data = JSON.parse( event.data );
289
+ } catch (e) {
290
+ }
291
+ if (data && data.method === 'triggerKey') {
292
+ onDocumentKeyDown( { keyCode: data.args[0], stopImmediatePropagation: function() {} } );
293
+ }
294
+ });
295
+
296
+ // Prevent reveal from processing keyboard events when the menu is open
297
+ if (config.keyboardCondition && typeof config.keyboardCondition === 'function') {
298
+ // combine user defined keyboard condition with the menu's own condition
299
+ var userCondition = config.keyboardCondition;
300
+ config.keyboardCondition = function() {
301
+ return userCondition() && !isOpen();
302
+ };
303
+ } else {
304
+ config.keyboardCondition = function() { return !isOpen(); }
305
+ }
306
+ }
307
+
308
+
309
+ //
310
+ // Utilty functions
311
+ //
312
+
313
+ function openMenu(event) {
314
+ if (event) event.preventDefault();
315
+ if (!isOpen()) {
316
+ select('body').classList.add('slide-menu-active');
317
+ select('.reveal').classList.add('has-' + options.effect + '-' + side);
318
+ select('.slide-menu').classList.add('active');
319
+ select('.slide-menu-overlay').classList.add('active');
320
+
321
+ // identify active theme
322
+ if (themes) {
323
+ selectAll('div[data-panel="Themes"] li').forEach(function(i) { i.classList.remove('active') });
324
+ selectAll('li[data-theme="' + select('link#theme').getAttribute('href') + '"]').forEach(function(i) { i.classList.add('active') });
325
+ }
326
+
327
+ // identify active transition
328
+ if (transitions) {
329
+ selectAll('div[data-panel="Transitions"] li').forEach(function(i) { i.classList.remove('active') });
330
+ selectAll('li[data-transition="' + Reveal.getConfig().transition + '"]').forEach(function(i) { i.classList.add('active') });
331
+ }
332
+
333
+ // set item selections to match active items
334
+ var items = selectAll('.slide-menu-panel li.active')
335
+ items.forEach(function(i) {
336
+ i.classList.add('selected');
337
+ keepVisible(i);
338
+ });
339
+ }
340
+ }
341
+
342
+ function closeMenu(event, force) {
343
+ if (event) event.preventDefault();
344
+ if (!sticky || force) {
345
+ select('body').classList.remove('slide-menu-active');
346
+ select('.reveal').classList.remove('has-' + options.effect + '-' + side);
347
+ select('.slide-menu').classList.remove('active');
348
+ select('.slide-menu-overlay').classList.remove('active');
349
+ selectAll('.slide-menu-panel li.selected').forEach(function(i) { i.classList.remove('selected') });
350
+ }
351
+ }
352
+
353
+ function toggleMenu(event) {
354
+ if (isOpen()) {
355
+ closeMenu(event, true);
356
+ } else {
357
+ openMenu(event);
358
+ }
359
+ }
360
+
361
+ function isOpen() {
362
+ return select('body').classList.contains('slide-menu-active');
363
+ }
364
+
365
+ function openPanel(event, ref) {
366
+ openMenu(event);
367
+ var panel = ref;
368
+ if (typeof ref !== "string") {
369
+ panel = event.currentTarget.getAttribute('data-panel');
370
+ }
371
+ select('.slide-menu-toolbar > li.active-toolbar-button').classList.remove('active-toolbar-button');
372
+ select('li[data-panel="' + panel + '"]').classList.add('active-toolbar-button');
373
+ select('.slide-menu-panel.active-menu-panel').classList.remove('active-menu-panel');
374
+ select('div[data-panel="' + panel + '"]').classList.add('active-menu-panel');
375
+ }
376
+
377
+ function nextPanel() {
378
+ var next = (parseInt(select('.active-toolbar-button').getAttribute('data-button')) + 1) % buttons;
379
+ openPanel(null, select('.toolbar-panel-button[data-button="' + next + '"]').getAttribute('data-panel'));
380
+ }
381
+
382
+ function prevPanel() {
383
+ var next = parseInt(select('.active-toolbar-button').getAttribute('data-button')) - 1;
384
+ if (next < 0) {
385
+ next = buttons - 1;
386
+ }
387
+ openPanel(null, select('.toolbar-panel-button[data-button="' + next + '"]').getAttribute('data-panel'));
388
+ }
389
+
390
+ function openItem(item, force) {
391
+ var h = parseInt(item.getAttribute('data-slide-h'));
392
+ var v = parseInt(item.getAttribute('data-slide-v'));
393
+ var theme = item.getAttribute('data-theme');
394
+ var transition = item.getAttribute('data-transition');
395
+ if (!isNaN(h) && !isNaN(v)) {
396
+ Reveal.slide(h, v);
397
+ closeMenu();
398
+ } else if (theme) {
399
+ // take note of the previous theme and remove it, then create a new stylesheet reference and insert it
400
+ // this is required to force a load event so we can change the menu style to match the new style
401
+ var stylesheet = select('link#theme');
402
+ var parent = stylesheet.parentElement;
403
+ var sibling = stylesheet.nextElementSibling;
404
+ stylesheet.remove();
405
+
406
+ var newStylesheet = stylesheet.cloneNode();
407
+ newStylesheet.setAttribute('href', theme);
408
+ newStylesheet.onload = function() { matchRevealStyle() };
409
+ parent.insertBefore(newStylesheet, sibling);
410
+
411
+ closeMenu();
412
+ } else if (transition) {
413
+ Reveal.configure({ transition: transition });
414
+ closeMenu();
415
+ } else {
416
+ var link = select('a', item);
417
+ if (link) {
418
+ if (force || !sticky || (autoOpen && link.href.startsWith('#') || link.href.startsWith(window.location.origin + window.location.pathname + '#'))) {
419
+ link.click();
420
+ }
421
+ }
422
+ closeMenu();
423
+ }
424
+ }
425
+
426
+ function clicked(event) {
427
+ if (event.target.nodeName !== "A") {
428
+ event.preventDefault();
429
+ }
430
+ openItem(event.currentTarget);
431
+ }
432
+
433
+ function highlightCurrentSlide() {
434
+ var state = Reveal.getState();
435
+ selectAll('li.slide-menu-item, li.slide-menu-item-vertical').forEach(function(item) {
436
+ item.classList.remove('past');
437
+ item.classList.remove('active');
438
+ item.classList.remove('future');
439
+
440
+ var h = parseInt(item.getAttribute('data-slide-h'));
441
+ var v = parseInt(item.getAttribute('data-slide-v'));
442
+ if (h < state.indexh || (h === state.indexh && v < state.indexv)) {
443
+ item.classList.add('past');
444
+ }
445
+ else if (h === state.indexh && v === state.indexv) {
446
+ item.classList.add('active');
447
+ }
448
+ else {
449
+ item.classList.add('future');
450
+ }
451
+ });
452
+ }
453
+
454
+ function matchRevealStyle() {
455
+ var revealStyle = window.getComputedStyle(select('.reveal'));
456
+ var element = select('.slide-menu');
457
+ element.style.fontFamily = revealStyle.fontFamily;
458
+ //XXX could adjust the complete menu style to match the theme, ie colors, etc
459
+ }
460
+
461
+ var buttons = 0;
462
+ function init() {
463
+ if (!initialised) {
464
+ var parent = select('.reveal').parentElement;
465
+ var top = create('div', { 'class': 'slide-menu-wrapper'});
466
+ parent.appendChild(top);
467
+ var panels = create('nav', { 'class': 'slide-menu slide-menu--' + side});
468
+ if (typeof width === 'string') {
469
+ if (['normal', 'wide', 'third', 'half', 'full'].indexOf(width) != -1) {
470
+ panels.classList.add('slide-menu--' + width);
471
+ }
472
+ else {
473
+ panels.classList.add('slide-menu--custom');
474
+ panels.style.width = width;
475
+ }
476
+ }
477
+ top.appendChild(panels);
478
+ matchRevealStyle();
479
+ var overlay = create('div', { 'class': 'slide-menu-overlay'});
480
+ top.appendChild(overlay);
481
+ overlay.onclick = function() { closeMenu(null, true) };
482
+
483
+ var toolbar = create('ol', {'class': 'slide-menu-toolbar'});
484
+ select('.slide-menu').appendChild(toolbar);
485
+
486
+ function addToolbarButton(title, ref, icon, style, fn, active) {
487
+ var attrs = {
488
+ 'data-button': '' + (buttons++),
489
+ 'class': 'toolbar-panel-button' + (active ? ' active-toolbar-button' : '')
490
+ };
491
+ if (ref) {
492
+ attrs['data-panel'] = ref;
493
+ }
494
+ var button = create('li', attrs);
495
+
496
+ if (icon.startsWith('fa-')) {
497
+ button.appendChild(create('i', {'class': style + ' ' + icon}));
498
+ } else {
499
+ button.innerHTML = icon + '</i>';
500
+ }
501
+ button.appendChild(create('br'), select('i', button));
502
+ button.appendChild(create('span', {'class': 'slide-menu-toolbar-label'}, title), select('i', button));
503
+ button.onclick = fn;
504
+ toolbar.appendChild(button);
505
+ return button;
506
+ }
507
+
508
+ addToolbarButton('Slides', 'Slides', 'fa-images', 'fas', openPanel, true);
509
+
510
+ if (custom) {
511
+ custom.forEach(function(element, index, array) {
512
+ addToolbarButton(element.title, 'Custom' + index, element.icon, null, openPanel);
513
+ });
514
+ }
515
+
516
+ if (themes) {
517
+ addToolbarButton('Themes', 'Themes', 'fa-adjust', 'fas', openPanel);
518
+ }
519
+ if (transitions) {
520
+ addToolbarButton('Transitions', 'Transitions', 'fa-sticky-note', 'fas', openPanel);
521
+ }
522
+ button = create('li', {id: 'close', 'class': 'toolbar-panel-button'});
523
+ button.appendChild(create('i', {'class': 'fas fa-times'}));
524
+ button.appendChild(create('br'));
525
+ button.appendChild(create('span', {'class': 'slide-menu-toolbar-label'}, 'Close'));
526
+ button.onclick = function() { closeMenu(null, true) };
527
+ toolbar.appendChild(button);
528
+
529
+ //
530
+ // Slide links
531
+ //
532
+ function generateItem(type, section, i, h, v) {
533
+ var link = '/#/' + h;
534
+ if (typeof v === 'number' && !isNaN( v )) link += '/' + v;
535
+
536
+ function text(selector, parent) {
537
+ var el = (parent ? select(selector, section) : select(selector));
538
+ if (el) return el.textContent;
539
+ return null;
540
+ }
541
+ var title = section.getAttribute('data-menu-title') ||
542
+ text('.menu-title', section) ||
543
+ text(titleSelector, section);
544
+
545
+ if (!title && useTextContentForMissingTitles) {
546
+ // attempt to figure out a title based on the text in the slide
547
+ title = section.textContent.trim();
548
+ if (title) {
549
+ title = title.split('\n')
550
+ .map(function(t) { return t.trim() }).join(' ').trim()
551
+ .replace(/^(.{16}[^\s]*).*/, "$1") // limit to 16 chars plus any consecutive non-whitespace chars (to avoid breaking words)
552
+ .replace(/&/g, "&amp;")
553
+ .replace(/</g, "&lt;")
554
+ .replace(/>/g, "&gt;")
555
+ .replace(/"/g, "&quot;")
556
+ .replace(/'/g, "&#039;") + '...';
557
+ }
558
+ }
559
+
560
+ if (!title) {
561
+ if (hideMissingTitles) return '';
562
+ type += ' no-title';
563
+ title = "Slide " + i;
564
+ }
565
+
566
+ var item = create('li', {
567
+ class: type,
568
+ 'data-item': i,
569
+ 'data-slide-h': h,
570
+ 'data-slide-v': (v === undefined ? 0 : v)
571
+ });
572
+
573
+ if (markers) {
574
+ item.appendChild(create('i', {class: 'fas fa-check-circle fa-fw past'}));
575
+ item.appendChild(create('i', {class: 'fas fa-arrow-alt-circle-right fa-fw active'}));
576
+ item.appendChild(create('i', {class: 'far fa-circle fa-fw future'}));
577
+ }
578
+
579
+ if (numbers) {
580
+ // Number formatting taken from reveal.js
581
+ var value = [];
582
+ var format = 'h.v';
583
+
584
+ // Check if a custom number format is available
585
+ if( typeof numbers === 'string' ) {
586
+ format = numbers;
587
+ }
588
+ else if (typeof config.slideNumber === 'string') {
589
+ // Take user defined number format for slides
590
+ format = config.slideNumber;
591
+ }
592
+
593
+ switch( format ) {
594
+ case 'c':
595
+ value.push( i );
596
+ break;
597
+ case 'c/t':
598
+ value.push( i, '/', Reveal.getTotalSlides() );
599
+ break;
600
+ case 'h/v':
601
+ value.push( h + 1 );
602
+ if( typeof v === 'number' && !isNaN( v ) ) value.push( '/', v + 1 );
603
+ break;
604
+ default:
605
+ value.push( h + 1 );
606
+ if( typeof v === 'number' && !isNaN( v ) ) value.push( '.', v + 1 );
607
+ }
608
+
609
+ item.appendChild(create('span', {class: 'slide-menu-item-number'}, value.join('') + '. '));
610
+ }
611
+
612
+ item.appendChild(create('span', {class: 'slide-menu-item-title'}, title));
613
+
614
+ return item;
615
+ }
616
+
617
+ function createSlideMenu() {
618
+ if ( !document.querySelector('section[data-markdown]:not([data-markdown-parsed])') ) {
619
+ var panel = create('div', {
620
+ 'data-panel': 'Slides',
621
+ 'class': 'slide-menu-panel active-menu-panel'
622
+ });
623
+ panel.appendChild(create('ul', {class: "slide-menu-items"}));
624
+ panels.appendChild(panel);
625
+ var items = select('.slide-menu-panel[data-panel="Slides"] > .slide-menu-items');
626
+ var slideCount = 0;
627
+ selectAll('.slides > section').forEach(function(section, h) {
628
+ var subsections = selectAll('section', section);
629
+ if (subsections.length > 0) {
630
+ subsections.forEach(function(subsection, v) {
631
+ var type = (v === 0 ? 'slide-menu-item' : 'slide-menu-item-vertical');
632
+ var item = generateItem(type, subsection, slideCount, h, v);
633
+ if (item) {
634
+ slideCount++;
635
+ items.appendChild(item);
636
+ }
637
+ });
638
+ } else {
639
+ var item = generateItem('slide-menu-item', section, slideCount, h);
640
+ if (item) {
641
+ slideCount++;
642
+ items.appendChild(item);
643
+ }
644
+ }
645
+ });
646
+ selectAll('.slide-menu-item, .slide-menu-item-vertical').forEach(function(i) {
647
+ i.onclick = clicked;
648
+ });
649
+ highlightCurrentSlide();
650
+ }
651
+ else {
652
+ // wait for markdown to be loaded and parsed
653
+ setTimeout( createSlideMenu, 100 );
654
+ }
655
+ }
656
+
657
+ createSlideMenu();
658
+ Reveal.addEventListener('slidechanged', highlightCurrentSlide);
659
+
660
+ //
661
+ // Custom menu panels
662
+ //
663
+ if (custom) {
664
+ function xhrSuccess () {
665
+ if (this.status >= 200 && this.status < 300) {
666
+ this.panel.innerHTML = this.responseText;
667
+ enableCustomLinks(this.panel);
668
+ }
669
+ else {
670
+ showErrorMsg(this)
671
+ }
672
+ }
673
+ function xhrError () {
674
+ showErrorMsg(this)
675
+ }
676
+ function loadCustomPanelContent (panel, sURL) {
677
+ var oReq = new XMLHttpRequest();
678
+ oReq.panel = panel;
679
+ oReq.arguments = Array.prototype.slice.call(arguments, 2);
680
+ oReq.onload = xhrSuccess;
681
+ oReq.onerror = xhrError;
682
+ oReq.open("get", sURL, true);
683
+ oReq.send(null);
684
+ }
685
+ function enableCustomLinks(panel) {
686
+ selectAll('ul.slide-menu-items li.slide-menu-item', panel).forEach(function(item, i) {
687
+ item.setAttribute('data-item', i+1);
688
+ item.onclick = clicked;
689
+ item.addEventListener("mouseenter", handleMouseHighlight);
690
+ });
691
+ }
692
+
693
+ function showErrorMsg(response) {
694
+ var msg = '<p>ERROR: The attempt to fetch ' + response.responseURL + ' failed with HTTP status ' +
695
+ response.status + ' (' + response.statusText + ').</p>' +
696
+ '<p>Remember that you need to serve the presentation HTML from a HTTP server.</p>';
697
+ response.panel.innerHTML = msg;
698
+ }
699
+
700
+ custom.forEach(function(element, index, array) {
701
+ var panel = create('div', {
702
+ 'data-panel': 'Custom' + index,
703
+ class: 'slide-menu-panel slide-menu-custom-panel'
704
+ });
705
+ if (element.content) {
706
+ panel.innerHTML = element.content;
707
+ enableCustomLinks(panel);
708
+ }
709
+ else if (element.src) {
710
+ loadCustomPanelContent(panel, element.src);
711
+ }
712
+ panels.appendChild(panel);
713
+ })
714
+ }
715
+
716
+ //
717
+ // Themes
718
+ //
719
+ if (themes) {
720
+ var panel = create('div', {
721
+ class: 'slide-menu-panel',
722
+ 'data-panel': 'Themes'
723
+ });
724
+ panels.appendChild(panel);
725
+ var menu = create('ul', {class: 'slide-menu-items'});
726
+ panel.appendChild(menu);
727
+ themes.forEach(function(t, i) {
728
+ var item = create('li', {
729
+ class: 'slide-menu-item',
730
+ 'data-theme': t.theme,
731
+ 'data-item': ''+(i+1)
732
+ }, t.name);
733
+ menu.appendChild(item);
734
+ item.onclick = clicked;
735
+ })
736
+ }
737
+
738
+ //
739
+ // Transitions
740
+ //
741
+ if (transitions) {
742
+ var panel = create('div', {
743
+ class: 'slide-menu-panel',
744
+ 'data-panel': 'Transitions'
745
+ });
746
+ panels.appendChild(panel);
747
+ var menu = create('ul', {class: 'slide-menu-items'});
748
+ panel.appendChild(menu);
749
+ transitions.forEach(function(name, i) {
750
+ var item = create('li', {
751
+ class: 'slide-menu-item',
752
+ 'data-transition': name.toLowerCase(),
753
+ 'data-item': ''+(i+1)
754
+ }, name);
755
+ menu.appendChild(item);
756
+ item.onclick = clicked;
757
+ })
758
+ }
759
+
760
+ //
761
+ // Open menu options
762
+ //
763
+ if (openButton) {
764
+ // add menu button
765
+ var div = create('div', {class: 'slide-menu-button'});
766
+ var link = create('a', {href: '#'});
767
+ link.appendChild(create('i', {class: 'fas fa-bars'}));
768
+ div.appendChild(link);
769
+ select('.reveal').appendChild(div);
770
+ div.onclick = openMenu;
771
+ }
772
+
773
+ if (openSlideNumber) {
774
+ // wrap slide number in link
775
+ var slideNumber = select('div.slide-number');
776
+ var wrapper = create('div', {class: 'slide-number-wrapper'});
777
+ var link = create('a', {href: '#'});
778
+ wrapper.appendChild(link);
779
+ slideNumber.parentElement.insertBefore(wrapper, slideNumber);
780
+ link.appendChild(slideNumber);
781
+ link.onclick = openMenu;
782
+ }
783
+
784
+ //
785
+ // Handle mouse overs
786
+ //
787
+ selectAll('.slide-menu-panel .slide-menu-items li').forEach(function(item) {
788
+ item.addEventListener("mouseenter", handleMouseHighlight);
789
+ });
790
+
791
+ function handleMouseHighlight(event) {
792
+ if (mouseSelectionEnabled) {
793
+ selectAll('.active-menu-panel .slide-menu-items li.selected').forEach(function(i) {
794
+ i.classList.remove('selected');
795
+ });
796
+ event.currentTarget.classList.add('selected');
797
+ }
798
+ }
799
+ }
800
+ if (openOnInit) {
801
+ openMenu();
802
+ }
803
+ initialised = true;
804
+ }
805
+
806
+ module.toggle = toggleMenu;
807
+ module.openMenu = openMenu;
808
+ module.closeMenu = closeMenu;
809
+ module.openPanel = openPanel;
810
+ module.isOpen = isOpen;
811
+ module.init = init;
812
+ module.isInit = function() { return initialised };
813
+
814
+ if (!delayInit) {
815
+ init();
816
+ }
817
+
818
+ /**
819
+ * Extend object a with the properties of object b.
820
+ * If there's a conflict, object b takes precedence.
821
+ */
822
+ function extend( a, b ) {
823
+ for( var i in b ) {
824
+ a[ i ] = b[ i ];
825
+ }
826
+ }
827
+
828
+ /**
829
+ * Dispatches an event of the specified type from the
830
+ * reveal DOM element.
831
+ */
832
+ function dispatchEvent( type, args ) {
833
+ var event = document.createEvent( 'HTMLEvents', 1, 2 );
834
+ event.initEvent( type, true, true );
835
+ extend( event, args );
836
+ document.querySelector('.reveal').dispatchEvent( event );
837
+
838
+ // If we're in an iframe, post each reveal.js event to the
839
+ // parent window. Used by the notes plugin
840
+ if( config.postMessageEvents && window.parent !== window.self ) {
841
+ window.parent.postMessage( JSON.stringify({ namespace: 'reveal', eventName: type, state: Reveal.getState() }), '*' );
842
+ }
843
+ }
844
+
845
+ dispatchEvent('menu-ready');
846
+ }
847
+ }
848
+
849
+ function select(selector, el) {
850
+ if (!el) {
851
+ el = document;
852
+ }
853
+ return el.querySelector(selector);
854
+ }
855
+
856
+ function selectAll(selector, el) {
857
+ if (!el) {
858
+ el = document;
859
+ }
860
+ return Array.prototype.slice.call(el.querySelectorAll(selector));
861
+ }
862
+
863
+ function create(tagName, attrs, content) {
864
+ var el = document.createElement(tagName);
865
+ if (attrs) {
866
+ Object.getOwnPropertyNames(attrs).forEach(function(n) {
867
+ el.setAttribute(n, attrs[n]);
868
+ });
869
+ }
870
+ if (content) el.innerHTML = content;
871
+ return el;
872
+ }
873
+
874
+ // modified from math plugin
875
+ function loadResource( url, type, callback ) {
876
+ var head = document.querySelector( 'head' );
877
+ var resource;
878
+
879
+ if ( type === 'script' ) {
880
+ resource = document.createElement( 'script' );
881
+ resource.type = 'text/javascript';
882
+ resource.src = url;
883
+ }
884
+ else if ( type === 'stylesheet' ) {
885
+ resource = document.createElement( 'link' );
886
+ resource.rel = 'stylesheet';
887
+ resource.href = url;
888
+ }
889
+
890
+ // Wrapper for callback to make sure it only fires once
891
+ var finish = function() {
892
+ if( typeof callback === 'function' ) {
893
+ callback.call();
894
+ callback = null;
895
+ }
896
+ }
897
+
898
+ resource.onload = finish;
899
+
900
+ // IE
901
+ resource.onreadystatechange = function() {
902
+ if ( this.readyState === 'loaded' ) {
903
+ finish();
904
+ }
905
+ }
906
+
907
+ // Normal browsers
908
+ head.appendChild( resource );
909
+ }
910
+
911
+ function scriptPath() {
912
+ // obtain plugin path from the script element
913
+ var path;
914
+ if (document.currentScript) {
915
+ path = document.currentScript.src.slice(0, -7);
916
+ } else {
917
+ var sel = document.querySelector('script[src$="menu.js"]');
918
+ if (sel) {
919
+ path = sel.src.slice(0, -7);
920
+ }
921
+ }
922
+ return path;
923
+ }
924
+
925
+ // polyfill
926
+ if (!String.prototype.startsWith) {
927
+ String.prototype.startsWith = function(searchString, position){
928
+ return this.substr(position || 0, searchString.length) === searchString;
929
+ };
930
+ }
931
+ if (!String.prototype.endsWith) {
932
+ String.prototype.endsWith = function(search, this_len) {
933
+ if (this_len === undefined || this_len > this.length) {
934
+ this_len = this.length;
935
+ }
936
+ return this.substring(this_len - search.length, this_len) === search;
937
+ };
938
+ }
939
+
940
+ var ieVersion = function() {
941
+ var browser = /(msie) ([\w.]+)/.exec(window.navigator.userAgent.toLowerCase());
942
+ if (browser && browser[1] === "msie") {
943
+ return parseFloat(browser[2]);
944
+ }
945
+ return null;
946
+ }();
947
+
948
+ return module;
949
+ })();