pagewave 1.0.0 → 1.0.1
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/package.json +3 -3
- package/transition.js +69 -22
- package/guide.txt +0 -56
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pagewave",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "NPM Package for implementing page transitions in both SSR and CSR apps",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "NPM Package for implementing page transitions in both SSR and CSR apps. Utilize both custom and preset animations. Choose between transitions, keyframe animations, and overlays.",
|
|
5
5
|
"main": "transition.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -17,6 +17,6 @@
|
|
|
17
17
|
"license": "ISC",
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
20
|
-
"url": "https://github.com/
|
|
20
|
+
"url": "https://github.com/danielpagano202/pagewave.git"
|
|
21
21
|
}
|
|
22
22
|
}
|
package/transition.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//Default Options
|
|
1
2
|
let defaultOptions = {
|
|
2
3
|
mainContentIdName: "main-content",
|
|
3
4
|
overlayClass: "a-overlay",
|
|
@@ -13,7 +14,10 @@ let defaultOptions = {
|
|
|
13
14
|
animateIgnoredLinks: false,
|
|
14
15
|
animateSelfLink: true,
|
|
15
16
|
loadEvent: "DOMContentLoaded",
|
|
17
|
+
usePresets: true,
|
|
18
|
+
cleanUpDivs: false,
|
|
16
19
|
}
|
|
20
|
+
//Options object that will contain the actual options used by the program
|
|
17
21
|
let finalOptions = {
|
|
18
22
|
mainContentIdName: "main-content",
|
|
19
23
|
overlayClass: "a-overlay",
|
|
@@ -29,22 +33,28 @@ let finalOptions = {
|
|
|
29
33
|
animateIgnoredLinks: false,
|
|
30
34
|
animateSelfLink: true,
|
|
31
35
|
loadEvent: "DOMContentLoaded",
|
|
36
|
+
usePresets: true,
|
|
37
|
+
cleanUpDivs: false,
|
|
32
38
|
}
|
|
33
39
|
|
|
40
|
+
//Sets Up Page Transition Capability. Not necessary if you don't need options or presets
|
|
34
41
|
function SetUp(options = {}) {
|
|
35
42
|
//Merge default options with user options
|
|
36
43
|
finalOptions = { ...defaultOptions, ...options };
|
|
37
|
-
//Import css files into
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
//Import css files into HTML document automatically
|
|
45
|
+
if(finalOptions.usePresets){
|
|
46
|
+
let cssFiles = ["OverlayPreset.css", "KeyFramePreset.css"];
|
|
47
|
+
for (let i = 0; i < cssFiles.length; i++) {
|
|
48
|
+
let link = document.createElement('link');
|
|
49
|
+
link.rel = 'stylesheet';
|
|
50
|
+
link.type = 'text/css';
|
|
51
|
+
link.href = cssFiles[i];
|
|
52
|
+
document.getElementsByTagName('HEAD')[0].appendChild(link);
|
|
53
|
+
}
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
56
|
exports.SetUp = SetUp;
|
|
57
|
+
//Overlay Preset Types to Choose From
|
|
48
58
|
const overlayType = Object.freeze({
|
|
49
59
|
slide: Symbol("slide"),
|
|
50
60
|
inverseSlide: Symbol("inverseSlide"),
|
|
@@ -54,12 +64,14 @@ const overlayType = Object.freeze({
|
|
|
54
64
|
bubble: Symbol("bubble"),
|
|
55
65
|
});
|
|
56
66
|
exports.overlayType = overlayType;
|
|
67
|
+
//Keyframe Preset Types to Choose From
|
|
57
68
|
const keyframeType = Object.freeze({
|
|
58
69
|
fade: Symbol("fade"),
|
|
59
70
|
fadeaway: Symbol("fadeaway"),
|
|
60
71
|
});
|
|
61
72
|
exports.keyframeType = keyframeType;
|
|
62
73
|
|
|
74
|
+
//Function to apply animation to element and keep its properties and remove the animation
|
|
63
75
|
function ApplyAnimation(element, animationName, duration, timing, direction) {
|
|
64
76
|
element.style.animation = `${animationName} ${duration}ms ${timing} both ${direction}`;
|
|
65
77
|
if (direction == "reverse") {
|
|
@@ -86,6 +98,7 @@ function ApplyAnimation(element, animationName, duration, timing, direction) {
|
|
|
86
98
|
element.addEventListener("animationend", handleAnimation,);
|
|
87
99
|
}
|
|
88
100
|
}
|
|
101
|
+
//Dispatch an event for the hooks
|
|
89
102
|
function CallHook(hookName, details) {
|
|
90
103
|
const event = new CustomEvent(hookName, {
|
|
91
104
|
detail: details
|
|
@@ -104,6 +117,7 @@ class KeyFramePreset {
|
|
|
104
117
|
fade: "fade",
|
|
105
118
|
fadeaway: "fadeaway"
|
|
106
119
|
};
|
|
120
|
+
//Uses keyframeType to run Keyframe Custom
|
|
107
121
|
if (animationMap[this.kfType.description]) {
|
|
108
122
|
AnimatePageTransition(new KeyFrameCustom(animationMap[this.kfType.description], this.duration, this.timing), direction);
|
|
109
123
|
}
|
|
@@ -117,6 +131,7 @@ class KeyFrameCustom {
|
|
|
117
131
|
this.timing = timing;
|
|
118
132
|
}
|
|
119
133
|
handle(direction, mainElement) {
|
|
134
|
+
//Reveals element and applys the animation
|
|
120
135
|
mainElement.hidden = false;
|
|
121
136
|
ApplyAnimation(mainElement, this.animationName, this.duration, this.timing, direction)
|
|
122
137
|
}
|
|
@@ -131,6 +146,7 @@ class StyleTransition {
|
|
|
131
146
|
this.timing = timing;
|
|
132
147
|
}
|
|
133
148
|
handle(direction, mainElement) {
|
|
149
|
+
//Applys the transition in the right direction
|
|
134
150
|
if (direction == "normal") {
|
|
135
151
|
mainElement.style[this.styleString] = this.startValue;
|
|
136
152
|
mainElement.style.transition = this.styleString + " " + this.duration.toString() + "ms " + this.timing;
|
|
@@ -138,6 +154,7 @@ class StyleTransition {
|
|
|
138
154
|
} else if (direction == "reverse") {
|
|
139
155
|
mainElement.style[this.styleString] = this.endValue;
|
|
140
156
|
mainElement.style.transition = this.styleString + " " + this.duration.toString() + "ms " + this.timing;
|
|
157
|
+
//Timeout is needed for some reason. Need to test further but it works
|
|
141
158
|
setTimeout(
|
|
142
159
|
() => {
|
|
143
160
|
mainElement.style[this.styleString] = this.startValue;
|
|
@@ -158,9 +175,11 @@ class MultiElementAnimation {
|
|
|
158
175
|
handle(direction, mainElement) {
|
|
159
176
|
mainElement.hidden = false;
|
|
160
177
|
let timing = this.timing;
|
|
178
|
+
//Goes through every animation selector, finds all of those elements, and applies the proper animation to them
|
|
161
179
|
for (const [selector, animationName] of Object.entries(this.animateableObjects)) {
|
|
162
180
|
document.querySelectorAll(selector).forEach(element => ApplyAnimation(element, animationName, this.duration, timing, direction));
|
|
163
181
|
}
|
|
182
|
+
//Animates main element if animation is given
|
|
164
183
|
if (this.mainElementAnimation != "") {
|
|
165
184
|
ApplyAnimation(mainElement, this.mainElementAnimation, this.duration, timing, direction);
|
|
166
185
|
}
|
|
@@ -175,6 +194,7 @@ class OverlayPreset {
|
|
|
175
194
|
this.timing = timing;
|
|
176
195
|
}
|
|
177
196
|
handle(direction) {
|
|
197
|
+
//Finds the proper preset and runs OverlayCustom appropriately
|
|
178
198
|
const overlayMap = {
|
|
179
199
|
slide: { firstOverlayElement: "slide" },
|
|
180
200
|
inverseSlide: { firstOverlayElement: "inverseSlide" },
|
|
@@ -201,21 +221,26 @@ class OverlayCustom {
|
|
|
201
221
|
var r = document.querySelector(':root');
|
|
202
222
|
r.style.setProperty('--div-color', this.color);
|
|
203
223
|
let timing = this.timing;
|
|
204
|
-
|
|
224
|
+
//Removes divs when animation is finished
|
|
205
225
|
function RemoveDiv(event) {
|
|
206
226
|
if (event.target.animateName == event.animationName) {
|
|
207
227
|
event.target.removeEventListener("animationend", RemoveDiv);
|
|
208
228
|
event.target.remove();
|
|
209
229
|
}
|
|
210
|
-
}
|
|
230
|
+
}
|
|
231
|
+
//Loops through divs, creating them, adding the provided class, and giving them an animation
|
|
211
232
|
for (const [className, animationName] of Object.entries(this.divAnimationObject)) {
|
|
212
233
|
let divElement = document.createElement("div");
|
|
213
234
|
divElement.className = className;
|
|
214
235
|
divElement.style.animation = `${animationName} ${this.duration.toString()}ms ${timing} both ${direction}`;
|
|
215
236
|
mainElement.appendChild(divElement);
|
|
216
|
-
//
|
|
217
|
-
|
|
237
|
+
//Removes divs at end of animation
|
|
238
|
+
if(finalOptions.cleanUpDivs){
|
|
239
|
+
divElement.animateName = animationName;
|
|
240
|
+
divElement.addEventListener("animationend", RemoveDiv);
|
|
241
|
+
}
|
|
218
242
|
}
|
|
243
|
+
//Animates main element if animation is given
|
|
219
244
|
if (this.mainElementAnimation != "") {
|
|
220
245
|
mainElement.style.animation = `${this.mainElementAnimation} ${this.duration.toString()}ms ${timing} both ${direction}`;
|
|
221
246
|
}
|
|
@@ -232,7 +257,7 @@ function AddFileToCache(file) {
|
|
|
232
257
|
}
|
|
233
258
|
}
|
|
234
259
|
}*/
|
|
235
|
-
|
|
260
|
+
//Adds service worker to cache presets and this script. Returns a boolean true if it is already active or useServiceWorker was overrided; false otherwise
|
|
236
261
|
function AddServiceWorker() {
|
|
237
262
|
if (!finalOptions.useServiceWorker) {
|
|
238
263
|
return true;
|
|
@@ -248,7 +273,7 @@ function AddServiceWorker() {
|
|
|
248
273
|
}
|
|
249
274
|
return isServiceWorker;
|
|
250
275
|
}
|
|
251
|
-
|
|
276
|
+
//Checks if navigation is from same site. Returns false if referrer and current host are different of refferer is empty
|
|
252
277
|
function isNavigationFromSameSite() {
|
|
253
278
|
const referrer = document.referrer;
|
|
254
279
|
if (referrer == "") {
|
|
@@ -259,7 +284,7 @@ function isNavigationFromSameSite() {
|
|
|
259
284
|
|
|
260
285
|
return referrerHost === currentHost;
|
|
261
286
|
}
|
|
262
|
-
|
|
287
|
+
//Returns true if animation is overlay type, false if animation type
|
|
263
288
|
function IsOverlay(transitionStyle) {
|
|
264
289
|
if (transitionStyle instanceof OverlayPreset || transitionStyle instanceof OverlayCustom) {
|
|
265
290
|
return true;
|
|
@@ -268,6 +293,7 @@ function IsOverlay(transitionStyle) {
|
|
|
268
293
|
}
|
|
269
294
|
}
|
|
270
295
|
exports.IsOverlay = IsOverlay;
|
|
296
|
+
//Checks if element exists. If it does, it runs functionToExecute. Otherwise, waits until element exists to run the function
|
|
271
297
|
function WaitForElementLoad(selector, functionToExecute) {
|
|
272
298
|
if(document.querySelector(selector) != null){
|
|
273
299
|
functionToExecute(document.querySelector(selector));
|
|
@@ -287,20 +313,25 @@ function WaitForElementLoad(selector, functionToExecute) {
|
|
|
287
313
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
288
314
|
}
|
|
289
315
|
exports.WaitForElementLoad = WaitForElementLoad;
|
|
316
|
+
//Shorthand for SendPoint and EndPoint
|
|
290
317
|
function ListenForChange(aStyle, aOverlay = aStyle, aAnimation = aStyle, leaveFunction = (link) => {window.location = link;}) {
|
|
291
318
|
EndPoint(aStyle, aOverlay, aAnimation, leaveFunction);
|
|
292
319
|
SendPoint(aStyle, aOverlay, aAnimation);
|
|
293
320
|
}
|
|
294
321
|
exports.ListenForChange = ListenForChange;
|
|
322
|
+
//Listens for clicks and plays animation and then redirects
|
|
295
323
|
function SendPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle, leaveFunction = (link) => {window.location = link;}) {
|
|
324
|
+
//True if service worker is active or ignored with useServiceWorker=false, false otherwise
|
|
296
325
|
let allowAnimate = AddServiceWorker();
|
|
297
326
|
|
|
298
327
|
function HandleClickAnimation(e) {
|
|
299
|
-
//
|
|
300
|
-
if (e.target.tagName
|
|
328
|
+
//Checks to see if target is a link, it is not a link to ignore, not a self link + animateSelfLink=false
|
|
329
|
+
if (e.target.tagName == "A" && !(e.target.classList.contains(finalOptions.classToIgnoreLink)) && !(e.target.href == window.location.href && !finalOptions.animateSelfLink)) {
|
|
330
|
+
//Prevents link from redirecting
|
|
301
331
|
e.preventDefault();
|
|
302
332
|
let duration = aStyle.duration;
|
|
303
333
|
CallHook("animateSSP", { style: aStyle, overlayStyle: aOverlay, animationStyle: aAnimation, clickEvent: e });
|
|
334
|
+
//Plays the right animation depending on link type and sets proper duration
|
|
304
335
|
if (e.target.classList.contains(finalOptions.overlayClass)) {
|
|
305
336
|
AnimatePageTransition(aOverlay, "normal");
|
|
306
337
|
duration = aOverlay.duration;
|
|
@@ -311,6 +342,7 @@ function SendPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle, leaveFunction
|
|
|
311
342
|
AnimatePageTransition(aStyle, "normal");
|
|
312
343
|
duration = aStyle.duration;
|
|
313
344
|
}
|
|
345
|
+
//Calls the leave function when duration timer finishes
|
|
314
346
|
setTimeout(
|
|
315
347
|
() => {
|
|
316
348
|
CallHook("animateESP", { style: aStyle, overlayStyle: aOverlay, animationStyle: aAnimation, clickEvent: e });
|
|
@@ -320,6 +352,7 @@ function SendPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle, leaveFunction
|
|
|
320
352
|
}
|
|
321
353
|
}, parseInt(duration)
|
|
322
354
|
);
|
|
355
|
+
//We set the storage to ignore so we don't play an animation when we go to another page.
|
|
323
356
|
} else if (e.target.classList.contains(finalOptions.classToIgnoreLink) || (e.target.href == window.location.href && !finalOptions.animateSelfLink)) {
|
|
324
357
|
sessionStorage.setItem("animationType", "ignore");
|
|
325
358
|
}
|
|
@@ -329,9 +362,11 @@ function SendPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle, leaveFunction
|
|
|
329
362
|
function AddListeners() {
|
|
330
363
|
window.addEventListener("click", HandleClickAnimation);
|
|
331
364
|
}
|
|
365
|
+
//If service worker active, can immediately listen
|
|
332
366
|
if (allowAnimate) {
|
|
333
367
|
AddListeners();
|
|
334
368
|
}
|
|
369
|
+
//Else, wait until the loadEvent provided is triggered
|
|
335
370
|
else {
|
|
336
371
|
window.addEventListener(finalOptions.loadEvent, () => {
|
|
337
372
|
AddListeners();
|
|
@@ -339,7 +374,9 @@ function SendPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle, leaveFunction
|
|
|
339
374
|
}
|
|
340
375
|
}
|
|
341
376
|
exports.SendPoint = SendPoint;
|
|
377
|
+
//Waits for the document to load and plays the reverse animation
|
|
342
378
|
function EndPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle) {
|
|
379
|
+
//Checks to see what kind of receiving animation to play
|
|
343
380
|
if (aOverlay != aStyle || aAnimation != aStyle) {
|
|
344
381
|
if (sessionStorage.getItem("animationType") === "true") {
|
|
345
382
|
aStyle = aOverlay;
|
|
@@ -373,9 +410,9 @@ function EndPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle) {
|
|
|
373
410
|
}
|
|
374
411
|
}
|
|
375
412
|
}
|
|
376
|
-
|
|
413
|
+
//True if service worker is active or ignored with useServiceWorker=false, false otherwise
|
|
377
414
|
let allowAnimate = AddServiceWorker();
|
|
378
|
-
//
|
|
415
|
+
//Figures out what kind of animation it is and hides the document properly
|
|
379
416
|
if (IsOverlay(aStyle)) {
|
|
380
417
|
RevealPage(true);
|
|
381
418
|
let pageBlocker = document.createElement('div');
|
|
@@ -394,16 +431,19 @@ function EndPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle) {
|
|
|
394
431
|
document.getElementById(finalOptions.mainContentIdName).hidden = true;
|
|
395
432
|
}
|
|
396
433
|
}
|
|
397
|
-
//
|
|
398
|
-
if (allowAnimate && !(
|
|
434
|
+
//Checks to see if allowAnimate=true and we aren't supposed to be ignoring the link
|
|
435
|
+
if (allowAnimate && !(sessionStorage.getItem("animationType") === "ignore" && (finalOptions.animateIgnoredLinks || finalOptions.animateSelfLink))){
|
|
436
|
+
//Once the load evnet is triggered, it registers a listener
|
|
399
437
|
window.addEventListener(finalOptions.loadEvent, (e) => {
|
|
400
438
|
e.stopPropagation();
|
|
401
439
|
CallHook("animateSEP", { style: aStyle });
|
|
402
|
-
//
|
|
440
|
+
//If we reloaded, we want to make sure runAnimationOnPageReload is false and if we came from a different site, we want to make sure we can run animation on cross site
|
|
403
441
|
if ((window.performance.getEntriesByType("navigation")[0].type != "reload" || finalOptions.runAnimationOnPageReload) && (isNavigationFromSameSite() || finalOptions.runAnimationOnCrossSite)) {
|
|
442
|
+
//Uses a delay between this to keep the document hidden for extra if the load event isn't trusted
|
|
404
443
|
setTimeout(
|
|
405
444
|
() => {
|
|
406
445
|
AnimatePageTransition(aStyle, "reverse");
|
|
446
|
+
//Delay between animation and reveal
|
|
407
447
|
setTimeout(
|
|
408
448
|
() => {
|
|
409
449
|
CallHook("animateEEP", { style: aStyle });
|
|
@@ -413,11 +453,13 @@ function EndPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle) {
|
|
|
413
453
|
}, finalOptions.pageAnimationDelay
|
|
414
454
|
);
|
|
415
455
|
} else {
|
|
456
|
+
//Reveals page after document is built
|
|
416
457
|
CallHook("animateEPNA", { style: aStyle })
|
|
417
458
|
RevealPage();
|
|
418
459
|
}
|
|
419
460
|
}, { once: true });
|
|
420
461
|
} else {
|
|
462
|
+
//Waits for load and Reveals the Page
|
|
421
463
|
window.addEventListener(finalOptions.loadEvent, () => {
|
|
422
464
|
CallHook("animateEPNSW", { style: aStyle })
|
|
423
465
|
RevealPage();
|
|
@@ -425,9 +467,12 @@ function EndPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle) {
|
|
|
425
467
|
}
|
|
426
468
|
}
|
|
427
469
|
exports.EndPoint = EndPoint;
|
|
470
|
+
//Animates the page transition
|
|
428
471
|
function AnimatePageTransition(aStyle, direction = "normal") {
|
|
429
472
|
let mainElement = document.getElementById(finalOptions.mainContentIdName);
|
|
473
|
+
//If we don't have a preset, we can call a hook because presets also call their custom variant
|
|
430
474
|
if (!(aStyle instanceof OverlayPreset) && !(aStyle instanceof KeyFramePreset)) {
|
|
475
|
+
//Sets animationType in storage to allow EndPoint to change page transition element depending on type
|
|
431
476
|
sessionStorage.setItem("animationType", IsOverlay(aStyle).toString());
|
|
432
477
|
if (direction == "normal") {
|
|
433
478
|
CallHook("animateSF", { style: aStyle, ele: mainElement, });
|
|
@@ -435,7 +480,9 @@ function AnimatePageTransition(aStyle, direction = "normal") {
|
|
|
435
480
|
CallHook("animateSR", { style: aStyle, ele: mainElement, });
|
|
436
481
|
}
|
|
437
482
|
}
|
|
483
|
+
//Calls handle function of style element
|
|
438
484
|
aStyle.handle(direction, mainElement);
|
|
485
|
+
//Same logic as above except for end hooks
|
|
439
486
|
if (!(aStyle instanceof OverlayPreset) && !(aStyle instanceof KeyFramePreset)) {
|
|
440
487
|
setTimeout(
|
|
441
488
|
() => {
|
package/guide.txt
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
Types of Animation Containers:
|
|
2
|
-
-KeyFramePreset
|
|
3
|
-
-KeyFrameCustom
|
|
4
|
-
-StyleTransition
|
|
5
|
-
-OverlayPreset
|
|
6
|
-
-OverlayCustom
|
|
7
|
-
-MultiElementAnimation
|
|
8
|
-
|
|
9
|
-
Preset Types:
|
|
10
|
-
-Overlay Presets
|
|
11
|
-
-Keyframe Presets
|
|
12
|
-
|
|
13
|
-
Animation Function:
|
|
14
|
-
-AnimatePageTransition
|
|
15
|
-
|
|
16
|
-
Listener Functions:
|
|
17
|
-
-ListenForChange
|
|
18
|
-
-SendPoint
|
|
19
|
-
-EndPoint
|
|
20
|
-
|
|
21
|
-
Hooks:
|
|
22
|
-
-animateSF - animation start forward
|
|
23
|
-
-animateSR - animation start reverse
|
|
24
|
-
-animateEF - animation end forward
|
|
25
|
-
-animateER - animation end reverse
|
|
26
|
-
-animateSSP - start of send point listen
|
|
27
|
-
-animateESP - end of send point listen
|
|
28
|
-
-animateSEP - start of end point listen
|
|
29
|
-
-animateEPNSW - end point no service worker exists
|
|
30
|
-
-animateEEP - end of end point
|
|
31
|
-
-animateEPNA - end point no animation played
|
|
32
|
-
|
|
33
|
-
Features:
|
|
34
|
-
-Built-in animations
|
|
35
|
-
-Hooks
|
|
36
|
-
-Doesn't touch history or use push state, allowing
|
|
37
|
-
for you to use it with routers like sveltekit
|
|
38
|
-
-Manual page transition animations can be run to avoid
|
|
39
|
-
conflicts with any frameworks
|
|
40
|
-
-Customizable ids for divs to avoid conflict with elements
|
|
41
|
-
in your body
|
|
42
|
-
-Allows for custom overlay animations, keyframe animations, or
|
|
43
|
-
transition animations
|
|
44
|
-
-Separate listener animations for different types of animations
|
|
45
|
-
-Separate types of links for overlay or other animations
|
|
46
|
-
|
|
47
|
-
What I Learned:
|
|
48
|
-
-Expanded knowledge on HTML, JS, and CSS Knowledge
|
|
49
|
-
-Session storage
|
|
50
|
-
-Service workers
|
|
51
|
-
-Polymorphism
|
|
52
|
-
-Event dispatcher
|
|
53
|
-
|
|
54
|
-
Common Issues:
|
|
55
|
-
-White Flash
|
|
56
|
-
-Issues with using absolute positioning on main content and calling overlay animations
|