fslightbox 3.3.0 → 3.3.2

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.
Files changed (80) hide show
  1. package/FsLightbox.js +110 -0
  2. package/README.md +55 -1
  3. package/components/helpers/renderSvg.js +17 -0
  4. package/components/nav/renderAndGetToolbarButton.js +11 -0
  5. package/components/nav/renderCloseButton.js +10 -0
  6. package/components/nav/renderFullscreenButton.js +42 -0
  7. package/components/nav/renderNav.js +17 -0
  8. package/components/nav/renderSlideNumber.js +33 -0
  9. package/components/nav/renderToolbar.js +13 -0
  10. package/components/renderSlideButton.js +11 -0
  11. package/components/renderSlideButtonContainer.js +15 -0
  12. package/components/renderSlideButtons.js +7 -0
  13. package/components/renderSlideSwipingHoverer.js +6 -0
  14. package/components/sources/proper-sources/renderCustom.js +15 -0
  15. package/components/sources/proper-sources/renderImage.js +18 -0
  16. package/components/sources/proper-sources/renderInvalid.js +19 -0
  17. package/components/sources/proper-sources/renderVideo.js +31 -0
  18. package/components/sources/proper-sources/renderYoutube.js +26 -0
  19. package/components/sources/renderSourceAnimationWrapper.js +4 -0
  20. package/components/sources/renderSourceMainWrapper.js +32 -0
  21. package/components/sources/renderSourceWrappersContainer.js +22 -0
  22. package/constants/classes-names.js +27 -0
  23. package/constants/core-constants.js +6 -0
  24. package/constants/css-constants.js +1 -0
  25. package/constants/dom-constants.js +1 -0
  26. package/constants/elements.js +3 -0
  27. package/constants/local-storage-constants.js +2 -0
  28. package/core/collections/fillSourcesOutersTransformersCollection.js +13 -0
  29. package/core/elements/setUpClassFacade.js +9 -0
  30. package/core/events/setUpEventsDispatcher.js +7 -0
  31. package/core/events/setUpGlobalEventsController.js +34 -0
  32. package/core/fullscreen/setUpFullscreenToggler.js +30 -0
  33. package/core/keyboard/KeyboardController.js +20 -0
  34. package/core/main-component/closing/LightboxCloseActioner.js +46 -0
  35. package/core/main-component/closing/setUpLightboxCloser.js +11 -0
  36. package/core/main-component/initializing/initializeLightbox.js +38 -0
  37. package/core/main-component/opening/setUpLightboxOpener.js +47 -0
  38. package/core/scrollbar/getInnerElementOfWidthGetter.js +5 -0
  39. package/core/scrollbar/getOuterElementOfWidthGetter.js +9 -0
  40. package/core/scrollbar/getScrollbarWidth.js +31 -0
  41. package/core/scrollbar/setUpScrollbarRecompensor.js +20 -0
  42. package/core/setUpCore.js +30 -0
  43. package/core/sizes/setUpWindowResizeActioner.js +35 -0
  44. package/core/slide/setUpSlideChangeFacade.js +23 -0
  45. package/core/slide/setUpSlideIndexChanger.js +60 -0
  46. package/core/sources/SourceLoadActioner.js +29 -0
  47. package/core/sources/SourceLoadHandler.js +41 -0
  48. package/core/sources/SourceSizer.js +36 -0
  49. package/core/sources/creating/CreatingSourcesBucket.js +29 -0
  50. package/core/sources/creating/CreatingSourcesLocalStorageManager.js +55 -0
  51. package/core/sources/creating/createSources.js +28 -0
  52. package/core/sources/pointering/down/setUpSourcesPointerDown.js +36 -0
  53. package/core/sources/pointering/move/SourcesPointerMove.js +16 -0
  54. package/core/sources/pointering/move/SourcesPointerMoveActioner.js +37 -0
  55. package/core/sources/pointering/up/SourcesPointerUp.js +13 -0
  56. package/core/sources/pointering/up/SourcesPointerUpActioner.js +38 -0
  57. package/core/sources/pointering/up/SourcesPointerUpActionerBucket.js +35 -0
  58. package/core/sources/setUpSourceDisplayFacade.js +26 -0
  59. package/core/sources/types/AutomaticTypeDetector.js +70 -0
  60. package/core/sources/types/DetectedTypeActioner.js +44 -0
  61. package/core/sources/types/getAutomaticTypeDetectorBucket.js +14 -0
  62. package/core/stage/setUpStageManager.js +60 -0
  63. package/core/styles/createAndAppendStyles.js +9 -0
  64. package/core/styles/injectStylesIfNotInDom.js +8 -0
  65. package/core/styles/styles-injection/styles-injection.js +5 -0
  66. package/core/timeouts/getQueuedAction.js +15 -0
  67. package/core/transforms/SourceMainWrapperTransformer.js +27 -0
  68. package/fslightbox.js +1 -0
  69. package/helpers/elements/addToElementClassIfNotContains.js +6 -0
  70. package/helpers/elements/removeFromElementChildIfContains.js +5 -0
  71. package/helpers/elements/removeFromElementClassIfContains.js +6 -0
  72. package/helpers/objects/assignToObject.js +10 -0
  73. package/helpers/source/setUpSourceClassName.js +13 -0
  74. package/helpers/source/setUpSourceCustomAttributes.js +5 -0
  75. package/helpers/state/ifOnUpdateExistsHandleItForState.js +6 -0
  76. package/i.js +86 -0
  77. package/index.js +1 -1
  78. package/package.json +4 -37
  79. package/styles.js +1 -0
  80. package/.env.example +0 -3
@@ -0,0 +1,34 @@
1
+ import { KeyboardController } from "../keyboard/KeyboardController";
2
+ import { SourcesPointerMove } from "../sources/pointering/move/SourcesPointerMove";
3
+ import { SourcesPointerUp } from "../sources/pointering/up/SourcesPointerUp";
4
+
5
+ export function setUpGlobalEventsController(
6
+ {
7
+ core: { globalEventsController: self, windowResizeActioner, },
8
+ resolve
9
+ }
10
+ ) {
11
+ const keyboardController = resolve(KeyboardController);
12
+ const sourcesPointerMove = resolve(SourcesPointerMove);
13
+ const sourcesPointerUp = resolve(SourcesPointerUp);
14
+
15
+ self.attachListeners = () => {
16
+ document.addEventListener('pointermove', sourcesPointerMove.listener);
17
+
18
+ document.addEventListener('pointerup', sourcesPointerUp.listener);
19
+
20
+ addEventListener('resize', windowResizeActioner.runActions);
21
+
22
+ document.addEventListener('keydown', keyboardController.listener);
23
+ };
24
+
25
+ self.removeListeners = () => {
26
+ document.removeEventListener('pointermove', sourcesPointerMove.listener);
27
+
28
+ document.removeEventListener('pointerup', sourcesPointerUp.listener);
29
+
30
+ removeEventListener('resize', windowResizeActioner.runActions);
31
+
32
+ document.removeEventListener('keydown', keyboardController.listener);
33
+ };
34
+ }
@@ -0,0 +1,30 @@
1
+ export function setUpFullscreenToggler({ componentsServices, core: { fullscreenToggler: self } }) {
2
+ self.enterFullscreen = () => {
3
+ componentsServices.enterFullscreen();
4
+
5
+ const documentElement = document.documentElement;
6
+ if (documentElement.requestFullscreen) {
7
+ documentElement.requestFullscreen();
8
+ } else if (documentElement.mozRequestFullScreen) {
9
+ documentElement.mozRequestFullScreen();
10
+ } else if (documentElement.webkitRequestFullscreen) {
11
+ documentElement.webkitRequestFullscreen();
12
+ } else if (documentElement.msRequestFullscreen) {
13
+ documentElement.msRequestFullscreen();
14
+ }
15
+ };
16
+
17
+ self.exitFullscreen = () => {
18
+ componentsServices.exitFullscreen();
19
+
20
+ if (document.exitFullscreen) {
21
+ document.exitFullscreen();
22
+ } else if (document.mozCancelFullScreen) {
23
+ document.mozCancelFullScreen();
24
+ } else if (document.webkitExitFullscreen) {
25
+ document.webkitExitFullscreen();
26
+ } else if (document.msExitFullscreen) {
27
+ document.msExitFullscreen();
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,20 @@
1
+ export function KeyboardController({ core: { lightboxCloser, fullscreenToggler, slideChangeFacade } }) {
2
+ this.listener = (e) => {
3
+ switch (e.key) {
4
+ case 'Escape':
5
+ lightboxCloser.closeLightbox();
6
+ break;
7
+ case 'ArrowLeft':
8
+ slideChangeFacade.changeToPrevious();
9
+ break;
10
+ case 'ArrowRight':
11
+ slideChangeFacade.changeToNext();
12
+ break;
13
+ case 'F11':
14
+ e.preventDefault();
15
+ // browsers does not trigger 'keydown' event when browser is already in fullscreen
16
+ fullscreenToggler.enterFullscreen();
17
+ break;
18
+ }
19
+ };
20
+ }
@@ -0,0 +1,46 @@
1
+ import { FADE_OUT_STRONG_CLASS_NAME, OPEN_CLASS_NAME } from "../../../constants/classes-names";
2
+ import { ANIMATION_TIME } from "../../../constants/css-constants";
3
+
4
+ export function LightboxCloseActioner(
5
+ {
6
+ core: {
7
+ eventsDispatcher,
8
+ fullscreenToggler,
9
+ globalEventsController,
10
+ scrollbarRecompensor
11
+ },
12
+ data,
13
+ elements,
14
+ props,
15
+ sourcePointerProps
16
+ }
17
+ ) {
18
+ this.isLightboxFadingOut = false;
19
+
20
+ this.runActions = () => {
21
+ this.isLightboxFadingOut = true;
22
+
23
+ elements.container.classList.add(FADE_OUT_STRONG_CLASS_NAME);
24
+
25
+ globalEventsController.removeListeners();
26
+
27
+ if (props.exitFullscreenOnClose && data.isFullscreenOpen) {
28
+ fullscreenToggler.exitFullscreen();
29
+ }
30
+
31
+ setTimeout(() => {
32
+ this.isLightboxFadingOut = false;
33
+
34
+ sourcePointerProps.isPointering = false;
35
+
36
+ elements.container.classList.remove(FADE_OUT_STRONG_CLASS_NAME);
37
+ document.documentElement.classList.remove(OPEN_CLASS_NAME);
38
+
39
+ scrollbarRecompensor.removeRecompense();
40
+
41
+ document.body.removeChild(elements.container);
42
+
43
+ eventsDispatcher.dispatch('onClose');
44
+ }, ANIMATION_TIME - 30);
45
+ };
46
+ }
@@ -0,0 +1,11 @@
1
+ import { LightboxCloseActioner } from "./LightboxCloseActioner";
2
+
3
+ export function setUpLightboxCloser({ core: { lightboxCloser: self }, resolve }) {
4
+ const lightboxCloseActioner = resolve(LightboxCloseActioner);
5
+
6
+ self.closeLightbox = () => {
7
+ if (!lightboxCloseActioner.isLightboxFadingOut) {
8
+ lightboxCloseActioner.runActions();
9
+ }
10
+ };
11
+ }
@@ -0,0 +1,38 @@
1
+ import {
2
+ FADE_IN_STRONG_CLASS_NAME,
3
+ FULL_DIMENSION_CLASS_NAME,
4
+ PREFIX
5
+ } from "../../../constants/classes-names";
6
+ import { createSources } from "../../sources/creating/createSources";
7
+ import { renderSourceWrappersContainer } from "../../../components/sources/renderSourceWrappersContainer";
8
+ import { renderNav } from "../../../components/nav/renderNav";
9
+ import { fillSourcesOutersTransformersCollection } from "../../collections/fillSourcesOutersTransformersCollection";
10
+ import { renderSlideButtons } from "../../../components/renderSlideButtons";
11
+ import { renderSlideSwipingHoverer } from "../../../components/renderSlideSwipingHoverer";
12
+ import { setUpCore } from "../../setUpCore";
13
+ import { getScrollbarWidth } from "../../scrollbar/getScrollbarWidth";
14
+
15
+ export function initializeLightbox(fsLightbox) {
16
+ const { core: { eventsDispatcher }, data, elements, props: { sources } } = fsLightbox;
17
+
18
+ data.isInitialized = true;
19
+ data.scrollbarWidth = getScrollbarWidth(fsLightbox);
20
+
21
+ fillSourcesOutersTransformersCollection(fsLightbox);
22
+
23
+ setUpCore(fsLightbox);
24
+
25
+ elements.container = document.createElement('div');
26
+ elements.container.className = `${PREFIX}container ${FULL_DIMENSION_CLASS_NAME} ${FADE_IN_STRONG_CLASS_NAME}`;
27
+
28
+ renderSlideSwipingHoverer(fsLightbox);
29
+ renderNav(fsLightbox);
30
+ renderSourceWrappersContainer(fsLightbox);
31
+ if (sources.length > 1) {
32
+ renderSlideButtons(fsLightbox);
33
+ }
34
+
35
+ createSources(fsLightbox);
36
+
37
+ eventsDispatcher.dispatch('onInit');
38
+ }
@@ -0,0 +1,47 @@
1
+ import { OPEN_CLASS_NAME } from "../../../constants/classes-names";
2
+ import { initializeLightbox } from "../initializing/initializeLightbox";
3
+
4
+ export function setUpLightboxOpener(fsLightbox) {
5
+ const {
6
+ collections: { sourceMainWrappersTransformers },
7
+ componentsServices,
8
+ core: {
9
+ eventsDispatcher,
10
+ lightboxOpener: self,
11
+ globalEventsController,
12
+ scrollbarRecompensor,
13
+ sourceDisplayFacade,
14
+ stageManager,
15
+ windowResizeActioner
16
+ },
17
+ data,
18
+ elements,
19
+ stageIndexes
20
+ } = fsLightbox;
21
+
22
+ self.open = (index = 0) => {
23
+ stageIndexes.current = index;
24
+
25
+ (data.isInitialized) ?
26
+ eventsDispatcher.dispatch('onShow') :
27
+ initializeLightbox(fsLightbox);
28
+
29
+ stageManager.updateStageIndexes();
30
+
31
+ sourceDisplayFacade.displaySourcesWhichShouldBeDisplayed();
32
+
33
+ componentsServices.setSlideNumber(index + 1);
34
+
35
+ document.body.appendChild(elements.container);
36
+ document.documentElement.classList.add(OPEN_CLASS_NAME);
37
+
38
+ scrollbarRecompensor.addRecompense();
39
+
40
+ globalEventsController.attachListeners();
41
+
42
+ windowResizeActioner.runActions();
43
+ sourceMainWrappersTransformers[stageIndexes.current].zero();
44
+
45
+ eventsDispatcher.dispatch('onOpen');
46
+ };
47
+ }
@@ -0,0 +1,5 @@
1
+ export function getInnerElementOfWidthGetter() {
2
+ const inner = document.createElement('div');
3
+ inner.style.width = '100%';
4
+ return inner;
5
+ }
@@ -0,0 +1,9 @@
1
+ export function getOuterElementOfWidthGetter() {
2
+ const outer = document.createElement('div');
3
+ const outerStyle = outer.style;
4
+ outerStyle.visibility = "hidden";
5
+ outerStyle.width = "100px";
6
+ outerStyle.msOverflowStyle = "scrollbar";
7
+ outerStyle.overflow = "scroll";
8
+ return outer;
9
+ }
@@ -0,0 +1,31 @@
1
+ import { getOuterElementOfWidthGetter } from "./getOuterElementOfWidthGetter";
2
+ import { getInnerElementOfWidthGetter } from "./getInnerElementOfWidthGetter";
3
+ import { SCROLLBAR_WIDTH_KEY } from "../../constants/local-storage-constants";
4
+
5
+ export function getScrollbarWidth({ props: { disableLocalStorage } }) {
6
+ if (!disableLocalStorage) {
7
+ const localStorageScrollbarWidth = localStorage.getItem(SCROLLBAR_WIDTH_KEY);
8
+ if (localStorageScrollbarWidth) {
9
+ return localStorageScrollbarWidth;
10
+ }
11
+ }
12
+
13
+ const outer = getOuterElementOfWidthGetter();
14
+ const inner = getInnerElementOfWidthGetter();
15
+
16
+ document.body.appendChild(outer);
17
+ const widthNoScroll = outer.offsetWidth;
18
+
19
+ outer.appendChild(inner);
20
+ const widthWithScroll = inner.offsetWidth;
21
+
22
+ document.body.removeChild(outer);
23
+
24
+ const scrollbarWidth = widthNoScroll - widthWithScroll;
25
+
26
+ if (!disableLocalStorage) {
27
+ localStorage.setItem(SCROLLBAR_WIDTH_KEY, scrollbarWidth.toString());
28
+ }
29
+
30
+ return scrollbarWidth;
31
+ }
@@ -0,0 +1,20 @@
1
+ export function setUpScrollbarRecompensor({ data, core: { scrollbarRecompensor: self } }) {
2
+ self.addRecompense = () => {
3
+ (document.readyState === "complete") ?
4
+ ifBodyIsHigherThanWindowAddRecompenseToScrollbar() :
5
+ addEventListener('load', () => {
6
+ ifBodyIsHigherThanWindowAddRecompenseToScrollbar();
7
+ self.addRecompense = ifBodyIsHigherThanWindowAddRecompenseToScrollbar;
8
+ });
9
+ };
10
+
11
+ function ifBodyIsHigherThanWindowAddRecompenseToScrollbar() {
12
+ if (document.body.offsetHeight > innerHeight) {
13
+ document.body.style.marginRight = data.scrollbarWidth + 'px';
14
+ }
15
+ }
16
+
17
+ self.removeRecompense = () => {
18
+ document.body.style.removeProperty('margin-right');
19
+ };
20
+ }
@@ -0,0 +1,30 @@
1
+ import { setUpLightboxOpener } from "./main-component/opening/setUpLightboxOpener";
2
+ import { setUpClassFacade } from "./elements/setUpClassFacade";
3
+ import { setUpEventsDispatcher } from "./events/setUpEventsDispatcher";
4
+ import { setUpFullscreenToggler } from "./fullscreen/setUpFullscreenToggler";
5
+ import { setUpLightboxCloser } from "./main-component/closing/setUpLightboxCloser";
6
+ import { setUpWindowResizeActioner } from "./sizes/setUpWindowResizeActioner";
7
+ import { setUpScrollbarRecompensor } from "./scrollbar/setUpScrollbarRecompensor";
8
+ import { setUpSlideIndexChanger } from "./slide/setUpSlideIndexChanger";
9
+ import { setUpGlobalEventsController } from "./events/setUpGlobalEventsController";
10
+ import { setUpSlideChangeFacade } from "./slide/setUpSlideChangeFacade";
11
+ import { setUpSourceDisplayFacade } from "./sources/setUpSourceDisplayFacade";
12
+ import { setUpStageManager } from "./stage/setUpStageManager";
13
+ import { setUpSourcesPointerDown } from "./sources/pointering/down/setUpSourcesPointerDown";
14
+
15
+ export function setUpCore(fsLightbox) {
16
+ setUpClassFacade(fsLightbox);
17
+ setUpEventsDispatcher(fsLightbox);
18
+ setUpFullscreenToggler(fsLightbox);
19
+ setUpGlobalEventsController(fsLightbox);
20
+ setUpLightboxCloser(fsLightbox);
21
+ setUpLightboxOpener(fsLightbox);
22
+ setUpScrollbarRecompensor(fsLightbox);
23
+ setUpSlideChangeFacade(fsLightbox);
24
+ setUpSlideIndexChanger(fsLightbox);
25
+ setUpSourcesPointerDown(fsLightbox);
26
+ setUpSourceDisplayFacade(fsLightbox);
27
+ setUpStageManager(fsLightbox);
28
+ setUpWindowResizeActioner(fsLightbox);
29
+ }
30
+
@@ -0,0 +1,35 @@
1
+ import { removeFromElementClassIfContains } from "../../helpers/elements/removeFromElementClassIfContains";
2
+ import { TRANSFORM_TRANSITION_CLASS_NAME } from "../../constants/classes-names";
3
+
4
+ export function setUpWindowResizeActioner(
5
+ {
6
+ collections: { sourceMainWrappersTransformers, sourceSizers },
7
+ core: { windowResizeActioner: self },
8
+ data,
9
+ elements: { sourceMainWrappers },
10
+ props,
11
+ stageIndexes
12
+ }
13
+ ) {
14
+ self.runActions = () => {
15
+ // decreasing max source dimensions for better UX
16
+ (innerWidth < 992) ?
17
+ data.maxSourceWidth = innerWidth :
18
+ data.maxSourceWidth = 0.9 * innerWidth;
19
+ data.maxSourceHeight = 0.9 * innerHeight;
20
+
21
+ for (let i = 0; i < props.sources.length; i++) {
22
+ removeFromElementClassIfContains(sourceMainWrappers[i], TRANSFORM_TRANSITION_CLASS_NAME);
23
+
24
+ if (i !== stageIndexes.current) {
25
+ sourceMainWrappersTransformers[i].negative();
26
+ }
27
+
28
+ // if source is Invalid or if lightbox is initialized there are no sourceSizers
29
+ // so we need to check if it exists
30
+ if (sourceSizers[i]) {
31
+ sourceSizers[i].adjustSize();
32
+ }
33
+ }
34
+ };
35
+ }
@@ -0,0 +1,23 @@
1
+ export function setUpSlideChangeFacade(
2
+ {
3
+ core: {
4
+ slideChangeFacade: self,
5
+ slideIndexChanger,
6
+ stageManager
7
+ },
8
+ props: { sources }
9
+ }
10
+ ) {
11
+ if (sources.length > 1) {
12
+ self.changeToPrevious = () => {
13
+ slideIndexChanger.jumpTo(stageManager.getPreviousSlideIndex());
14
+ };
15
+
16
+ self.changeToNext = () => {
17
+ slideIndexChanger.jumpTo(stageManager.getNextSlideIndex());
18
+ };
19
+ } else {
20
+ self.changeToPrevious = () => {};
21
+ self.changeToNext = () => {};
22
+ }
23
+ }
@@ -0,0 +1,60 @@
1
+ import { ANIMATION_TIME } from "../../constants/css-constants";
2
+ import { SOURCE_ANIMATION_WRAPPERS, SOURCE_MAIN_WRAPPERS } from "../../constants/elements";
3
+ import {
4
+ FADE_IN_CLASS_NAME, FADE_IN_STRONG_CLASS_NAME,
5
+ FADE_OUT_CLASS_NAME,
6
+ TRANSFORM_TRANSITION_CLASS_NAME,
7
+ } from "../../constants/classes-names";
8
+ import { removeFromElementClassIfContains } from "../../helpers/elements/removeFromElementClassIfContains";
9
+ import { getQueuedAction } from "../timeouts/getQueuedAction";
10
+
11
+ export function setUpSlideIndexChanger(
12
+ {
13
+ collections: { sourceMainWrappersTransformers },
14
+ componentsServices,
15
+ core: { classFacade, slideIndexChanger: self, sourceDisplayFacade, stageManager },
16
+ elements: { sourceAnimationWrappers },
17
+ stageIndexes
18
+ }
19
+ ) {
20
+ const runQueuedRemoveFadeOut = getQueuedAction(() => {
21
+ classFacade.removeFromEachElementClassIfContains(SOURCE_ANIMATION_WRAPPERS, FADE_OUT_CLASS_NAME);
22
+ }, ANIMATION_TIME);
23
+
24
+ self.changeTo = (i) => {
25
+ stageIndexes.current = i;
26
+
27
+ stageManager.updateStageIndexes();
28
+
29
+ componentsServices.setSlideNumber(i + 1);
30
+
31
+ sourceDisplayFacade.displaySourcesWhichShouldBeDisplayed();
32
+ };
33
+
34
+ self.jumpTo = (i) => {
35
+ let previousI = stageIndexes.current;
36
+ self.changeTo(i);
37
+
38
+ classFacade.removeFromEachElementClassIfContains(SOURCE_MAIN_WRAPPERS, TRANSFORM_TRANSITION_CLASS_NAME);
39
+
40
+ removeFromElementClassIfContains(sourceAnimationWrappers[previousI], FADE_IN_STRONG_CLASS_NAME);
41
+ removeFromElementClassIfContains(sourceAnimationWrappers[previousI], FADE_IN_CLASS_NAME);
42
+ sourceAnimationWrappers[previousI].classList.add(FADE_OUT_CLASS_NAME);
43
+
44
+ removeFromElementClassIfContains(sourceAnimationWrappers[i], FADE_IN_STRONG_CLASS_NAME);
45
+ removeFromElementClassIfContains(sourceAnimationWrappers[i], FADE_OUT_CLASS_NAME);
46
+ sourceAnimationWrappers[i].classList.add(FADE_IN_CLASS_NAME);
47
+
48
+ // we need to remove fade out from all sources because if someone used slide swiping during animation timeout
49
+ // we cannot detect what slide will be
50
+ runQueuedRemoveFadeOut();
51
+
52
+ sourceMainWrappersTransformers[i].zero();
53
+
54
+ setTimeout(() => {
55
+ if (previousI !== stageIndexes.current) {
56
+ sourceMainWrappersTransformers[previousI].negative();
57
+ }
58
+ }, ANIMATION_TIME - 30);
59
+ };
60
+ }
@@ -0,0 +1,29 @@
1
+ import { SourceSizer } from "./SourceSizer";
2
+ import { FADE_IN_STRONG_CLASS_NAME, OPACITY_1_CLASS_NAME } from "../../constants/classes-names";
3
+
4
+ export function SourceLoadActioner(
5
+ {
6
+ collections: { sourceSizers },
7
+ elements: { sourceAnimationWrappers, sourceMainWrappers, sources },
8
+ resolve
9
+ }, i
10
+ ) {
11
+ this.runActions = (defaultWidth, defaultHeight) => {
12
+ sources[i].classList.add(OPACITY_1_CLASS_NAME);
13
+ sourceAnimationWrappers[i].classList.add(FADE_IN_STRONG_CLASS_NAME);
14
+ sourceMainWrappers[i].removeChild(sourceMainWrappers[i].firstChild);
15
+
16
+ runNormalLoadActions(defaultWidth, defaultHeight);
17
+ this.runActions = runNormalLoadActions;
18
+ };
19
+
20
+ /**
21
+ * Next loads after initial occur only while using 'srcset' so need to recreate SourceSizer.
22
+ *
23
+ * Note: Reopening lightbox does not trigger image load.
24
+ */
25
+ function runNormalLoadActions(defaultWidth, defaultHeight) {
26
+ sourceSizers[i] = resolve(SourceSizer, [i, defaultWidth, defaultHeight]);
27
+ sourceSizers[i].adjustSize();
28
+ }
29
+ }
@@ -0,0 +1,41 @@
1
+ import { SourceLoadActioner } from "./SourceLoadActioner";
2
+
3
+ export function SourceLoadHandler({ elements: { sources }, props, resolve, }, i) {
4
+ const sourceLoadActioner = resolve(SourceLoadActioner, [i]);
5
+
6
+ let wasVideoLoadCalled;
7
+
8
+ this.handleImageLoad = ({ target: { naturalWidth, naturalHeight } }) => {
9
+ sourceLoadActioner.runActions(naturalWidth, naturalHeight);
10
+ };
11
+
12
+ this.handleVideoLoad = ({ target: { videoWidth, videoHeight } }) => {
13
+ wasVideoLoadCalled = true;
14
+ sourceLoadActioner.runActions(videoWidth, videoHeight);
15
+ };
16
+
17
+ this.handleNotMetaDatedVideoLoad = () => {
18
+ if (!wasVideoLoadCalled) {
19
+ this.handleYoutubeLoad();
20
+ }
21
+ };
22
+
23
+ this.handleYoutubeLoad = () => {
24
+ let width = 1920;
25
+ let height = 1080;
26
+
27
+ if (props.maxYoutubeDimensions) {
28
+ width = props.maxYoutubeDimensions.width;
29
+ height = props.maxYoutubeDimensions.height;
30
+ }
31
+
32
+ sourceLoadActioner.runActions(width, height);
33
+ };
34
+
35
+ this.handleCustomLoad = () => {
36
+ setTimeout(() => {
37
+ const source = sources[i];
38
+ sourceLoadActioner.runActions(source.offsetWidth, source.offsetHeight);
39
+ });
40
+ };
41
+ }
@@ -0,0 +1,36 @@
1
+ export function SourceSizer({ data, elements: { sources } }, i, defaultWidth, defaultHeight) {
2
+ const ratio = defaultWidth / defaultHeight;
3
+ let newHeight = 0;
4
+
5
+ /**
6
+ * This method takes care of setting sources dimensions.
7
+ * Unfortunately wa cannot only set max width and max height and allow the sources to scale themselves,
8
+ * due tu Youtube source which dimensions needs to be set in advance.
9
+ * In this case we are calculating dimensions mathematically.
10
+ */
11
+ this.adjustSize = () => {
12
+ newHeight = data.maxSourceWidth / ratio;
13
+
14
+ // wider than higher
15
+ if (newHeight < data.maxSourceHeight) {
16
+ if (defaultWidth < data.maxSourceWidth) {
17
+ newHeight = defaultHeight;
18
+ }
19
+ return updateDimensions();
20
+ }
21
+
22
+ // higher than wider
23
+ if (defaultHeight > data.maxSourceHeight) {
24
+ newHeight = data.maxSourceHeight;
25
+ } else {
26
+ newHeight = defaultHeight;
27
+ }
28
+
29
+ updateDimensions();
30
+ };
31
+
32
+ const updateDimensions = () => {
33
+ sources[i].style.width = newHeight * ratio + 'px';
34
+ sources[i].style.height = newHeight + 'px';
35
+ }
36
+ }
@@ -0,0 +1,29 @@
1
+ import { AutomaticTypeDetector } from "../types/AutomaticTypeDetector";
2
+
3
+ export function CreatingSourcesBucket(
4
+ {
5
+ props: { types, type, sources }, resolve,
6
+ }, localStorageManager, detectedTypeActioner
7
+ ) {
8
+ this.getTypeSetByClientForIndex = (i) => {
9
+ let typeSetManuallyByClient;
10
+
11
+ if (types && types[i]) {
12
+ typeSetManuallyByClient = types[i];
13
+ } else if (type) {
14
+ typeSetManuallyByClient = type;
15
+ }
16
+
17
+ return typeSetManuallyByClient;
18
+ };
19
+
20
+ this.retrieveTypeWithXhrForIndex = (i) => {
21
+ // we need to copy index because xhr will for sure come later than next loop iteration
22
+ const automaticTypeDetector = resolve(AutomaticTypeDetector);
23
+ automaticTypeDetector.setUrlToCheck(sources[i]);
24
+ automaticTypeDetector.getSourceType((sourceType) => {
25
+ localStorageManager.handleReceivedSourceTypeForUrl(sourceType, sources[i]);
26
+ detectedTypeActioner.runActionsForSourceTypeAndIndex(sourceType, i)
27
+ });
28
+ };
29
+ }
@@ -0,0 +1,55 @@
1
+ import { SOURCES_TYPES_KEY } from "../../../constants/local-storage-constants";
2
+ import { assignToObject } from "../../../helpers/objects/assignToObject";
3
+
4
+ export function CreatingSourcesLocalStorageManager({ props }) {
5
+ const NEW_TYPE_SHOULD_BE_ADDED_HERE = false;
6
+ let decodedSourceTypes;
7
+ let newSourceTypesToDetect = 0;
8
+ const newTypes = {};
9
+
10
+ this.getSourceTypeFromLocalStorageByUrl = (url) => {
11
+ if (!decodedSourceTypes[url]) {
12
+ return addNewUrlToDetect(url);
13
+ }
14
+ return decodedSourceTypes[url];
15
+ };
16
+
17
+ this.handleReceivedSourceTypeForUrl = (sourceType, url) => {
18
+ if (newTypes[url] === NEW_TYPE_SHOULD_BE_ADDED_HERE) {
19
+ newSourceTypesToDetect--;
20
+
21
+ // not storing invalid types
22
+ if (sourceType !== 'invalid') {
23
+ newTypes[url] = sourceType;
24
+ } else {
25
+ delete newTypes[url];
26
+ }
27
+
28
+ if (newSourceTypesToDetect === 0) {
29
+ assignToObject(decodedSourceTypes, newTypes);
30
+ localStorage.setItem(SOURCES_TYPES_KEY, JSON.stringify(decodedSourceTypes));
31
+ }
32
+ }
33
+ };
34
+
35
+ const addNewUrlToDetect = (url) => {
36
+ newSourceTypesToDetect++;
37
+ newTypes[url] = NEW_TYPE_SHOULD_BE_ADDED_HERE;
38
+ };
39
+
40
+ if (!props.disableLocalStorage) {
41
+ decodedSourceTypes = JSON.parse(localStorage.getItem(SOURCES_TYPES_KEY));
42
+ // we are checking if detected source types contains at certain key source type
43
+ // when localStorage will be empty we can overwrite this method because we are sure
44
+ // that at every index will be no source type
45
+ if (!decodedSourceTypes) {
46
+ // in ifAllNewTypesAreDetectedStoreAllTypesToLocalStorage we are assigning to
47
+ // decodedSourceTypes new Types so we need to make it an object to avoid errors
48
+ decodedSourceTypes = {};
49
+ this.getSourceTypeFromLocalStorageByUrl = addNewUrlToDetect;
50
+ }
51
+ } else {
52
+ this.getSourceTypeFromLocalStorageByUrl = function () {};
53
+ this.handleReceivedSourceTypeForUrl = function () {};
54
+ }
55
+ }