Completed
Push — master ( 530622...0684ff )
by D
02:37
created

Lightbox.bodyClose   A

Complexity

Conditions 3

Size

Total Lines 17
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 17
dl 0
loc 17
rs 9.55
c 0
b 0
f 0
1
import {define} from "../globals/globals";
2
import {LightboxInterface} from "../interfaces/LightboxInterface";
3
import {LightboxOptions} from "../types/LightboxOptions";
4
import {ImagePositionOptions} from "../types/internal/ImagePositionOptions";
5
6
(function (root, factory) {
7
    if (typeof define === 'function' && define.amd) {
8
        define([], factory);
9
    } else if (typeof module === 'object' && module.exports) {
10
        module.exports = factory();
11
    } else {
12
        root!.Lightbox = factory();
13
    }
14
}(typeof self !== 'undefined' ? self : this, function () {
15
16
    class Lightbox implements LightboxInterface {
17
        public options: LightboxOptions;
18
        static animationCloseSpeed: number = 500;
19
        static animationTranslateSpeed: number = 150;
20
21
        constructor(options: LightboxOptions) {
22
23
            if (!options.targets) {
24
                throw new Error('No targets')
25
            }
26
27
            this.options = options;
28
            this.options.targets = typeof options.targets === 'string' ? document.querySelectorAll(options.targets) : options.targets;
29
            this.initClasses();
30
            this.initClone();
31
            this.bodyClose();
32
        }
33
34
        private initClasses(): void {
35
            this.options.targets.forEach(function (target: HTMLImageElement) {
36
                target.classList.add('lightbox');
37
            });
38
        }
39
40
        private initHTML(target: HTMLImageElement, position: ImagePositionOptions): void {
41
            let wrapper = document.createElement('div');
42
43
            new Promise(function (resolve) {
44
                wrapper.classList.add('lightbox-clone-wrapper');
45
46
                setTimeout(resolve, 100);
47
            }).then(function () {
48
                wrapper.classList.add('active');
49
            });
50
51
            let clone = document.createElement('div');
52
53
            new Promise(function (resolve) {
54
                clone.classList.add('lightbox-clone');
55
                clone.style.top = position.top + 'px';
56
                clone.style.left = position.left + 'px';
57
                clone.style.width = target.naturalWidth + 'px';
58
59
                setTimeout(resolve, 100);
60
            }).then(function () {
61
                clone.classList.add('centered');
62
            });
63
64
            let cloneImg = document.createElement('img');
65
            cloneImg.src = target.src;
66
67
            clone.appendChild(cloneImg);
68
            wrapper.appendChild(clone);
69
            document.body.appendChild(wrapper);
70
        }
71
72
        private initClone(): void {
73
            let that = this;
74
75
            this.options.targets.forEach(function (target: HTMLImageElement) {
76
                target.addEventListener('click', function (e) {
77
                    that.initHTML(e.target as HTMLImageElement, that.getTargetPosition(target));
78
79
                    that.scrollClose(target);
80
                })
81
            });
82
        }
83
84
        protected getTargetPosition(target: HTMLImageElement): ImagePositionOptions {
85
            let targetPosition = target.getBoundingClientRect();
86
87
            return {
88
                top: targetPosition.top,
89
                left: targetPosition.left
90
            }
91
        }
92
93
        protected bodyClose(): void {
94
            document.addEventListener('click', function (e) {
95
                e.preventDefault();
96
97
                if((e.target as HTMLElement).closest('.lightbox-clone-wrapper')) {
98
                    let wrapper = document.querySelector('.lightbox-clone-wrapper') as HTMLElement;
99
100
                    if(wrapper) {
101
                        let clone = wrapper.firstElementChild as HTMLElement;
102
103
                        new Promise<void>(function (resolve) {
104
                            clone.classList.remove('centered');
105
106
                            setTimeout(resolve, Lightbox.animationCloseSpeed);
107
                        }).then(function () {
108
                            wrapper.remove();
109
                        });
110
                    }
111
                }
112
            });
113
        }
114
115
        protected scrollClose(target: HTMLImageElement) {
116
            setTimeout(function(){
117
                Lightbox.runOnce(document, 'scroll', function () {
118
                    let targetPosition = target.getBoundingClientRect();
119
                    let wrapper = document.querySelector('.lightbox-clone-wrapper') as HTMLElement;
120
121
                    if(wrapper) {
122
                        let clone = wrapper.firstElementChild as HTMLElement;
123
124
                        new Promise<void>(function (resolve) {
125
                            clone.classList.remove('centered');
126
                            clone.style.top = targetPosition.top + 'px';
127
                            clone.style.left = targetPosition.left + 'px';
128
129
                            setTimeout(resolve, Lightbox.animationCloseSpeed);
130
                        }).then(function () {
131
                            if((clone.style.top === targetPosition.top + 'px') && (clone.style.left === targetPosition.left + 'px')) {
132
                                wrapper.remove();
133
                            }
134
                        });
135
                    }
136
                });
137
            }, Lightbox.animationCloseSpeed);
138
        }
139
140
        static runOnce(node: Node, type: string, callback: EventListener) {
141
            node.addEventListener(type, function(e) {
142
                e.target!.removeEventListener(e.type, callback);
143
                return callback(e);
144
            });
145
        }
146
    }
147
148
    return Lightbox;
149
}));