forked from DeepSpec/sf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslides.js
137 lines (122 loc) · 3.97 KB
/
slides.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* Presentation mode for SF HTML
*
* This file implements simple slide functionality for the SF HTML
* files. When loaded in a page, it will tag some of the page elements
* as slide boundaries, giving each an id of the form
* "#slide-XX". Pressing left or right should trigger "slide mode",
* focusing the screen on the current slide, and then navigate between
* slides. Pressing escape brings the page back to normal. */
/* Which DOM elements to mark as slide boundaries */
var slideSelector = 'h1.libtitle, h1.section, h2.section, h3.section, .quiz';
/* Whether or not we are in slide mode */
var slideMode = false;
/* Keyboard navigation */
var KEYS = {
next: 39, // Right arrow
prev: 37, // Left arrow
exit: 27 // Escape
};
/* Navigates between slides, using the current location hash to find
* the next slide to go to */
function slideNavigate(direction) {
function slideNumber(s) {
if (!s) return null;
var match = s.match(/slide-(.*)/);
if (match && match.length != 0) {
return parseInt(match[1]);
}
return null;
}
var curSlide = slideNumber(location.hash);
var lastSlide = slideNumber($('.slide').last().attr('id'));
var nextSlide;
/* We change the id of each slide element when the page loads, and
* then switch between slides based on the current hash. This is
* not entirely optimal, and can probably be made better.
* http://www.appelsiini.net/projects/viewport seems to be a nice choice.
*/
if (direction == 'left') {
if (curSlide != null) {
if (curSlide > 0) {
nextSlide = curSlide - 1;
} else {
nextSlide = lastSlide;
}
} else {
nextSlide = 0;
}
} else if (direction == 'right') {
if (curSlide != null && curSlide < lastSlide) {
nextSlide = curSlide + 1;
} else {
nextSlide = 0;
}
}
location.hash = '#slide-' + nextSlide;
return false;
};
/* Force the browser to scroll back to the hash location */
function refreshHash() {
var t = location.hash;
location.hash = '';
location.hash = t;
}
/* Activate slide mode. Inserts the right amount of spacing between
* slide boundaries, ensuring that only one slide appears on the
* screen at a time */
function slideActivate() {
$('.slide').each(function (i, elt) {
if (i > 0) $(elt).css('margin-top', $(window).height());
$(elt).css('height', '20px');
});
$('#main').css('padding-bottom', $(window).height());
slideMode = true;
if (location.hash) {
refreshHash();
} else {
location.hash = '#slide-0';
}
}
/* Deactivate slide mode. Removes the extra spacing between slides */
function slideDeactivate() {
$('.slide').each(function (i, elt) {
$(elt).css('margin-top', 0);
$(elt).css('height', 0);
});
$('#main').css('padding-bottom', 0);
refreshHash();
slideMode = false;
}
/* Set up appropriate input handlers */
$(document).keydown(function (event) {
if (slideMode) {
if (event.keyCode == KEYS.prev) {
slideNavigate('left');
event.preventDefault();
} else if (event.keyCode == KEYS.next) {
slideNavigate('right');
event.preventDefault();
} else if (event.keyCode == KEYS.exit) {
slideDeactivate();
event.preventDefault();
} else return true;
} else {
if (event.keyCode == KEYS.prev || event.keyCode == KEYS.next) {
slideActivate();
event.preventDefault();
return false;
} else {
return true;
}
}
});
/* Find slide boundaries and tag them */
$(document).ready(function () {
$(slideSelector).each(function (i, elt) {
var mark = '<div class="slide" id="slide-' + i + '" />';
$(mark).insertBefore($(elt));
});
if (location.hash) {
slideActivate();
}
});