aboutsummaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/slides.js482
1 files changed, 482 insertions, 0 deletions
diff --git a/js/slides.js b/js/slides.js
new file mode 100644
index 0000000..3cb2852
--- /dev/null
+++ b/js/slides.js
@@ -0,0 +1,482 @@
1/**
2 * @constructor
3 */
4function SlideDeck() {
5 this.curSlide_ = 0;
6 this.slides = [];
7 this.config_ = null;
8
9 this.getCurrentSlideFromHash_();
10
11 document.addEventListener('DOMContentLoaded',
12 this.handleDomLoaded_.bind(this), false);
13}
14
15/**
16 * @const
17 * @private
18 */
19SlideDeck.prototype.SLIDE_CLASSES_ = [
20 'far-past', 'past', 'current', 'next', 'far-next'];
21
22/**
23 * @const
24 * @private
25 */
26SlideDeck.prototype.CSS_DIR_ = 'theme/css/';
27
28/**
29 * @private
30 */
31SlideDeck.prototype.getCurrentSlideFromHash_ = function() {
32 var slideNo = parseInt(document.location.hash.substr(1));
33
34 if (slideNo) {
35 this.curSlide_ = slideNo - 1;
36 } else {
37 this.curSlide_ = 0;
38 }
39};
40
41/**
42 * @private
43 */
44SlideDeck.prototype.handleDomLoaded_ = function() {
45 this.slides_ = document.querySelectorAll('slide:not(.hidden)');
46
47 for (var i = 0, slide; slide = this.slides_[i]; ++i) {
48 slide.dataset.slideNum = i + 1;
49 slide.dataset.totalSlides = this.slides_.length;
50 }
51
52 // Load config
53 this.loadConfig_();
54 this.addEventListeners_();
55 this.updateSlides_();
56};
57
58/**
59 * @private
60 */
61SlideDeck.prototype.addEventListeners_ = function() {
62 document.addEventListener('keydown', this.handleBodyKeyDown_.bind(this),
63 false);
64 window.addEventListener('popstate', this.handlePopState_.bind(this),
65 false);
66};
67
68/**
69 * @private
70 * @param {Event} e
71 */
72SlideDeck.prototype.handlePopState_ = function(e) {
73 if (e.state != null) {
74 this.curSlide_ = e.state;
75 this.updateSlides_(true);
76 }
77};
78
79/**
80 * @param {Event} e
81 */
82SlideDeck.prototype.handleBodyKeyDown_ = function(e) {
83 if (/^(input|textarea)$/i.test(e.target.nodeName) ||
84 e.target.isContentEditable) {
85 return;
86 }
87
88 switch (e.keyCode) {
89 case 39: // right arrow
90 case 32: // space
91 case 34: // PgDn
92 this.nextSlide();
93 e.preventDefault();
94 break;
95
96 case 37: // left arrow
97 case 8: // Backspace
98 case 33: // PgUp
99 this.prevSlide();
100 e.preventDefault();
101 break;
102
103 case 40: // down arrow
104 //if (this.isChromeVoxActive()) {
105 // speakNextItem();
106 //} else {
107 this.nextSlide();
108 //}
109 e.preventDefault();
110 break;
111
112 case 38: // up arrow
113 //if (this.isChromeVoxActive()) {
114 // speakPrevItem();
115 //} else {
116 this.prevSlide();
117 //}
118 e.preventDefault();
119 break;
120
121 case 78: // N
122 document.body.classList.toggle('with-notes');
123 break;
124
125 case 27: // ESC
126 document.body.classList.remove('with-notes');
127 break;
128
129 //case 13: // Enter
130 case 70: // F
131 // Only respect 'f'/enter on body. Don't want to capture keys from <input>
132 if (e.target == document.body) {
133 if (e.keyCode != 13 && !document.webkitIsFullScreen) {
134 document.body.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
135 } else {
136 document.webkitCancelFullScreen();
137 }
138 }
139 break;
140 }
141};
142
143/**
144 * @private
145 */
146SlideDeck.prototype.loadConfig_ = function() {
147 var configScripts =
148 document.querySelector('script[type="text/slide-config"]');
149 if (configScripts) {
150 eval(configScripts.innerHTML);
151 this.config_ = slideConfig;
152 }
153
154 var settings = this.config_.settings;
155
156 this.loadTheme_(settings.theme || 'default');
157
158 if (settings.favIcon) {
159 this.addFavIcon_(settings.favIcon);
160 }
161
162 if (settings.title) {
163 document.title = settings.title;
164 }
165
166 if (!!!('usePrettify' in settings) || settings.usePrettify) {
167 console.log('Use prettify');
168 //TODO
169 }
170
171 if (settings.analyticsId) {
172 this.loadAnalytics_();
173 }
174
175 if (settings.fonts) {
176 this.addFonts_(settings.fonts);
177 }
178
179 if (settings.useBuilds || true) {
180 this.makeBuildLists_();
181 }
182};
183
184/**
185 * @private
186 * @param {Array.<string>} fonts
187 */
188SlideDeck.prototype.addFonts_ = function(fonts) {
189 var el = document.createElement('link');
190 el.rel = 'stylesheet';
191 el.href = 'http://fonts.googleapis.com/css?family=' + fonts.join('|') + '&v2';
192 document.querySelector('head').appendChild(el);
193
194};
195
196/**
197 * @private
198 */
199SlideDeck.prototype.buildNextItem_ = function() {
200 var slide = this.slides_[this.curSlide_];
201 var toBuild = slide.querySelector('.to-build');
202 var built = slide.querySelector('.build-current');
203
204 if (built) {
205 built.classList.remove('build-current');
206 if (built.classList.contains('fade')) {
207 built.classList.add('build-fade');
208 }
209 }
210
211 if (!toBuild) {
212 var items = slide.querySelectorAll('.build-fade');
213 for (var j = 0, item; item = items[j]; j++) {
214 item.classList.remove('build-fade');
215 }
216 return false;
217 }
218
219 toBuild.classList.remove('to-build');
220 toBuild.classList.add('build-current');
221
222 /*if (isChromeVoxActive()) {
223 speakAndSyncToNode(toBuild);
224 }*/
225
226 return true;
227};
228
229/**
230 * @param {boolean=} opt_dontPush
231 */
232SlideDeck.prototype.prevSlide = function(opt_dontPush) {
233 if (this.curSlide_ > 0) {
234 this.curSlide_--;
235
236 this.updateSlides_(opt_dontPush);
237 }
238};
239
240/**
241 * @param {boolean=} opt_dontPush
242 */
243SlideDeck.prototype.nextSlide = function(opt_dontPush) {
244
245 if (this.buildNextItem_()) {
246 return;
247 }
248
249 if (this.curSlide_ < this.slides_.length - 1) {
250 this.curSlide_++;
251
252 this.updateSlides_(opt_dontPush);
253 }
254};
255
256/**
257 * @private
258 */
259SlideDeck.prototype.updateSlides_ = function(opt_dontPush) {
260 var dontPush = opt_dontPush || false;
261
262 var curSlide = this.curSlide_;
263 for (var i = 0; i < this.slides_.length; i++) {
264 switch (i) {