pagewave 1.0.3 → 1.0.5

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/transition.js DELETED
@@ -1,499 +0,0 @@
1
- //Default Options
2
- let defaultOptions = {
3
- mainContentIdName: "main-content",
4
- overlayClass: "a-overlay",
5
- animationClass: "a-animation",
6
- pageAnimationDelay: 200,
7
- useServiceWorker: true,
8
- runAnimationOnPageReload: false,
9
- runAnimationOnCrossSite: false,
10
- pageRevealDelay: 0,
11
- leavePageOnLink: true,
12
- pageBlockerId: "pageBlocker",
13
- classToIgnoreLink: "ignore-click",
14
- animateIgnoredLinks: false,
15
- animateSelfLink: true,
16
- loadEvent: "DOMContentLoaded",
17
- usePresets: true,
18
- cleanUpDivs: false,
19
- }
20
- //Options object that will contain the actual options used by the program
21
- let finalOptions = {
22
- mainContentIdName: "main-content",
23
- overlayClass: "a-overlay",
24
- animationClass: "a-animation",
25
- pageAnimationDelay: 200,
26
- useServiceWorker: true,
27
- runAnimationOnPageReload: false,
28
- runAnimationOnCrossSite: false,
29
- pageRevealDelay: 0,
30
- leavePageOnClick: true,
31
- pageBlockerId: "pageBlocker",
32
- classToIgnoreLink: "ignore-click",
33
- animateIgnoredLinks: false,
34
- animateSelfLink: true,
35
- loadEvent: "DOMContentLoaded",
36
- usePresets: true,
37
- cleanUpDivs: false,
38
- }
39
-
40
- //Sets Up Page Transition Capability. Not necessary if you don't need options or presets
41
- function SetUp(options = {}) {
42
- //Merge default options with user options
43
- finalOptions = { ...defaultOptions, ...options };
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
- }
54
- }
55
- }
56
- exports.SetUp = SetUp;
57
- //Overlay Preset Types to Choose From
58
- const overlayType = Object.freeze({
59
- slide: Symbol("slide"),
60
- inverseSlide: Symbol("inverseSlide"),
61
- curtain: Symbol("curtain"),
62
- rise: Symbol("rise"),
63
- fall: Symbol("fall"),
64
- bubble: Symbol("bubble"),
65
- });
66
- exports.overlayType = overlayType;
67
- //Keyframe Preset Types to Choose From
68
- const keyframeType = Object.freeze({
69
- fade: Symbol("fade"),
70
- fadeaway: Symbol("fadeaway"),
71
- });
72
- exports.keyframeType = keyframeType;
73
-
74
- //Function to apply animation to element and keep its properties and remove the animation
75
- function ApplyAnimation(element, animationName, duration, timing, direction) {
76
- element.style.animation = `${animationName} ${duration}ms ${timing} both ${direction}`;
77
- if (direction == "reverse") {
78
- let currentAnimation = null;
79
- element.getAnimations().forEach((animation) => {
80
- if (currentAnimation == null && animation.animationName == animationName) {
81
- currentAnimation = animation;
82
- }
83
- });
84
- function handleAnimation(event) {
85
- if (event.animationName == animationName) {
86
- let animationKeyframes = currentAnimation.effect;
87
- let kfValues = Object.values(animationKeyframes.getKeyframes()[0]);
88
- let kfKeys = Object.keys(animationKeyframes.getKeyframes()[0]);
89
- let animationProperties = kfValues.slice(3, kfValues.length - 1);
90
- let animationKeys = kfKeys.slice(3, kfValues.length - 1);
91
- for (let i = 0; i < animationKeys.length; i++) {
92
- element.style[animationKeys[i]] = animationProperties[i].toString();
93
- }
94
- element.style.animation = "";
95
- element.removeEventListener("animationend", handleAnimation);
96
- }
97
- }
98
- element.addEventListener("animationend", handleAnimation,);
99
- }
100
- }
101
- //Dispatch an event for the hooks
102
- function CallHook(hookName, details) {
103
- const event = new CustomEvent(hookName, {
104
- detail: details
105
- });
106
- window.dispatchEvent(event);
107
- }
108
-
109
- class KeyFramePreset {
110
- constructor(kfType, duration, timing = "linear") {
111
- this.kfType = kfType;
112
- this.duration = duration;
113
- this.timing = timing;
114
- }
115
- handle(direction) {
116
- const animationMap = {
117
- fade: "fade",
118
- fadeaway: "fadeaway"
119
- };
120
- //Uses keyframeType to run Keyframe Custom
121
- if (animationMap[this.kfType.description]) {
122
- AnimatePageTransition(new KeyFrameCustom(animationMap[this.kfType.description], this.duration, this.timing), direction);
123
- }
124
- }
125
- }
126
- exports.KeyFramePreset = KeyFramePreset;
127
- class KeyFrameCustom {
128
- constructor(animationName, duration, timing = "linear") {
129
- this.animationName = animationName;
130
- this.duration = duration;
131
- this.timing = timing;
132
- }
133
- handle(direction, mainElement) {
134
- //Reveals element and applys the animation
135
- mainElement.hidden = false;
136
- ApplyAnimation(mainElement, this.animationName, this.duration, this.timing, direction)
137
- }
138
- }
139
- exports.KeyFrameCustom = KeyFrameCustom;
140
- class StyleTransition {
141
- constructor(styleString, duration, startValue, endValue, timing = "linear") {
142
- this.styleString = styleString;
143
- this.duration = duration;
144
- this.startValue = startValue
145
- this.endValue = endValue;
146
- this.timing = timing;
147
- }
148
- handle(direction, mainElement) {
149
- //Applys the transition in the right direction
150
- if (direction == "normal") {
151
- mainElement.style[this.styleString] = this.startValue;
152
- mainElement.style.transition = this.styleString + " " + this.duration.toString() + "ms " + this.timing;
153
- mainElement.style[this.styleString] = this.endValue;
154
- } else if (direction == "reverse") {
155
- mainElement.style[this.styleString] = this.endValue;
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
158
- setTimeout(
159
- () => {
160
- mainElement.style[this.styleString] = this.startValue;
161
- }, 40
162
- );
163
-
164
- }
165
- }
166
- }
167
- exports.StyleTransition = StyleTransition;
168
- class MultiElementAnimation {
169
- constructor(animateableObjects, duration, timing = "linear", mainElementAnimation = "") {
170
- this.animateableObjects = animateableObjects;
171
- this.duration = duration;
172
- this.timing = timing;
173
- this.mainElementAnimation = mainElementAnimation;
174
- }
175
- handle(direction, mainElement) {
176
- mainElement.hidden = false;
177
- let timing = this.timing;
178
- //Goes through every animation selector, finds all of those elements, and applies the proper animation to them
179
- for (const [selector, animationName] of Object.entries(this.animateableObjects)) {
180
- document.querySelectorAll(selector).forEach(element => ApplyAnimation(element, animationName, this.duration, timing, direction));
181
- }
182
- //Animates main element if animation is given
183
- if (this.mainElementAnimation != "") {
184
- ApplyAnimation(mainElement, this.mainElementAnimation, this.duration, timing, direction);
185
- }
186
- }
187
- }
188
- exports.MultiElementAnimation = MultiElementAnimation;
189
- class OverlayPreset {
190
- constructor(oType, duration, color, timing = "linear") {
191
- this.duration = duration;
192
- this.color = color;
193
- this.oType = oType;
194
- this.timing = timing;
195
- }
196
- handle(direction) {
197
- //Finds the proper preset and runs OverlayCustom appropriately
198
- const overlayMap = {
199
- slide: { firstOverlayElement: "slide" },
200
- inverseSlide: { firstOverlayElement: "inverseSlide" },
201
- curtain: { firstOverlayElement: "rightcurtain", secondOverlayElement: "leftcurtain" },
202
- rise: { firstOverlayElement: "rise" },
203
- fall: { firstOverlayElement: "fall" },
204
- bubble: { firstOverlayElement: "bubble" }
205
- };
206
- if (overlayMap[this.oType.description]) {
207
- AnimatePageTransition(new OverlayCustom(overlayMap[this.oType.description], this.duration, this.color, this.timing), direction);
208
- }
209
- }
210
- }
211
- exports.OverlayPreset = OverlayPreset;
212
- class OverlayCustom {
213
- constructor(divAnimationObject, duration, color, timing = "linear", mainElementAnimation = "") {
214
- this.divAnimationObject = divAnimationObject;
215
- this.duration = duration;
216
- this.color = color;
217
- this.timing = timing;
218
- this.mainElementAnimation = mainElementAnimation;
219
- }
220
- handle(direction, mainElement) {
221
- var r = document.querySelector(':root');
222
- r.style.setProperty('--div-color', this.color);
223
- let timing = this.timing;
224
- //Removes divs when animation is finished
225
- function RemoveDiv(event) {
226
- if (event.target.animateName == event.animationName) {
227
- event.target.removeEventListener("animationend", RemoveDiv);
228
- event.target.remove();
229
- }
230
- }
231
- //Loops through divs, creating them, adding the provided class, and giving them an animation
232
- for (const [className, animationName] of Object.entries(this.divAnimationObject)) {
233
- let divElement = document.createElement("div");
234
- divElement.className = className;
235
- divElement.style.animation = `${animationName} ${this.duration.toString()}ms ${timing} both ${direction}`;
236
- mainElement.appendChild(divElement);
237
- //Removes divs at end of animation
238
- if(finalOptions.cleanUpDivs){
239
- divElement.animateName = animationName;
240
- divElement.addEventListener("animationend", RemoveDiv);
241
- }
242
- }
243
- //Animates main element if animation is given
244
- if (this.mainElementAnimation != "") {
245
- mainElement.style.animation = `${this.mainElementAnimation} ${this.duration.toString()}ms ${timing} both ${direction}`;
246
- }
247
- }
248
- }
249
- exports.OverlayCustom = OverlayCustom;
250
- /*
251
- function AddFileToCache(file) {
252
- if ("serviceWorker" in navigator) {
253
- if (navigator.serviceWorker.controller) {
254
- if (navigator.serviceWorker.controller.scriptURL.slice(-5) == "sw.js") {
255
- navigator.serviceWorker.controller.postMessage(file);
256
- }
257
- }
258
- }
259
- }*/
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
261
- function AddServiceWorker() {
262
- if (!finalOptions.useServiceWorker) {
263
- return true;
264
- }
265
- let isServiceWorker = false;
266
- if ("serviceWorker" in navigator) {
267
- if (navigator.serviceWorker.controller) {
268
- if (navigator.serviceWorker.controller.scriptURL.slice(-5) == "sw.js") {
269
- isServiceWorker = true;
270
- }
271
- }
272
- navigator.serviceWorker.register("./sw.js");
273
- }
274
- return isServiceWorker;
275
- }
276
- //Checks if navigation is from same site. Returns false if referrer and current host are different of refferer is empty
277
- function isNavigationFromSameSite() {
278
- const referrer = document.referrer;
279
- if (referrer == "") {
280
- return false;
281
- }
282
- const currentHost = window.location.hostname;
283
- const referrerHost = new URL(referrer).hostname;
284
-
285
- return referrerHost === currentHost;
286
- }
287
- //Returns true if animation is overlay type, false if animation type
288
- function IsOverlay(transitionStyle) {
289
- if (transitionStyle instanceof OverlayPreset || transitionStyle instanceof OverlayCustom) {
290
- return true;
291
- } else if (transitionStyle instanceof StyleTransition || transitionStyle instanceof KeyFrameCustom || transitionStyle instanceof KeyFramePreset || transitionStyle instanceof MultiElementAnimation) {
292
- return false;
293
- }
294
- }
295
- exports.IsOverlay = IsOverlay;
296
- //Checks if element exists. If it does, it runs functionToExecute. Otherwise, waits until element exists to run the function
297
- function WaitForElementLoad(selector, functionToExecute) {
298
- if(document.querySelector(selector) != null){
299
- functionToExecute(document.querySelector(selector));
300
- return;
301
- }
302
- const observer = new MutationObserver((mutations) => {
303
- mutations.forEach((mutation) => {
304
- mutation.addedNodes.forEach((node) => {
305
- if (node.matches && node.matches(selector)) {
306
- observer.disconnect(); // Stop observing
307
- functionToExecute(node); // Handle the element
308
- }
309
- });
310
- });
311
- });
312
- // Start observing the document body for child additions
313
- observer.observe(document.body, { childList: true, subtree: true });
314
- }
315
- exports.WaitForElementLoad = WaitForElementLoad;
316
- //Shorthand for SendPoint and EndPoint
317
- function ListenForChange(aStyle, aOverlay = aStyle, aAnimation = aStyle, leaveFunction = (link) => {window.location = link;}) {
318
- EndPoint(aStyle, aOverlay, aAnimation, leaveFunction);
319
- SendPoint(aStyle, aOverlay, aAnimation);
320
- }
321
- exports.ListenForChange = ListenForChange;
322
- //Listens for clicks and plays animation and then redirects
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
325
- let allowAnimate = AddServiceWorker();
326
-
327
- function HandleClickAnimation(e) {
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
331
- e.preventDefault();
332
- let duration = aStyle.duration;
333
- CallHook("animateSSP", { style: aStyle, overlayStyle: aOverlay, animationStyle: aAnimation, clickEvent: e });
334
- //Plays the right animation depending on link type and sets proper duration
335
- if (e.target.classList.contains(finalOptions.overlayClass)) {
336
- AnimatePageTransition(aOverlay, "normal");
337
- duration = aOverlay.duration;
338
- } else if (e.target.classList.contains(finalOptions.animationClass)) {
339
- AnimatePageTransition(aAnimation, "normal");
340
- duration = aAnimation.duration;
341
- } else {
342
- AnimatePageTransition(aStyle, "normal");
343
- duration = aStyle.duration;
344
- }
345
- //Calls the leave function when duration timer finishes
346
- setTimeout(
347
- () => {
348
- CallHook("animateESP", { style: aStyle, overlayStyle: aOverlay, animationStyle: aAnimation, clickEvent: e });
349
- window.removeEventListener("click", HandleClickAnimation);
350
- if (finalOptions.leavePageOnClick) {
351
- leaveFunction(e.target.href);
352
- }
353
- }, parseInt(duration)
354
- );
355
- //We set the storage to ignore so we don't play an animation when we go to another page.
356
- } else if (e.target.classList.contains(finalOptions.classToIgnoreLink) || (e.target.href == window.location.href && !finalOptions.animateSelfLink)) {
357
- sessionStorage.setItem("animationType", "ignore");
358
- }
359
-
360
- }
361
-
362
- function AddListeners() {
363
- window.addEventListener("click", HandleClickAnimation);
364
- }
365
- //If service worker active, can immediately listen
366
- if (allowAnimate) {
367
- AddListeners();
368
- }
369
- //Else, wait until the loadEvent provided is triggered
370
- else {
371
- window.addEventListener(finalOptions.loadEvent, () => {
372
- AddListeners();
373
- }, { once: true });
374
- }
375
- }
376
- exports.SendPoint = SendPoint;
377
- //Waits for the document to load and plays the reverse animation
378
- function EndPoint(aStyle, aOverlay = aStyle, aAnimation = aStyle) {
379
- //Checks to see what kind of receiving animation to play
380
- if (aOverlay != aStyle || aAnimation != aStyle) {
381
- if (sessionStorage.getItem("animationType") === "true") {
382
- aStyle = aOverlay;
383
- } else if (sessionStorage.getItem("animationType") === "false") {
384
- aStyle = aAnimation;
385
- }
386
- }
387
- function RevealPage(opposite = false) {
388
- if (Boolean(IsOverlay(aStyle) ^ opposite)) {
389
- if (document.getElementById(finalOptions.pageBlockerId) == null) {
390
- WaitForElementLoad(
391
- "#" + finalOptions.pageBlockerId, () => {
392
- if (document.getElementById(finalOptions.pageBlockerId) != null) {
393
- document.getElementById(finalOptions.pageBlockerId).remove();
394
- }
395
- }
396
- );
397
- } else {
398
- document.getElementById(finalOptions.pageBlockerId).remove();
399
- }
400
- }
401
- else if(Boolean(!IsOverlay(aStyle) ^ opposite)) {
402
- if (document.getElementById(finalOptions.mainContentIdName) == null) {
403
- WaitForElementLoad(
404
- "#" + finalOptions.mainContentIdName, () => {
405
- document.getElementById(finalOptions.mainContentIdName).hidden = false;
406
- }
407
- );
408
- } else {
409
- document.getElementById(finalOptions.mainContentIdName).hidden = false;
410
- }
411
- }
412
- }
413
- //True if service worker is active or ignored with useServiceWorker=false, false otherwise
414
- let allowAnimate = AddServiceWorker();
415
- //Figures out what kind of animation it is and hides the document properly
416
- if (IsOverlay(aStyle)) {
417
- RevealPage(true);
418
- let pageBlocker = document.createElement('div');
419
- pageBlocker.id = finalOptions.pageBlockerId;
420
- pageBlocker.style.cssText = `position: absolute; width: 100%; height: 100%; z-index: 100; top: 0; background-color: ${aStyle.color}`
421
- document.body.append(pageBlocker);
422
- } else {
423
- RevealPage(true);
424
- if (document.getElementById(finalOptions.mainContentIdName) == null) {
425
- WaitForElementLoad(
426
- "#" + finalOptions.mainContentIdName, () => {
427
- document.getElementById(finalOptions.mainContentIdName).hidden = true;
428
- }
429
- );
430
- } else {
431
- document.getElementById(finalOptions.mainContentIdName).hidden = true;
432
- }
433
- }
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
437
- window.addEventListener(finalOptions.loadEvent, (e) => {
438
- e.stopPropagation();
439
- CallHook("animateSEP", { style: aStyle });
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
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
443
- setTimeout(
444
- () => {
445
- AnimatePageTransition(aStyle, "reverse");
446
- //Delay between animation and reveal
447
- setTimeout(
448
- () => {
449
- CallHook("animateEEP", { style: aStyle });
450
- RevealPage();
451
- }, finalOptions.pageRevealDelay
452
- );
453
- }, finalOptions.pageAnimationDelay
454
- );
455
- } else {
456
- //Reveals page after document is built
457
- CallHook("animateEPNA", { style: aStyle })
458
- RevealPage();
459
- }
460
- }, { once: true });
461
- } else {
462
- //Waits for load and Reveals the Page
463
- window.addEventListener(finalOptions.loadEvent, () => {
464
- CallHook("animateEPNSW", { style: aStyle })
465
- RevealPage();
466
- }, { once: true });
467
- }
468
- }
469
- exports.EndPoint = EndPoint;
470
- //Animates the page transition
471
- function AnimatePageTransition(aStyle, direction = "normal") {
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
474
- if (!(aStyle instanceof OverlayPreset) && !(aStyle instanceof KeyFramePreset)) {
475
- //Sets animationType in storage to allow EndPoint to change page transition element depending on type
476
- sessionStorage.setItem("animationType", IsOverlay(aStyle).toString());
477
- if (direction == "normal") {
478
- CallHook("animateSF", { style: aStyle, ele: mainElement, });
479
- } else if (direction == "reverse") {
480
- CallHook("animateSR", { style: aStyle, ele: mainElement, });
481
- }
482
- }
483
- //Calls handle function of style element
484
- aStyle.handle(direction, mainElement);
485
- //Same logic as above except for end hooks
486
- if (!(aStyle instanceof OverlayPreset) && !(aStyle instanceof KeyFramePreset)) {
487
- setTimeout(
488
- () => {
489
- if (direction == "normal") {
490
- CallHook("animateEF", { style: aStyle, ele: mainElement, });
491
- } else if (direction == "reverse") {
492
- CallHook("animateER", { style: aStyle, ele: mainElement, });
493
- }
494
- }, aStyle.duration
495
- );
496
- }
497
-
498
- }
499
- exports.AnimatePageTransition = AnimatePageTransition;