PageSourceSearch

https://evertz.com/js/lib.video-lightbox.js?039

js evertz.com collected 2026-10-02 03:45:35 UTC 11,387 bytes, 260 lines download raw bytes

1/**
2 * Video lightbox controller
3 * - Requires lib.ajax.js
4 * - Requires bootstrap.min.css(.map)
5 * - Requires web.css, web.js
6 * - Requires /img/evertz/loading.214px.webp
7 * - Requires /img/evertz/loading.428px.webp
8 * - Requires /img/evertz/loading.856px.webp
9 *
10 * @param video: must be an object containing:
11 *   - 'link' => An 11 character YouTube code OR a link URL
12 *   - 'resolution' => Video resolution; (req'd for link URLs)
13 *     - Must be one of the following string values:
14 *       - 320p, 480p, 720p, 1080p, 2160p, 4K
15 *
16 *   ... OR an array of such objects. Video link types cannot be
17 *   mixed within a single call; you can't use YouTube and link URLs
18 *   in the same array of objects. In the case of using link URLs, the
19 *   multiple videos should be different resolutions of the same video
20 *   to provide a responsive video experience. See the _template.php
21 *   file for examples of embedding both types of video.
22 *
23 * @param autoplay: true/false - autoplay the video when displayed
24 *
25 * - To close the lightbox, call the function with an empty string as
26 *   the first argument
27 *
28 * - Example calls:
29 *     PAGE_LIGHTBOX.activate({"link":"eBGIQ7ZuuiU"}, false); // YouTube
30 *     PAGE_LIGHTBOX.activate([{"link":"/video/nucleus-480p.mp4","resolution":"480p"},{"link":"/video/nucleus-1080p.mp4","resolution":"1080p"}], false);
31 *
32 */
33let PAGE_LIGHTBOX = document.getElementById('videoLightbox');
34if (!PAGE_LIGHTBOX) {
35  // Create the lightbox and add it to the page
36    PAGE_LIGHTBOX = document.createElement('div');
37    PAGE_LIGHTBOX.classList.add('w-100', 'h-100', 'opacity-0', 'invisible', 'position-fixed', 'top-0', 'start-0');
38    PAGE_LIGHTBOX.style.zIndex = 2000;
39    PAGE_LIGHTBOX.style.background = 'rgba(0,0,0,0.7) none no-repeat scroll center center';
40    PAGE_LIGHTBOX.style.backgroundSize = '50vw';
41    PAGE_LIGHTBOX.style.transition = 'opacity 0.2s linear';
42    PAGE_LIGHTBOX.id = 'videoLightbox';
43  let div1 = document.createElement('div');
44      div1.classList.add('video', 'd-table', 'w-100', 'h-100', 'opacity-0', 'position-absolute', 'top-0', 'start-0');
45      div1.style.transition = 'opacity 0.2s linear';
46    let div2 = document.createElement('div');
47        div2.classList.add('d-table-cell', 'text-center', 'align-middle');
48      div1.appendChild(div2);
49    let figure = document.createElement('figure');
50        figure.classList.add('position-absolute');
51        figure.style.top = figure.style.right = '1.5rem';
52        figure.style.width = figure.style.height = '2.4rem';
53        figure.title = 'Close video';
54      let img = document.createElement('img');
55          img.src = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="%23fff"><path d="M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z"/></svg>';
56          img.alt = 'Close';
57          img.setAttribute('role', 'button');
58          img.classList.add('d-block', 'w-100', 'h-100');
59        figure.appendChild(img);
60      div1.appendChild(figure);
61    PAGE_LIGHTBOX.appendChild(div1);
62  document.body.appendChild(PAGE_LIGHTBOX);
63}
64PAGE_LIGHTBOX.container = document.querySelector('#videoLightbox .video');
65PAGE_LIGHTBOX.player = false;
66PAGE_LIGHTBOX.video = false;
67PAGE_LIGHTBOX.addEventListener('click', function() { this.activate('', false); }, false);
68PAGE_LIGHTBOX.innerDimensions = function() {
69  if (window.innerHeight) {
70    return [window.innerWidth, window.innerHeight];
71  } else if (document.documentElement && document.documentElement.clientHeight) {
72    return [document.documentElement.clientWidth, document.documentElement.clientHeight];
73  } else if (document.body)
74    return [document.body.clientWidth, document.body.clientHeight];
75  return [0, 0];
76};
77PAGE_LIGHTBOX.setBackground = function() {
78  let vport = this.innerDimensions();
79  if (vport[0] < 428) {
80    this.style.backgroundImage = 'url(' + PAGE_DOWNROOT + 'img/evertz/loading.214px.webp)';
81  } else if (vport[0] < 856) {
82    this.style.backgroundImage = 'url(' + PAGE_DOWNROOT + 'img/evertz/loading.428px.webp)';
83  } else this.style.backgroundImage = 'url(' + PAGE_DOWNROOT + 'img/evertz/loading.856px.webp)';
84};
85PAGE_LIGHTBOX.activate = function(video, autoplay) {
86
87  // This is a request to raise the lightbox
88  if (video) {
89
90    this.classList.remove('opacity-0', 'invisible');
91    document.documentElement.style.overflow = 'hidden';
92
93    // A new video is being set
94    if (JSON.stringify(video) != this.video) {
95
96      this.container.classList.add('opacity-0');
97
98      this.video = JSON.stringify(video);
99
100      // Empty the video container
101      let vidbox = document.querySelector('#videoLightbox .video > div');
102      while (vidbox.firstChild) vidbox.removeChild(vidbox.firstChild);
103
104      if (typeof video != 'object') {
105        console.log('[lightboxVideo]: Function expects an object, non-object passed.');
106        return false;
107      }
108
109      if (!Array.isArray(video)) video = [video];
110
111      // This is a YouTube video
112      if (typeof video[0].link == 'string' && video[0].link.match(/^[0-9a-zA-Z_-]{11}$/)) {
113
114        this.player = document.createElement('iframe');
115        this.player.classList.add('ytvideo');
116        this.player.title = 'YouTube video player';
117        this.player.src = '//www.youtube.com/embed/' + video[0].link + '?enablejsapi=1' + ((autoplay) ? '&autoplay=1' : '');
118        this.player.setAttribute('frameborder', '0');
119        this.player.setAttribute('allow', 'autoplay');
120        this.player.setAttribute('allowfullscreen', true);
121
122        // Get aspect ratio of video
123        let http = getHTTPObject();
124        let uri = 'https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=' + video[0].link
125        http.open('GET', uri, true);
126        http.onreadystatechange = function() {
127          if (http.readyState == 4) {
128            let response = JSON.parse(http.responseText);
129            if (response.width && response.height) {
130              PAGE_LIGHTBOX.player.aspect = response.width / response.height;
131              if (!PAGE_LIGHTBOX.classList.contains('opacity-0'))
132                PAGE_LIGHTBOX.player.resize();
133            } else console.log('[lightboxVideo]: Could not read aspect ratio from www.youtube.com.');
134          }
135        };
136        http.send(null);
137
138
139      // Assume this is a video URL object or an array of such
140      } else {
141
142        this.player = document.createElement('video');
143        this.player.title = 'HTML5 video player';
144        if (autoplay) this.player.setAttribute('autoplay', true);
145        this.player.setAttribute('controls', true);
146        this.player.setAttribute('disablepictureinpicture', true);
147        this.player.setAttribute('controlslist', 'nodownload');
148
149        // An array of objects such as:
150        // [
151        //   { 'link': '...', 'resolution': '480p' },
152        //   { 'link': '...', 'resolution': '1080p' }
153        // ]
154
155        // Simple sanity check
156        for (let x; x < video.length; x++) {
157          if (!video[0].link || !video[0].resolution) {
158            console.log('[lightboxVideo]: Video object is missing a "link" or "resolution" value.');
159            return false;
160          }
161        }
162
163        // Sort the array so the largest resolution is last
164        video.sort(function(a, b) {
165          if (a.resolution == b.resolution) return 0;
166          return (parseInt(a.resolution) - parseInt(b.resolution));
167        });
168
169        // Since W3C has removed support for the media attribute on
170        // <source> elements, we cannot serve videos responsively by
171        // screen size. Remove all videos with the media attribute so
172        // only the largest video remains. There is a campaign on to
173        // restore the media attribute so this code might be removed
174        // someday.
175        // let source = document.createElement('source');
176        //     source.src = video[video.length - 1].link;
177        // this.player.appendChild(source);
178
179        for (let x = 0, source; x < video.length; x++) {
180          source = document.createElement('source');
181          source.src = video[x].link;
182          if (x < video.length -1) { // Don't limit the largest video
183            switch (video[x].resolution) {
184              case '320p':
185                source.setAttribute('media', 'all and (max-width:576px)');
186                break;
187              case '480p':
188                source.setAttribute('media', 'all and (max-width:768px)');
189                break;
190              case '720p':
191                source.setAttribute('media', 'all and (max-width:992px)');
192                break;
193              case '1080p':
194                source.setAttribute('media', 'all and (max-width:1440px)');
195                break;
196              case '2160p':
197                source.setAttribute('media', 'all and (max-width:2880px)');
198                break;
199              case '4K': // ?
200            }
201          }
202          this.player.appendChild(source);
203        }
204
205        this.player.appendChild(document.createTextNode('Your browser doesn\'t support the HTML5 video tag.'));
206
207      }
208
209      // Set default aspect ratio of 16:9
210      this.player.aspect = 1.77777778;
211
212      this.player.resize = function() {
213        let vport = PAGE_LIGHTBOX.innerDimensions();
214        if ((vport[0] / vport[1]) > this.aspect) { // Height is limiting
215          let h = Math.round(vport[1] * .8);
216          this.setAttribute('height', h.toString());
217          this.setAttribute('width', Math.round(h * this.aspect).toString());
218        } else { // Width is limiting
219          let w = Math.round(vport[0] * .8);
220          this.setAttribute('width', w.toString());
221          this.setAttribute('height', Math.round(w / this.aspect).toString());
222        }
223      }
224      this.player.loaded = function() {
225        PAGE_LIGHTBOX.container.classList.remove('opacity-0');
226        if (PAGE_LIGHTBOX.player.nodeName == 'VIDEO')
227          PAGE_LIGHTBOX.player.aspect = PAGE_LIGHTBOX.player.videoWidth / PAGE_LIGHTBOX.player.videoHeight;
228        PAGE_LIGHTBOX.player.resize();
229        this.removeEventListener('load', this.loaded, false);
230      };
231      this.player.addEventListener('load', this.player.loaded, false);
232      this.player.addEventListener('loadeddata', this.player.loaded, false);
233
234      vidbox.appendChild(this.player);
235
236    // Same video is requested, just raise the lightbox
237    } else {
238      this.classList.remove('opacity-0', 'invisible');
239      document.documentElement.style.overflow = 'hidden';
240    }
241
242
243  // No video specified, so lower the lightbox
244  } else {
245    this.classList.add('opacity-0', 'invisible');
246
247    // Stop the player
248    if (this.player.nodeName != 'VIDEO') {
249      let oldsrc = this.player.src;
250      this.player.setAttribute('src', oldsrc.replace(/autoplay=1/, 'autoplay=0'));
251    } else this.player.pause();
252    document.documentElement.style.overflow = '';
253  }
254};
255
256PAGE_LIGHTBOX.setBackground();
257window.addEventListener('resize', function() {
258  if (PAGE_LIGHTBOX.player) PAGE_LIGHTBOX.player.resize();
259  PAGE_LIGHTBOX.setBackground();
260}, false);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.