summaryrefslogtreecommitdiff
path: root/slides/final/js/slide-deck.js
diff options
context:
space:
mode:
Diffstat (limited to 'slides/final/js/slide-deck.js')
-rw-r--r--slides/final/js/slide-deck.js838
1 files changed, 838 insertions, 0 deletions
diff --git a/slides/final/js/slide-deck.js b/slides/final/js/slide-deck.js
new file mode 100644
index 0000000..5cdb9c4
--- /dev/null
+++ b/slides/final/js/slide-deck.js
@@ -0,0 +1,838 @@
1/**
2 * @authors Luke Mahe
3 * @authors Eric Bidelman
4 * @fileoverview TODO
5 */
6document.cancelFullScreen = document.webkitCancelFullScreen
7 || document.mozCancelFullScreen;
8
9/**
10 * @constructor
11 */
12function SlideDeck(el) {
13 this.curSlide_ = 0;
14 this.prevSlide_ = 0;
15 this.config_ = null;
16 this.container = el || document.querySelector('slides');
17 this.slides = [];
18 this.controller = null;
19
20 this.getCurrentSlideFromHash_();
21
22 // Call this explicitly. Modernizr.load won't be done until after DOM load.
23 this.onDomLoaded_.bind(this)();
24}
25
26/**
27 * @const
28 * @private
29 */
30SlideDeck.prototype.SLIDE_CLASSES_ = [ 'far-past', 'past', 'current', 'next',
31 'far-next' ];
32
33/**
34 * @const
35 * @private
36 */
37SlideDeck.prototype.CSS_DIR_ = 'theme/css/';
38
39/**
40 * @private
41 */
42SlideDeck.prototype.getCurrentSlideFromHash_ = function() {
43 var slideNo = parseInt(document.location.hash.substr(1));
44
45 if (slideNo) {
46 this.curSlide_ = slideNo - 1;
47 } else {
48 this.curSlide_ = 0;
49 }
50};
51
52/**
53 * @param {number}
54 * slideNo
55 */
56SlideDeck.prototype.loadSlide = function(slideNo) {
57 if (slideNo) {
58 this.curSlide_ = slideNo - 1;
59 this.updateSlides_();
60 }
61};
62
63/**
64 * @private
65 */
66SlideDeck.prototype.onDomLoaded_ = function(e) {
67 document.body.classList.add('loaded'); // Add loaded class for templates to
68 // use.
69
70 this.slides = this.container
71 .querySelectorAll('slide:not([hidden]):not(.hidden):not(.backdrop)');
72
73 // If we're on a smartphone, apply special sauce.
74 if (Modernizr.mq('only screen and (max-device-width: 480px)')) {
75 // var style = document.createElement('link');
76 // style.rel = 'stylesheet';
77 // style.type = 'text/css';
78 // style.href = this.CSS_DIR_ + 'phone.css';
79 // document.querySelector('head').appendChild(style);
80
81 // No need for widescreen layout on a phone.
82 this.container.classList.remove('layout-widescreen');
83 }
84
85 this.loadConfig_(SLIDE_CONFIG);
86 this.addEventListeners_();
87 this.updateSlides_();
88
89 // Add slide numbers and total slide count metadata to each slide.
90 var that = this;
91 for (var i = 0, slide; slide = this.slides[i]; ++i) {
92 slide.dataset.slideNum = i + 1;
93 slide.dataset.totalSlides = this.slides.length;
94
95 slide.addEventListener('click', function(e) {
96 if (document.body.classList.contains('overview')) {
97 that.loadSlide(this.dataset.slideNum);
98 e.preventDefault();
99 window.setTimeout(function() {
100 that.toggleOverview();
101 }, 500);
102 }
103 }, false);
104 }
105
106 // Note: this needs to come after addEventListeners_(), which adds a
107 // 'keydown' listener that this controller relies on.
108
109 // Modernizr.touch isn't a sufficient check for devices that support both
110 // touch and mouse. Create the controller in all cases.
111 // // Also, no need to set this up if we're on mobile.
112 // if (!Modernizr.touch) {
113 this.controller = new SlideController(this);
114 // if (this.controller.isPresenter) {
115 // document.body.classList.add('popup');
116 // }
117 // }
118};
119
120/**
121 * @private
122 */
123SlideDeck.prototype.addEventListeners_ = function() {
124 document.addEventListener('keydown', this.onBodyKeyDown_.bind(this), false);
125 window.addEventListener('popstate', this.onPopState_.bind(this), false);
126
127 // var transEndEventNames = {
128 // 'WebkitTransition': 'webkitTransitionEnd',
129 // 'MozTransition': 'transitionend',
130 // 'OTransition': 'oTransitionEnd',
131 // 'msTransition': 'MSTransitionEnd',
132 // 'transition': 'transitionend'
133 // };
134 //
135 // // Find the correct transitionEnd vendor prefix.
136 // window.transEndEventName = transEndEventNames[
137 // Modernizr.prefixed('transition')];
138 //
139 // // When slides are done transitioning, kickoff loading iframes.
140 // // Note: we're only looking at a single transition (on the slide). This
141 // // doesn't include autobuilds the slides may have. Also, if the slide
142 // // transitions on multiple properties (e.g. not just 'all'), this doesn't
143 // // handle that case.
144 // this.container.addEventListener(transEndEventName, function(e) {
145 // this.enableSlideFrames_(this.curSlide_);
146 // }.bind(this), false);
147
148 // document.addEventListener('slideenter', function(e) {
149 // var slide = e.target;
150 // window.setTimeout(function() {
151 // this.enableSlideFrames_(e.slideNumber);
152 // this.enableSlideFrames_(e.slideNumber + 1);
153 // }.bind(this), 300);
154 // }.bind(this), false);
155};
156
157/**
158 * @private
159 * @param {Event}
160 * e The pop event.
161 */
162SlideDeck.prototype.onPopState_ = function(e) {
163 if (e.state != null) {
164 this.curSlide_ = e.state;
165 this.updateSlides_(true);
166 }
167};
168
169/**
170 * @param {Event}
171 * e
172 */
173SlideDeck.prototype.onBodyKeyDown_ = function(e) {
174 if (/^(input|textarea)$/i.test(e.target.nodeName)
175 || e.target.isContentEditable) {
176 return;
177 }
178
179 // Forward keydowns to the main slides if we're the popup.
180 if (this.controller && this.controller.isController) {
181 this.controller.sendMsg({
182 keyCode : e.keyCode
183 });
184 }
185
186 switch (e.keyCode) {
187 case 13: // Enter
188 if (document.body.classList.contains('overview')) {
189 this.toggleOverview();
190 }
191 break;
192
193 case 39: // right arrow
194 case 32: // space
195 case 34: // PgDn
196 this.nextSlide();
197 e.preventDefault();
198 break;
199
200 case 37: // left arrow
201 case 8: // Backspace
202 case 33: // PgUp
203 this.prevSlide();
204 e.preventDefault();
205 break;
206
207 case 40: // down arrow
208 this.nextSlide();
209 e.preventDefault();
210 break;
211
212 case 38: // up arrow
213 this.prevSlide();
214 e.preventDefault();
215 break;
216
217 case 72: // H: Toggle code highlighting
218 document.body.classList.toggle('highlight-code');
219 break;
220
221 case 79: // O: Toggle overview
222 this.toggleOverview();
223 break;
224
225 case 80: // P
226 // if (this.controller && this.controller.isPresenter) {
227 document.body.classList.toggle('with-notes');
228 // } else if (this.controller && !this.controller.popup) {
229 // document.body.classList.toggle('with-notes');
230 // }
231 break;
232
233 case 82: // R
234 // TODO: implement refresh on main slides when popup is refreshed.
235 break;
236
237 case 27: // ESC: Hide notes and highlighting
238 document.body.classList.remove('with-notes');
239 document.body.classList.remove('highlight-code');