reveal.js-appearance 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/LICENSE +1 -1
- package/README.md +140 -52
- package/css/demo.css +106 -4
- package/demo-markdown.html +62 -0
- package/demo.html +312 -92
- package/img/5.jpg +0 -0
- package/markdown.md +156 -0
- package/package.json +5 -3
- package/plugin/appearance/appearance.css +17 -1
- package/plugin/appearance/appearance.esm.js +265 -170
- package/plugin/appearance/appearance.js +479 -384
- package/plugin/appearance/plugin-src.js +229 -39
- package/screenshot.png +0 -0
|
@@ -28,19 +28,62 @@ const Plugin = () => {
|
|
|
28
28
|
head.appendChild(style);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
const isJSON = str => {
|
|
32
|
+
try {
|
|
33
|
+
return (JSON.parse(str) && !!str);
|
|
34
|
+
} catch (e) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const isObj = (test) => {
|
|
40
|
+
while ( Object.prototype.toString.call(test) === '[object Object]')
|
|
41
|
+
if ((test = Object.getPrototypeOf(test)) === null)
|
|
42
|
+
return true
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
|
|
31
46
|
const selectionArray = function (container, selectors) {
|
|
32
47
|
let selections = container.querySelectorAll(selectors);
|
|
33
48
|
let selectionarray = Array.prototype.slice.call(selections);
|
|
34
49
|
return selectionarray;
|
|
35
50
|
};
|
|
36
51
|
|
|
52
|
+
const isStack = function (section) {
|
|
53
|
+
let isStack = false;
|
|
54
|
+
for (let i = 0; i < section.childNodes.length; i++) {
|
|
55
|
+
if (section.childNodes[i].tagName == "SECTION") {
|
|
56
|
+
isStack = true
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return isStack;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
function copyDataAttributes(source, target, not) {
|
|
64
|
+
[...source.attributes].filter( attr => attr.nodeName.indexOf('data') > -1).forEach( attr => {
|
|
65
|
+
if ((not && attr.nodeName !== not) || !not) {
|
|
66
|
+
target.setAttribute(attr.nodeName, attr.nodeValue)
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
37
72
|
const appear = function (deck, options) {
|
|
38
73
|
|
|
39
74
|
let baseclass = 'animate__animated';
|
|
75
|
+
let viewport = (deck.getRevealElement()).tagName == "BODY" ? document : deck.getRevealElement();
|
|
40
76
|
let appearanceSelector = options.compatibility ? `.${options.compatibilitybaseclass}` : `.${baseclass}`;
|
|
41
|
-
let fragmentSelector = ".fragment"
|
|
77
|
+
let fragmentSelector = ".fragment";
|
|
78
|
+
|
|
79
|
+
let speedClasses = ['slower', 'slow', 'fast', 'faster'];
|
|
80
|
+
speedClasses.push(...speedClasses.map(speed => `animate__${speed}`));
|
|
81
|
+
|
|
82
|
+
const generator = document.querySelector('[name=generator]');
|
|
83
|
+
|
|
84
|
+
const sections = selectionArray(viewport, "section");
|
|
85
|
+
const regularSections = sections.filter( section => !isStack(section) && section.dataset.visibility != "hidden");
|
|
42
86
|
|
|
43
|
-
const sections = deck.getRevealElement().querySelectorAll(`.slides section`);
|
|
44
87
|
const fragments = deck.getRevealElement().querySelectorAll(fragmentSelector);
|
|
45
88
|
let animatecss = '[class^="animate__"],[class*=" animate__"]'
|
|
46
89
|
|
|
@@ -48,17 +91,157 @@ const Plugin = () => {
|
|
|
48
91
|
if (options.debug) console.log(text);
|
|
49
92
|
}
|
|
50
93
|
|
|
94
|
+
const assignAutoClass = (section, str, kind) => {
|
|
95
|
+
|
|
96
|
+
let index = [...section.parentElement.children].filter(s => s.tagName=="SECTION").indexOf(section) + 1;
|
|
97
|
+
|
|
98
|
+
let warning = kind == 'global' ? `JSON Parse error, please try to correct the global "autoelements" option.` : `JSON Parse error, please try to correct the "data-autoappear" attribute on section ${index}`;
|
|
99
|
+
|
|
100
|
+
if (typeof str === "string") str = str.replace(/[“”]/g,'"').replace(/[‘’]/g,"'");
|
|
101
|
+
|
|
102
|
+
let strJSON = isJSON(str) ? str : typeof str === "object" ? JSON.stringify(str, null, 2) : str.trim().replace(/'/g, '"').charAt(0) === "{" ? str.trim().replace(/'/g, '"') : `{${str.trim().replace(/'/g, '"')}}`;
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if (!isJSON(strJSON)) {
|
|
106
|
+
console.log(warning);
|
|
107
|
+
} else {
|
|
108
|
+
let elementsToAnimate = JSON.parse(strJSON);
|
|
109
|
+
|
|
110
|
+
for (const [element, assignables] of Object.entries(elementsToAnimate)) {
|
|
111
|
+
|
|
112
|
+
let elementsInSection = section.querySelectorAll(element);
|
|
113
|
+
|
|
114
|
+
elementsInSection.forEach(elementInSection => {
|
|
115
|
+
|
|
116
|
+
if (!elementInSection.classList.contains(baseclass) || elementInSection.dataset["autoappear"]) {
|
|
117
|
+
|
|
118
|
+
elementInSection.dataset["autoappear"] = true;
|
|
119
|
+
|
|
120
|
+
let newClasses = [], newDelay = null, speedClass = false;
|
|
121
|
+
|
|
122
|
+
if (Array.isArray(assignables)) {
|
|
123
|
+
newClasses = assignables[0].split(/[ ,]+/);
|
|
124
|
+
newDelay = assignables[1];
|
|
125
|
+
} else if (typeof assignables == "string"){
|
|
126
|
+
newClasses = assignables.split(/[ ,]+/);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
speedClasses.forEach(speed => {
|
|
130
|
+
if (elementInSection.classList.contains(speed)) {
|
|
131
|
+
speedClass = speed;
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
let classesToRemove = [];
|
|
136
|
+
elementInSection.classList.forEach(currentClass => {
|
|
137
|
+
if (String(currentClass).includes("animate__")) {
|
|
138
|
+
classesToRemove.push(currentClass);
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
classesToRemove.forEach(currentClass => {elementInSection.classList.remove(currentClass)});
|
|
142
|
+
|
|
143
|
+
newClasses.forEach(newClass => {
|
|
144
|
+
if (speedClasses.includes(newClass)) {
|
|
145
|
+
// There is a speed class from JSON to be assigned
|
|
146
|
+
if (speedClass) { speedClass = newClass }
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
newClasses.forEach(newClass => {
|
|
151
|
+
elementInSection.classList.add(newClass);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (speedClass) {
|
|
155
|
+
elementInSection.classList.add(speedClass);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
if (newDelay) {
|
|
162
|
+
elementInSection.dataset.delay = newDelay;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
elementInSection.classList.add(baseclass);
|
|
166
|
+
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
51
175
|
const findAppearancesIn = function (container, includeClass, excludeClass) {
|
|
52
176
|
if (!isStack(container)) {
|
|
53
177
|
let appearances = selectionArray(container, `:scope ${includeClass}`);
|
|
178
|
+
|
|
179
|
+
appearances.forEach(appearance => {
|
|
180
|
+
|
|
181
|
+
let convertListItem = (appearance) => {
|
|
182
|
+
let from = appearance, to = appearance.parentNode;
|
|
183
|
+
if (!to) return
|
|
184
|
+
for (let sibling of to.children) {
|
|
185
|
+
if (sibling !== appearance) { if (sibling.dataset.appearParent) return }
|
|
186
|
+
}
|
|
187
|
+
to.classList = from.classList;
|
|
188
|
+
copyDataAttributes(from, to, "data-appear-parent");
|
|
189
|
+
to.innerHTML = from.innerHTML;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Conversion of list items with Appearance classes to the parent, needs manual attribute
|
|
193
|
+
// Relates to Quarto wrapping list content in a span.
|
|
194
|
+
if (appearance.hasAttribute("data-appear-parent")) {
|
|
195
|
+
convertListItem(appearance);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Automatic conversion of list items which directly contain spans.
|
|
199
|
+
// Relates to Quarto wrapping list content in a span.
|
|
200
|
+
if (options.appearparents) {
|
|
201
|
+
if (appearance.parentNode && appearance.parentNode.tagName) {
|
|
202
|
+
if (appearance.tagName == "SPAN" && appearance.parentNode.tagName == "LI") {
|
|
203
|
+
let spanLength = String(appearance.outerHTML).length;
|
|
204
|
+
let liContentLength = String(appearance.parentNode.innerHTML).length;
|
|
205
|
+
if (spanLength == liContentLength) {
|
|
206
|
+
convertListItem(appearance);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
appearances = selectionArray(container, `:scope ${includeClass}`);
|
|
54
216
|
let excludes = selectionArray(container, `:scope ${excludeClass} ${includeClass}`);
|
|
55
217
|
let delay = 0;
|
|
56
|
-
|
|
218
|
+
|
|
57
219
|
appearances.filter(function (appearance, index) {
|
|
58
|
-
if (
|
|
220
|
+
if ( !(excludes.indexOf(appearance) > -1 ) ) {
|
|
59
221
|
if ((index == 0 && appearance.dataset.delay) || index !=0) {
|
|
60
|
-
|
|
222
|
+
|
|
223
|
+
let elementDelay = options.delay;
|
|
224
|
+
if (appearance.dataset && appearance.dataset.delay) {
|
|
225
|
+
elementDelay = parseInt(appearance.dataset.delay);
|
|
226
|
+
}
|
|
227
|
+
|
|
61
228
|
delay = delay + elementDelay;
|
|
229
|
+
|
|
230
|
+
// Allow fragments to be Appearance items
|
|
231
|
+
if (appearance.classList.contains("fragment")) {
|
|
232
|
+
delay = 0;
|
|
233
|
+
if (appearance.querySelectorAll(`.${baseclass}`)) {
|
|
234
|
+
let firstNestedAppearance = appearance.querySelectorAll(`.${baseclass}`)[0];
|
|
235
|
+
|
|
236
|
+
if (firstNestedAppearance) {
|
|
237
|
+
let elementDelay = options.delay;
|
|
238
|
+
if (firstNestedAppearance.dataset && firstNestedAppearance.dataset.delay) {
|
|
239
|
+
elementDelay = parseInt(firstNestedAppearance.dataset.delay);
|
|
240
|
+
}
|
|
241
|
+
firstNestedAppearance.dataset.delay = elementDelay
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
62
245
|
appearance.style.setProperty('animation-delay', delay + "ms");
|
|
63
246
|
}
|
|
64
247
|
}
|
|
@@ -68,46 +251,46 @@ const Plugin = () => {
|
|
|
68
251
|
|
|
69
252
|
const autoAdd = function () {
|
|
70
253
|
|
|
71
|
-
|
|
254
|
+
regularSections.forEach(section => {
|
|
72
255
|
|
|
73
|
-
|
|
256
|
+
if (section.hasAttribute("data-autoappear")) {
|
|
74
257
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
autoAppearances.forEach(autoAppearance => {
|
|
83
|
-
if (!autoAppearance.classList.contains(baseclass)) {
|
|
84
|
-
autoAppearance.classList.add(baseclass);
|
|
85
|
-
autoAppearance.classList.add(autoanimation);
|
|
258
|
+
let sectDataAppear = section.dataset.autoappear;
|
|
259
|
+
|
|
260
|
+
if (sectDataAppear == "auto" || sectDataAppear == "" || sectDataAppear.length < 1 || sectDataAppear == "true") {
|
|
261
|
+
// This section should get the global autoappear classes on its objects
|
|
262
|
+
if (options.autoelements) {
|
|
263
|
+
if (!options.autoelements) {
|
|
264
|
+
return console.log(`Please add some elements in the option "autoelements"`);
|
|
86
265
|
}
|
|
87
|
-
|
|
266
|
+
assignAutoClass(section, options.autoelements, 'global')
|
|
267
|
+
}
|
|
268
|
+
} else if (sectDataAppear.length > 0) {
|
|
269
|
+
// This section should get the local data-autoappear classes on its objects
|
|
270
|
+
assignAutoClass(section, sectDataAppear, 'local');
|
|
271
|
+
//section.removeAttribute("data-autoappear");
|
|
88
272
|
}
|
|
89
|
-
}
|
|
90
|
-
} else if (options.autoappear) {
|
|
91
|
-
console.log(`Please set an "autoelements" object.`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
273
|
+
} else {
|
|
94
274
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
275
|
+
if (options.autoappear) {
|
|
276
|
+
if (!options.autoelements) {
|
|
277
|
+
return console.log(`Please add some elements in the option "autoelements"`);
|
|
278
|
+
}
|
|
279
|
+
// This section should get the global autoappear classes on its objects
|
|
280
|
+
assignAutoClass(section, options.autoelements, 'global')
|
|
281
|
+
}
|
|
101
282
|
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
}
|
|
105
286
|
|
|
106
287
|
if (options.compatibility) {
|
|
107
288
|
animatecss = '.backInDown, .backInLeft, .backInRight, .backInUp, .bounceIn, .bounceInDown, .bounceInLeft, .bounceInRight, .bounceInUp, .fadeIn, .fadeInDown, .fadeInDownBig, .fadeInLeft, .fadeInLeftBig, .fadeInRight, .fadeInRightBig, .fadeInUp, .fadeInUpBig, .fadeInTopLeft, .fadeInTopRight, .fadeInBottomLeft, .fadeInBottomRight, .flipInX, .flipInY, .lightSpeedInRight, .lightSpeedInLeft, .rotateIn, .rotateInDownLeft, .rotateInDownRight, .rotateInUpLeft, .rotateInUpRight, .jackInTheBox, .rollIn, .zoomIn, .zoomInDown, .zoomInLeft, .zoomInRight, .zoomInUp, .slideInDown, .slideInLeft, .slideInRight, .slideInUp, .skidLeft, .skidLeftBig, .skidRight, .skidRightBig, .shrinkIn, .shrinkInBlur';
|
|
108
289
|
baseclass = options.compatibilitybaseclass
|
|
109
290
|
}
|
|
110
291
|
|
|
292
|
+
|
|
293
|
+
|
|
111
294
|
let allappearances = deck.getRevealElement().querySelectorAll(animatecss);
|
|
112
295
|
|
|
113
296
|
allappearances.forEach(appearance => {
|
|
@@ -156,11 +339,17 @@ const Plugin = () => {
|
|
|
156
339
|
|
|
157
340
|
if (etype == "slidetransitionend") {
|
|
158
341
|
if (options.hideagain) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
342
|
+
if (slides.from) {
|
|
343
|
+
if (slides.from.dataset.appearanceCanStart) {
|
|
344
|
+
delete slides.from.dataset.appearanceCanStart;
|
|
345
|
+
}
|
|
346
|
+
let fromFragments = slides.from.querySelectorAll(`.fragment.visible`);
|
|
347
|
+
if (fromFragments) {
|
|
348
|
+
fromFragments.forEach(fragment => {
|
|
349
|
+
fragment.classList.remove('visible');
|
|
350
|
+
})
|
|
351
|
+
}
|
|
352
|
+
}
|
|
164
353
|
}
|
|
165
354
|
}
|
|
166
355
|
|
|
@@ -204,10 +393,11 @@ const Plugin = () => {
|
|
|
204
393
|
appearevent: 'slidetransitionend',
|
|
205
394
|
autoappear: false,
|
|
206
395
|
autoelements: false,
|
|
396
|
+
appearparents: false,
|
|
207
397
|
csspath: '',
|
|
208
398
|
animatecsspath: {
|
|
209
399
|
link : 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css',
|
|
210
|
-
compat : 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.
|
|
400
|
+
compat : 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.compat.css',
|
|
211
401
|
},
|
|
212
402
|
compatibility: false,
|
|
213
403
|
compatibilitybaseclass: 'animated'
|
package/screenshot.png
CHANGED
|
Binary file
|