aboutsummaryrefslogtreecommitdiff
path: root/scripts/src/overlay.js
blob: b40d911cf5a25f6af0334adac36253dfb296da97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
'use strict';
/**
 * @name Novicell overlay
 * @desc Simple script that opens an overlay / modal with some content form either a selector or an URL
 * @author Danni Larsen (DLA), Michael Sølvsteen (MSL), Signe Helbo Poulsen (SHP), Emil Skytte Ankersen (EAN)
 * @example novicell.overlay.create({ 'selector': SELECTOR, 'url': URL,  'class':'CLASSNAME', 'onCreate': FUNCTIONNAME, 'onLoaded': FUNCTIONNAME, 'onDestroy': FUNCTIONNAME });
 * @requires none
 */

var novicell = novicell || {};

novicell.overlay = novicell.overlay || new function () {
    var self = this;
    var options = {};
    var overlayElem;
    var overlayContainer;
    var overlayContent;
    var backdrop;
    var content;
    var onCreate;
    var onLoaded;
    var onDestroy;
    var isVideo = false;

    this.create = function (opts) {
        var self = this;
        // Set global options
        options = opts;

        // Call onCreate callback
        if (typeof options.onCreate === 'function') {
            options.onCreate();
        }

        // Remove existing overlays
        self.destroy();

        // Check if content comes from a DOM selector
        if (options.hasOwnProperty('selector') && options.selector !== null) {
            var element = document.querySelector(options.selector);
            
            if (element) {
                content = element.innerHTML;
                constructOverlay();
            } else {
                console.warn('novicell.overlay: element does not exist. Please provide a valid selector for use in document.querySelector.');
                return;
            }
        }

        // Check if content comes from a HTML element
        else if (options.hasOwnProperty('element') && options.element !== null) {
            var element = options.element;

            if (element) {
                content = element.innerHTML;
                constructOverlay();
            } else {
                console.warn('novicell.overlay: element does not exist. Please provide a valid DOM element.');
                return;
            }
        }

        // Or if content comes from an ID
        else if (options.hasOwnProperty('videoId')) {
            if (options.videoId !== null) {
                var src = '';
                isVideo = true;

                if(options.type == 'vimeo') {
                    src = 'https://player.vimeo.com/video/' + options.videoId + '?autoplay=' + options.autoplay;
                }
                else if(options.type == 'youtube') {
                    src = 'https://www.youtube.com/embed/' + options.videoId + '?autoplay=' + options.autoplay + '&rel=0';
                }
                else {
                    return;
                }

                var iframe = document.createElement('iframe');
                iframe.setAttribute('src', src);
                iframe.setAttribute('frameborder', 0);
                iframe.setAttribute('allowfullscreen', '');
                iframe.setAttribute('width', '100%');
                iframe.setAttribute('height', '100%');

                content = iframe.outerHTML;
                
                constructOverlay();
            } else {
                console.warn('novicell.overlay: video-id is empty. Please provide a video-id for use in video embed code (we support only Vimeo and YouTube).');
                return;
            }
        }
        // If nothing is working, send error to los consolé
        else {
            console.error('novicell.overlay: no content to display! Please set a selector or a url to load.')
            return;
        }
    };

    this.destroy = function () {
        if(document.querySelector('#js-novi-overlay')) {
            // Remove elements
            overlayElem.parentElement.removeChild(overlayElem);
            backdrop.parentElement.removeChild(backdrop);

            // Stop listening for close overlay events
            document.removeEventListener('keyup', self.destroy);

            // Remove class on body
            document.documentElement.classList.remove('no-scroll', 'novi-overlay--open');

            // Reset video variable
            isVideo = false;

            // Call onDestroy callback
            if (typeof options.onDestroy === 'function') {
                options.onDestroy();
            }
        }
    };

    function constructOverlay() {
        // Create backdrop
        setupBackdrop();

        // Create the overlay
        setupOverlay();

        // Create content for overlay
        setupOverlayContainer();

        // Create close button
        setupCloseButton();

        // Add class to body-element
        document.documentElement.classList.add('no-scroll');

        // Call onLoaded callback
        if (typeof options.onLoaded === 'function') {
            options.onLoaded();
        }
    };

    function setupBackdrop() {
        // Create the backdrop
        backdrop = document.createElement('div');
        backdrop.classList.add('novi-backdrop');
        backdrop.id = 'js-novi-backdrop';

        backdrop.addEventListener('click', function(e){
            if(e.target.classList.contains('novi-overlay') || e.target.classList.contains('novi-overlay__container')) {
                self.destroy();
            }
        });

        // Add backdrop to overlay element
        document.querySelector('body').appendChild(backdrop);
    };

    /*
     * Helper functions for HTML elements
     */
    function setupOverlay() {
        // Create the overlay
        overlayElem = document.createElement('div');
        overlayElem.classList.add('novi-overlay');
        overlayElem.id = 'js-novi-overlay';

        // Set class for the overlay, if set in options
        if (options.hasOwnProperty('class')) {
            overlayElem.classList.add(options.class);
        }

        // Add overlay to overlay element
        // document.querySelector('body').appendChild(overlayElem);
        backdrop.appendChild(overlayElem);
    };

    function setupOverlayContainer() {
        // Create content for overlay
        overlayContainer = document.createElement('div');
        overlayContainer.classList.add('novi-overlay__container');

        // Create scroll element
        overlayContent = document.createElement('div');
        overlayContent.classList.add('novi-overlay__content');

        if(isVideo) {
            overlayContent.classList.add('novi-overlay__content--video')
        }

        // Set content
        overlayContent.innerHTML = content;
        overlayContainer.appendChild(overlayContent);

        // Add overlayContainer to overlay element
        overlayElem.appendChild(overlayContainer);
    };

    function setupCloseButton() {
        // Create the button
        var btnClose = document.createElement('button');
        btnClose.classList.add('novi-overlay-close', 'button--close');
        btnClose.type = 'button';
        btnClose.id = 'js-novi-overlay-close';

        // Add eventlistener for button click
        btnClose.addEventListener('click', self.destroy);

        // Add eventlistener for esc key
        document.addEventListener('keydown', function (e) {
            if (e.keyCode === 27) {
                self.destroy();
            }
        });

        // Add close button to overlay element
        overlayContent.appendChild(btnClose);
    };

    /*
     * Helper functions for getting content
     */
    function get(url) {
        // Return a new promise.
        return new Promise(function (resolve, reject) {
            // Do the usual XHR stuff
            var req = new XMLHttpRequest();
            req.open('GET', url);

            req.onload = function () {
                if (req.status >= 200 && req.status < 400) {
                    // Success!!
                    resolve(req.response);
                } else {
                    // Error!!
                    reject(Error(req.statusText));
                }
            };

            // Handle network errors
            req.onerror = function () {
                reject(Error("Network Error"));
            };

            // Make the request
            req.send();
        });
    };

}();