Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gmcninch-tufts
GitHub Repository: gmcninch-tufts/2024-Sp-Math190
Path: blob/main/build-assets/slideous/slideous.js
908 views
1
/* This work is licensed under Creative Commons GNU LGPL License.
2
3
License: http://creativecommons.org/licenses/LGPL/2.1/
4
5
Author: Stefan Goessner/2005-2006
6
Web: http://goessner.net/
7
*/
8
var Slideous = {
9
version: 1.0,
10
// == user customisable ===
11
clickables: { a: true, button: true, img: true, input: true, object: true, textarea: true, select: true, option: true },
12
incrementables: { blockquote: { filter: "self, parent" },
13
dd: { filter: "self, parent" },
14
dt: { filter: "self, parent" },
15
h2: { filter: "self, parent" },
16
h3: { filter: "self, parent" },
17
h4: { filter: "self, parent" },
18
h5: { filter: "self, parent" },
19
h6: { filter: "self, parent" },
20
li: { filter: "self, parent" },
21
p: { filter: "self" },
22
pre: { filter: "self" },
23
img: { filter: "self, parent" },
24
object: { filter: "self, parent" },
25
table: { filter: "self, parent" },
26
td: { filter: "self, parent" },
27
th: { filter: "self, parent" },
28
tr: { filter: "parent, grandparent" }
29
},
30
autoincrementables: { ol: true, ul: true, dl: true },
31
autoincrement: false,
32
statusbar: true,
33
navbuttons: { incfontbutton: function(){Slideous.changefontsize(+Slideous.fontdelta);},
34
decfontbutton: function(){Slideous.changefontsize(-Slideous.fontdelta);},
35
contentbutton: function(){Slideous.gotoslide(Slideous.tocidx(), true, true);},
36
homebutton: function(){Slideous.gotoslide(1, true, true);},
37
prevslidebutton: function(){Slideous.previous(false);},
38
previtembutton: function(){Slideous.previous(true);},
39
nextitembutton: function(){Slideous.next(true);},
40
nextslidebutton: function(){Slideous.next(false);},
41
endbutton: function(){Slideous.gotoslide(Slideous.count,true,true);} },
42
fontsize: 125, // in percent, corresponding to body.font-size in css file
43
fontdelta: 5, // increase/decrease fontsize by this value
44
mousesensitive: true,
45
tocidx: 0,
46
tocitems: { toc: "<li><a href=\"#s{\$slideidx}\">{\$slidetitle}</a></li>",
47
tocbox: "<option value=\"#s{\$slideidx}\" title=\"{\$slidetitle}\">{\$slidetitle}</option>" },
48
keydown: function(evt) {
49
evt = evt || window.event;
50
var key = evt.keyCode || evt.which;
51
if (key && !evt.ctrlKey && !evt.altKey) {
52
switch (key) {
53
case 33: // page up ... previous slide
54
Slideous.previous(false); evt.cancel = !Slideous.showall; break;
55
case 37: // left arrow ... previous item
56
Slideous.previous(true); evt.cancel = !Slideous.showall; break;
57
case 32: // space bar
58
case 39: // right arrow
59
Slideous.next(true); evt.cancel = !Slideous.showall; break;
60
case 13: // carriage return ... next slide
61
case 34: // page down
62
Slideous.next(false); evt.cancel = !Slideous.showall; break;
63
case 35: // end ... last slide (not recognised by opera)
64
Slideous.gotoslide(Slideous.count, true, true); evt.cancel = !Slideous.showall; break;
65
case 36: // home ... first slide (not recognised by opera)
66
Slideous.gotoslide(1, true, true); evt.cancel = !Slideous.showall; break;
67
case 65: // A ... show All
68
case 80: // P ... Print mode
69
Slideous.toggleshowall(!Slideous.showall); evt.cancel = true; break;
70
case 67: // C ... goto contents
71
Slideous.gotoslide(Slideous.tocidx, true, true); evt.cancel = true; break;
72
case 77: // M ... toggle mouse sensitivity
73
Slideous.mousenavigation(Slideous.mousesensitive = !Slideous.mousesensitive); evt.cancel = true; break;
74
case 83: // S ... toggle statusbar
75
Slideous.togglestatusbar(); evt.cancel = true; break;
76
case 61: // + ... increase fontsize
77
case 107:
78
Slideous.changefontsize(+Slideous.fontdelta); evt.cancel = true; break;
79
case 109: // - ... decrease fontsize
80
Slideous.changefontsize(-Slideous.fontdelta); evt.cancel = true; break;
81
default: break;
82
}
83
if (evt.cancel) evt.returnValue = false;
84
}
85
return !evt.cancel;
86
},
87
88
// == program logic ===
89
count: 0, // # of slides ..
90
curidx: 0, // current slide index ..
91
mousedownpos: null, // last mouse down position ..
92
contentselected: false, // indicates content selection ..
93
showall: true,
94
init: function() {
95
Slideous.curidx = 1;
96
Slideous.importproperties();
97
Slideous.registerslides();
98
document.body.innerHTML = Slideous.injectproperties(document.body.innerHTML);
99
Slideous.buildtocs();
100
Slideous.registeranchors();
101
Slideous.toggleshowall(false);
102
Slideous.updatestatus();
103
document.body.style.fontSize = Slideous.fontsize+"%";
104
document.getElementById("s1").style.display = "block";
105
document.onkeydown = Slideous.keydown;
106
Slideous.mousenavigation(Slideous.mousesensitive);
107
Slideous.registerbuttons();
108
if (window.location.hash)
109
Slideous.gotoslide(window.location.hash.substr(2), true, true);
110
},
111
registerslides: function() {
112
var div = document.getElementsByTagName("div");
113
Slideous.count = 0;
114
for (var i in div)
115
if (Slideous.hasclass(div[i], "slide"))
116
div[i].setAttribute("id", "s"+(++Slideous.count));
117
},
118
registeranchors: function() {
119
var a = document.getElementsByTagName("a"),
120
loc = (window.location.hostname+window.location.pathname).replace(/\\/g, "/");
121
for (var i in a) {
122
if (a[i].href && a[i].href.indexOf(loc) >= 0 && a[i].href.lastIndexOf("#") >= 0) {
123
a[i].href = "javascript:Slideous.gotoslide(" + a[i].href.substr(a[i].href.lastIndexOf("#")+2)+",true,true)";
124
}
125
}
126
},
127
registerbuttons: function() {
128
var button;
129
for (var b in Slideous.navbuttons)
130
if (button = document.getElementById(b))
131
button.onclick = Slideous.navbuttons[b];
132
},
133
importproperties: function() { // from html meta section ..
134
var meta = document.getElementsByTagName("meta"), elem;
135
for (var i in meta)
136
if (meta[i].attributes && meta[i].attributes["name"] && meta[i].attributes["name"].value in Slideous)
137
switch (typeof(Slideous[meta[i].attributes["name"].value])) {
138
case "number": Slideous[meta[i].attributes["name"].value] = parseInt(meta[i].attributes["content"].value); break;
139
case "boolean": Slideous[meta[i].attributes["name"].value] = meta[i].attributes["content"].value == "true" ? true : false; break;
140
default: Slideous[meta[i].attributes["name"].value] = meta[i].attributes["content"].value; break;
141
}
142
},
143
injectproperties: function(str) {
144
var meta = document.getElementsByTagName("meta"), elem;
145
for (var i in meta) {
146
if (meta[i].attributes && meta[i].attributes["name"])
147
str = str.replace(new RegExp("{\\$"+meta[i].attributes["name"].value+"}","g"), meta[i].attributes["content"].value);
148
}
149
return str = str.replace(/{\$generator}/g, "Slideous")
150
.replace(/{\$version}/g, Slideous.version)
151
.replace(/{\$title}/g, document.title)
152
.replace(/{\$slidecount}/g, Slideous.count);
153
},
154
buildtocs: function() {
155
var toc = document.getElementById("toc"), list = "",
156
tocbox = document.getElementById("tocbox");
157
if (toc) {
158
for (var i=0; i<Slideous.count; i++)
159
list += Slideous.tocitems.toc.replace(/{\$slideidx}/g, i+1).replace(/{\$slidetitle}/, document.getElementById("s"+(i+1)).getElementsByTagName("h1")[0].innerHTML);
160
toc.innerHTML = list;
161
while (toc && !Slideous.hasclass(toc, "slide")) toc = toc.parentNode;
162
if (toc) Slideous.tocidx = toc.getAttribute("id").substr(1);
163
}
164
if (tocbox) {
165
tocbox.innerHTML = "";
166
for (var i=0; i<Slideous.count; i++)
167
tocbox.options[tocbox.length] = new Option((i+1)+". "+document.getElementById("s"+(i+1)).getElementsByTagName("h1")[0].innerHTML, "#s"+(i+1));
168
tocbox.onchange = function() { Slideous.gotoslide(this.selectedIndex+1, true, true); };
169
}
170
},
171
next: function(deep) {
172
if (!Slideous.showall) {
173
var slide = document.getElementById("s"+Slideous.curidx),
174
item = Slideous.firstitem(slide, Slideous.isitemhidden);
175
if (deep) { // next item
176
if (item)
177
Slideous.displayitem(item, true);
178
else
179
Slideous.gotoslide(Slideous.curidx+1, false, false);
180
}
181
else if (item) // complete slide ..
182
while (item = Slideous.firstitem(slide, Slideous.isitemhidden))
183
Slideous.displayitem(item, true);
184
else // next slide
185
Slideous.gotoslide(Slideous.curidx+1, true, false);
186
Slideous.updatestatus();
187
}
188
},
189
previous: function(deep) {
190
if (!Slideous.showall) {
191
var slide = document.getElementById("s"+Slideous.curidx);
192
if (deep) {
193
var item = Slideous.lastitem(slide, Slideous.isitemvisible);
194
if (item)
195
Slideous.displayitem(item, false);
196
else
197
Slideous.gotoslide(Slideous.curidx-1, true, false);
198
}
199
else
200
Slideous.gotoslide(Slideous.curidx-1, true, false);
201
Slideous.updatestatus();
202
}
203
},
204
gotoslide: function(i, showitems, updatestatus) {
205
if (!Slideous.showall && i > 0 && i <= Slideous.count && i != Slideous.curidx) {
206
document.getElementById("s"+Slideous.curidx).style.display = "none";
207
var slide = document.getElementById("s"+(Slideous.curidx=i)), item;
208
while (item = Slideous.firstitem(slide, showitems ? Slideous.isitemhidden : Slideous.isitemvisible))
209
Slideous.displayitem(item, showitems);
210
slide.style.display = "block";
211
if (updatestatus)
212
Slideous.updatestatus();
213
}
214
},
215
firstitem: function(root, filter) {
216
var found = filter(root);
217
for (var node=root.firstChild; node!=null && !found; node = node.nextSibling)
218
found = Slideous.firstitem(node, filter);
219
return found;
220
},
221
lastitem: function(root, filter) {
222
var found = null;
223
for (var node=root.lastChild; node!=null && !found; node = node.previousSibling)
224
found = Slideous.lastitem(node, filter);
225
return found || filter(root);
226
},
227
isitem: function(node, visible) {
228
var nodename;
229
return node && node.nodeType == 1 // elements only ..
230
&& (nodename=node.nodeName.toLowerCase()) in Slideous.incrementables
231
&& ( Slideous.incrementables[nodename].filter.match("\\bself\\b") && (Slideous.hasclass(node, "incremental") || (Slideous.autoincrement && nodename in Slideous.autoincrementables))
232
|| Slideous.incrementables[nodename].filter.match("\\bparent\\b") && (Slideous.hasclass(node.parentNode, "incremental") || (Slideous.autoincrement && node.parentNode.nodeName.toLowerCase() in Slideous.autoincrementables))
233
|| Slideous.incrementables[nodename].filter.match("\\bgrandparent\\b") && (Slideous.hasclass(node.parentNode.parentNode, "incremental") || (Slideous.autoincrement && node.parentNode.parentNode.nodeName.toLowerCase() in Slideous.autoincrementables))
234
)
235
&& (visible ? (node.style.visibility != "hidden")
236
: (node.style.visibility == "hidden"))
237
? node : null;
238
},
239
isitemvisible: function(node) { return Slideous.isitem(node, true); },
240
isitemhidden: function(node) { return Slideous.isitem(node, false); },
241
displayitem: function(item, show) {
242
if (item) item.style.visibility = (show ? "visible" : "hidden");
243
},
244
updatestatus: function() {
245
if (Slideous.statusbar) {
246
var eos = document.getElementById("eos"),
247
idx = document.getElementById("slideidx"),
248
tocbox = document.getElementById("tocbox");
249
if (eos)
250
eos.style.visibility = Slideous.firstitem(document.getElementById("s"+Slideous.curidx), Slideous.isitemhidden) != null
251
? "visible" : "hidden";
252
if (idx)
253
idx.innerHTML = Slideous.curidx;
254
if (tocbox)
255
tocbox.selectedIndex = Slideous.curidx-1;
256
}
257
},
258
changefontsize: function(delta) {
259
document.body.style.fontSize = (Slideous.fontsize+=delta)+"%";
260
},
261
togglestatusbar: function() {
262
document.getElementById("statusbar").style.display = (Slideous.statusbar = !Slideous.statusbar) ? "block" : "none";
263
},
264
toggleshowall: function(showall) {
265
var slide, item;
266
for (var i=0; i<Slideous.count; i++) {
267
slide = document.getElementById("s"+(i+1));
268
slide.style.display = showall ? "block" : "none";
269
while (item = Slideous.firstitem(slide, showall ? Slideous.isitemhidden : Slideous.isitemvisible))
270
Slideous.displayitem(item, showall);
271
var divs = slide.getElementsByTagName("div");
272
for (var j in divs)
273
if (Slideous.hasclass(divs[j], "handout"))
274
divs[j].style.display = showall ? "block" : "none";
275
}
276
if (!showall)
277
document.getElementById("s"+Slideous.curidx).style.display = "block";
278
if (Slideous.statusbar)
279
document.getElementById("statusbar").style.display = showall ? "none" : "block";
280
Slideous.showall = showall;
281
},
282
hasclass: function(elem, classname) {
283
var classattr = null;
284
return (classattr=(elem.attributes && elem.attributes["class"]))
285
&& classattr.nodeValue.match("\\b"+classname+"\\b");
286
},
287
selectedcontent: function() {
288
return window.getSelection ? window.getSelection().toString()
289
: document.getSelection ? document.getSelection()
290
: document.selection ? document.selection.createRange().text
291
: "";
292
},
293
mousenavigation: function(on) {
294
if (on) {
295
document.onmousedown = Slideous.mousedown;
296
document.onmouseup = Slideous.mouseup;
297
}
298
else
299
document.onmousedown = document.onmouseup = null;
300
},
301
mousepos: function(e) {
302
return e.pageX ? {x: e.pageX, y: e.pageY}
303
: {x: e.x+document.body.scrollLeft, y: e.y+document.body.scrollTop};
304
},
305
mousedown: function(evt) {
306
evt = evt||window.event;
307
Slideous.mousedownpos = Slideous.mousepos(evt);
308
Slideous.contentselected = !!Slideous.selectedcontent() || ((evt.target || evt.srcElement).nodeName.toLowerCase() in Slideous.clickables);
309
return true;
310
},
311
mouseup: function(evt) {
312
evt = evt||window.event;
313
var pos = Slideous.mousepos(evt);
314
if (pos.x == Slideous.mousedownpos.x && pos.y == Slideous.mousedownpos.y && !Slideous.contentselected) {
315
Slideous.next(true);
316
return evt.returnValue = !(evt.cancel = true);
317
}
318
return false;
319
}
320
};
321
window.onload = Slideous.init;
322
323