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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
/*!
Deck JS - deck.toc
Copyright (c) 2011 Remi BARRAQUAND
Dual licensed under the MIT license and GPL license.
https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
*/
/*
This module provides a support for TOC to the deck.
*/
(function($, deck, undefined) {
var $d = $(document);
var $toc;
/*
Extends defaults/options.
options.classes.toc
This class is added to the deck container when showing the slide
toc.
options.keys.toc
The numeric keycode used to toggle between showing and hiding
the slide toc.
options.selectors.toc
The element matching this selector displays the toc.
options.selectors.tocTitle
The element matching this selector displays the current title
of the slide i.e the current h1.
options.selectors.tocSection
The element matching this selector displays the current section
of the slide i.e the current h2.
options.selectors.tocSubSection
The element matching this selector displays the current
subsection of the slide i.e the current h3.
options.selectors.tocSubSubSection
The element matching this selector displays the current
subsubsection of the slide i.e the current h4.
*/
$.extend(true, $[deck].defaults, {
classes: {
toc: 'deck-toc-frame'
},
keys: {
toc: 84 // t
},
selectors: {
toc: '.deck-toc',
tocTitle: '.deck-toc-h1',
tocSection: '.deck-toc-h2',
tocSubSection: '.deck-toc-h3',
tocSubSubSection: '.deck-toc-h4',
tocStatus: '.deck-toc-status'
}
});
/*
jQuery.deck('showToc')
Shows the slide toc by adding the class specified by the toc class option
to the deck container.
*/
$[deck]('extend', 'showToc', function() {
$[deck]('getContainer').addClass($[deck]('getOptions').classes.toc);
});
/*
jQuery.deck('hideToc')
Hides the slide toc by removing the class specified by the toc class
option from the deck container.
*/
$[deck]('extend', 'hideToc', function() {
$[deck]('getContainer').removeClass($[deck]('getOptions').classes.toc);
});
/*
jQuery.deck('toggleToc')
Toggles between showing and hiding the TOC.
*/
$[deck]('extend', 'toggleToc', function() {
$[deck]('getContainer').hasClass($[deck]('getOptions').classes.toc) ?
$[deck]('hideToc') : $[deck]('showToc');
});
/*
jQuery.deck('Init')
*/
$d.bind('deck.init', function() {
var opts = $[deck]('getOptions');
var container = $[deck]('getContainer');
/* Bind key events */
$d.unbind('keydown.decktoc').bind('keydown.decktoc', function(e) {
if (e.which === opts.keys.toc || $.inArray(e.which, opts.keys.toc) > -1) {
$[deck]('toggleToc');
e.preventDefault();
}
});
/* Hide TOC panel when user click on container */
container.click(function(e){
$[deck]('hideToc');
});
/* Init TOC and append it to the document */
$toc = new TOC();
$($[deck]('getOptions').selectors.toc).append($toc.root);
/* Go through all slides */
$.each($[deck]('getSlides'), function(i, $el) {
var slide = $[deck]('getSlide',i);
//var tocElementFound = false;
/* If there is a toc item, push it in the TOC */
for(var level=1; level<6; level++) {
if( slide.find("h"+level).length > 0) {
var tocTitle = "";
var $tocElement = slide.find("h"+level+":first");
if( $tocElement.attr("title") != undefined && $tocElement.attr("title") != "") {
tocTitle = $tocElement.attr("title");
} else {
tocTitle = $tocElement.text();
}
$toc.push(level, tocTitle, slide);
$toc.tag(slide);
//tocElementFound = true;
}
}
/* Tag the slide with the current TOC level */
$toc.tag(slide);
});
})
/* Update current slide number with each change event */
.bind('deck.change', function(e, from, to) {
var opts = $[deck]('getOptions');
var slideTo = $[deck]('getSlide', to);
var container = $[deck]('getContainer');
if (container.hasClass($[deck]('getOptions').classes.toc)) {
container.scrollTop(slideTo.offset().top);
}
/* update toc status */
if( slideTo.data("toc") ) {
// reset
$(opts.selectors.tocTitle).text("");
$(opts.selectors.tocSection).text("");
$(opts.selectors.tocSubSection).text("");
$(opts.selectors.tocSubSubSection).text("");
if( slideTo.hasClass('hide-toc-status') ) {
$(opts.selectors.tocStatus).hide();
} else {
$(opts.selectors.tocStatus).show();
// update according to the current context
var $context = $toc.context(slideTo.data('toc'))
for(var level=1; level<=$context.length; level++) {
switch(level) {
case 1:
$(opts.selectors.tocTitle).text($context[level-1]);
break;
case 2:
$(opts.selectors.tocSection).text($context[level-1]);
break;
case 3:
$(opts.selectors.tocSubSection).text($context[level-1]);
break;
case 4:
$(opts.selectors.tocSubSubSection).text($context[level-1]);
break;
}
}
}
}
});
/*
Simple TOC manager (must be improved)
*/
var TOC = function() {
this.root = $("<ul/>", {"class":"toc"});
/*
Push new item in the TOC
depth is the level (e.g. 1 for h1, 2 for h2, etc.)
title is the toc-item title
slide is the slide that provides the toc-element
*/
this.push = function(depth,title,slide) {
inc(depth);
/* Create toc element */
var $tocElm = $("<li />", {
id: "toc-"+($c.join('-'))
}).data({ // keep track of the slide in case...
slide: slide,
title: title
}).append($("<a />", { // create an hyperlink
href: "#"+$(slide).attr('id'),
text: title
})).append($("<ul />"));
/* insert it at the right place */
var $target = this.root;
if( depth > 1) {
$target = ($target.find("li#toc-"+($c.slice(0,$c.length-1).join('-')))).children("ul");
}
$tocElm.appendTo($target);
};
/*
Tag the slide with the current TOC level.
slide is the slide to tag
*/
this.tag = function(slide) {
slide.data({
toc: $c.slice(0)
});
}
/*
Get the current TOC context
path is the current path in the TOC
*/
this.context = function(path) {
$context = new Array();
var $target = this.root;
for(var depth=0; depth<path.length; depth++) {
var tocElm = $target.find("li#toc-"+(path.slice(0,depth+1).join('-')))
$context.push(tocElm.data('title'));
$target = (tocElm).children("ul");
}
return $context;
}
/* cursor */
var $c = [-1];
function inc(depth) {
var current_depth = $c.length;
if(depth>current_depth) {
for(i=current_depth;i<depth;i++) {
$c.push(0);
}
} else if( current_depth>depth) {
for(i=depth;i<current_depth;i++) {
$c.pop();
$c[depth-1]++
}
} else {
$c[depth-1]++
}
}
}
})(jQuery, 'deck');
|