Skip to content

Commit 86d5e5d

Browse files
Add sections plugin
- Use data-section to assign steps to sections - Use data-sub-section to assign steps to sub-sections - Optional divs showing the section progress - active-section and hidden-section are classes to mark steps as active and hidden section element.
1 parent c61403d commit 86d5e5d

File tree

2 files changed

+229
-0
lines changed

2 files changed

+229
-0
lines changed

src/plugins/sections/README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
Sections plugin
2+
===============
3+
4+
Sections for impress.js presentations
5+
6+
Usage
7+
-----
8+
9+
Add `data-section="Intro"` to your steps as you can see here:
10+
11+
```html
12+
<div data-section="Section Name" id="title" class="step">
13+
<h1>Title of Slide</h1>
14+
</div>
15+
16+
<div id="agenda" class="agenda" class="step"> <!-- no data-section required -->
17+
18+
</div>
19+
20+
<div data-section="A new section" id="first-slide" class="step">
21+
22+
</div>
23+
```
24+
25+
The section name and the current index of the section will be displayed in your presentation.
26+
Therefore, add a div for displaying the current section and/or progress as you can see it here:
27+
28+
29+
```html
30+
<div class="impress-section-overview">
31+
<div class="impress-section-numbers"></div>
32+
<div class="impress-current-section"></div>
33+
</div>
34+
```
35+
36+
```css
37+
.impress-section-overview {
38+
display: flex;
39+
align-items: flex-end;
40+
justify-content: flex-end;
41+
}
42+
43+
.impress-section-numbers {
44+
display: inline-block;
45+
margin-top: .25em;
46+
padding: .1em .25em;
47+
color: white;
48+
background: #aaa;
49+
}
50+
51+
.impress-current-section {
52+
padding-left: 5px;
53+
}
54+
```
55+
56+
Feel free to change the style of your section overview as you like by editing the CSS file.
57+
58+
Additionally, the plugin will generate an agenda outline for you if you want it to. Therefore, add the a class `agenda`
59+
to any of your divs of the presentation (as shown in the aforementioned HTML snippet).
60+
61+
Furthermore, this plugin adds the class `active-section` to all steps of the action section and `hidden-section` to all
62+
steps that do not belong to this section. You can use this classes, e.g. to hide the steps of another section:
63+
64+
```css
65+
.impress-enabled .hidden-section {
66+
opacity: 0 !important;
67+
}
68+
```
69+
70+
The sections plugin supports also sub section. Therefore, add the attribute `data-sub-section="…"` to your subsection.
71+
The agenda list and also the section overview will show the sub sections.
72+
73+
Author
74+
------
75+
76+
Copyright 2019: Marc Schreiber (@schrieveslaach)

src/plugins/sections/sections.js

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/**
2+
* Sections Plugin
3+
*
4+
* Copyright 2019 Marc Schreiber (@schrieveslaach)
5+
* Released under the MIT license.
6+
*/
7+
/* global document */
8+
9+
(function (document) {
10+
"use strict";
11+
var root, api, gc;
12+
13+
var indexedSteps;
14+
15+
var agenda = document.querySelector("div.agenda ul");
16+
var currentSection = document.querySelector("div.impress-section-overview .impress-current-section");
17+
var sectionNumbers = document.querySelector("div.impress-section-overview .impress-section-numbers");
18+
19+
function indexSteps() {
20+
var slides = Array.prototype.slice.call(root.querySelectorAll(".step"))
21+
.map(function (step) {
22+
return {
23+
id: step.id,
24+
section: step.dataset.section,
25+
subSection: step.dataset.subSection
26+
};
27+
})
28+
.reduce(function (accumulatedSlides, slide, currentIndex, slides) {
29+
if (currentIndex === 0) {
30+
return [slide];
31+
}
32+
33+
let previousSlide = slides[currentIndex - 1];
34+
if (slide.section == null) {
35+
var currentSection = previousSlide.section;
36+
slide.section = currentSection;
37+
}
38+
39+
if (slide.subSection == null && previousSlide.section === slide.section) {
40+
var currentSubSection = previousSlide.subSection;
41+
slide.subSection = currentSubSection;
42+
}
43+
44+
return accumulatedSlides.concat([slide]);
45+
}, []);
46+
47+
return {
48+
sectionIndices: slides.reduce(function (sectionIndices, slide) {
49+
var section = sectionIndices[slide.section];
50+
51+
if (section == null) {
52+
section = {
53+
index: Object.keys(sectionIndices).length + 1,
54+
steps: [slide.id],
55+
subSections: []
56+
};
57+
sectionIndices[slide.section] = section;
58+
} else {
59+
section.steps = section.steps.concat([slide.id]);
60+
}
61+
62+
if (slide.subSection != null && section.subSections.indexOf(slide.subSection) < 0) {
63+
section.subSections = section.subSections.concat([slide.subSection]);
64+
}
65+
66+
return sectionIndices;
67+
}, {}),
68+
69+
slideSectionMapping: slides.reduce(function (slideSectionMapping, slide) {
70+
slideSectionMapping[slide.id] = {
71+
section: slide.section,
72+
subSection: slide.subSection
73+
};
74+
return slideSectionMapping;
75+
}, {})
76+
};
77+
}
78+
79+
document.addEventListener("impress:init", function (event) {
80+
root = event.target;
81+
api = event.detail.api;
82+
gc = api.lib.gc;
83+
84+
indexedSteps = indexSteps();
85+
86+
if (agenda != null) {
87+
Object.keys(indexedSteps.sectionIndices).forEach(function (section) {
88+
var li = document.createElement("li");
89+
agenda.appendChild(li);
90+
li.innerText = section;
91+
92+
var subSections = indexedSteps.sectionIndices[section].subSections;
93+
if (subSections.length > 0) {
94+
var ul = document.createElement("ul");
95+
li.appendChild(ul);
96+
97+
subSections.forEach(function (subSection) {
98+
var li = document.createElement("li");
99+
ul.appendChild(li);
100+
li.innerText = subSection;
101+
});
102+
}
103+
});
104+
}
105+
});
106+
107+
108+
document.addEventListener("impress:stepleave", function (event) {
109+
updateSectionOverview(event.detail.next.id);
110+
});
111+
112+
document.addEventListener("impress:steprefresh", function (event) {
113+
updateSectionOverview(event.target.id);
114+
});
115+
116+
function updateSectionOverview(slideId) {
117+
if (indexedSteps == null) {
118+
return;
119+
}
120+
121+
var section = {
122+
section: indexedSteps.slideSectionMapping[slideId].section,
123+
subSection: indexedSteps.slideSectionMapping[slideId].subSection,
124+
indices: indexedSteps.sectionIndices[indexedSteps.slideSectionMapping[slideId].section]
125+
};
126+
127+
if (currentSection != null) {
128+
if (section.subSection == null) {
129+
currentSection.innerText = section.section;
130+
} else {
131+
currentSection.innerText = section.section + " \u2022 " + section.subSection;
132+
}
133+
}
134+
135+
if (sectionNumbers != null) {
136+
sectionNumbers.innerText = section.indices.index + "/" + Object.keys(indexedSteps.sectionIndices).length;
137+
}
138+
139+
Object.keys(indexedSteps.slideSectionMapping).forEach(function (stepId) {
140+
var step = document.getElementById(stepId);
141+
142+
var subSection = indexedSteps.slideSectionMapping[stepId].subSection;
143+
if (section.indices.steps.indexOf(stepId) >= 0 && section.subSection === subSection) {
144+
step.classList.add("active-section");
145+
step.classList.remove("hidden-section");
146+
} else {
147+
step.classList.remove("active-section");
148+
step.classList.add("hidden-section");
149+
}
150+
});
151+
}
152+
153+
})(document);

0 commit comments

Comments
 (0)