PageSourceSearch

https://www.rvrhs.com/apps-shared/en-commons.js?acn=406966

js rvrhs.com collected 2026-09-25 00:09:21 UTC 52,265 bytes, 1,439 lines download raw bytes

1function initENAnimateOnScroll() {
2    // console.log("Initializing Intersection Observer");
3    let observerOptions = {
4        root: null,
5        rootMargin: "0px",
6        threshold: [0.2]
7    };
8    let intersectionObserverCallback = function (entries) {
9        entries.forEach(entry => {
10            if (entry.isIntersecting) {
11                let clist = entry.target.classList;
12                for (let c = 0; c < clist.length; c++) {
13                    let thisClass = clist[c];
14                    if (thisClass.startsWith("en-aos-") && !thisClass.startsWith("en-aos-init")  && !thisClass.endsWith("-animate")
15                        && !clist.contains(thisClass + "-animate")
16                    ) {
17                        entry.target.classList.add(thisClass + '-animate');
18                        break;
19                    }
20                }
21            }
22        });
23    };
24    let intersectionObserver = new IntersectionObserver(intersectionObserverCallback, observerOptions);
25    let aosList = document.querySelectorAll('[class*="en-aos-"]');
26    for (let x = 0; x < aosList.length; x++) {
27        intersectionObserver.observe(aosList[x]);
28    }
29
30}
31
32var createElement = function (type, cssClass, innerHTML) {
33    let el = document.createElement(type);
34    if (cssClass != null) {
35        if (typeof cssClass === "string") {
36            el.classList.add(cssClass);
37        } else if (Array.isArray(cssClass)) {
38            for (let x = 0; x < cssClass.length; x++) {
39                if (cssClass[x] != null) {
40                    el.classList.add(cssClass[x]);
41                }
42            }
43        }
44    }
45    if (innerHTML != null) {
46        el.innerHTML = innerHTML;
47    }
48    return el;
49}
50
51function initPopupEl() {
52    let popWrapper = createElement("div", "en-header-popup-wrapper");
53    popWrapper.setAttribute("id", "en-header-popup-wrapper");
54    let popupBodyDiv = createElement("div", "en-header-popup-body");
55    popupBodyDiv.setAttribute("id", "en-header-popup-body");
56    let popDivClose = createElement("a", "en-public-header-popup-close");
57    popDivClose.setAttribute("id", "en-public-header-popup-close");
58    popDivClose.setAttribute("title", "close");
59    popDivClose.setAttribute("href", "javascript:__enSearchPopupHide()");
60
61    let popDivImg = createElement("img", "en-popup-close-img");
62    popDivImg.setAttribute("src", "/apps-shared/images/icons/cancel-03.svg");
63
64    let popForm = createElement("form");
65    popForm.setAttribute("action", "/apps/search/index.jsp");
66
67    let popFormInput = createElement("input");
68    popFormInput.setAttribute("id", "search-field");
69    popFormInput.setAttribute("name", "q");
70    popFormInput.setAttribute("type", "text");
71    popFormInput.setAttribute("aria-label", "Search input");
72    popFormInput.setAttribute("placeholder", "Search");
73    let q;
74    if (location.pathname == popForm.getAttribute("action") && (q = location.search.match(/q=([^&]+)/))) {
75        popFormInput.setAttribute("value", decodeURIComponent(q[1]).replaceAll("+", " "));
76    }
77
78    let popupBackdrop = createElement("div");
79    popupBackdrop.setAttribute("id", "en-header-popup-backdrop");
80    popupBackdrop.setAttribute("onClick", "__enSearchPopupHide()")
81
82    popDivClose.appendChild(popDivImg);
83    popForm.appendChild(popFormInput);
84    //popForm.appendChild(popFormImage);
85    popupBodyDiv.appendChild(popForm);
86    popupBodyDiv.appendChild(popDivClose);
87    popWrapper.appendChild(popupBodyDiv);
88    document.getElementsByTagName("body")[0].appendChild(popupBackdrop);
89    document.getElementsByTagName("body")[0].appendChild(popWrapper);
90}
91
92function checkInitPopEl() {
93    var popupWrapperCheck = document.getElementById("en-header-popup-wrapper");
94    if (popupWrapperCheck == null) {
95        initPopupEl();
96    }
97}
98
99function isEmpty(val) {
100    return val === undefined || val === null || val === '' || (Array.isArray(val) && val.length === 0);
101}
102
103// Display search
104function _enSearchPopupToggle() {
105    checkInitPopEl();
106    var popupWrapper = document.getElementById("en-header-popup-wrapper");
107    if (!isEmpty(popupWrapper)) {
108        if (popupWrapper.style.display === "block") {
109            popupWrapper.style.display = "none";
110            document.getElementById("en-header-popup-backdrop").classList.remove("en-header-popup-backdrop");
111        } else {
112            document.getElementById("en-header-popup-backdrop").classList.add("en-header-popup-backdrop");
113            popupWrapper.style.display = "block";
114            popupWrapper._searchButton = document.activeElement;
115            var searchInput = popupWrapper.querySelector("#search-field");
116            if (searchInput) {
117                searchInput.focus();
118            }
119        }
120    }
121}
122
123//Hide popup
124function __enSearchPopupHide() {
125    var popupWrapper = document.getElementById("en-header-popup-wrapper");
126    if (!isEmpty(popupWrapper)) {
127        popupWrapper.style.display = "none";
128        if (popupWrapper._searchButton) {
129            popupWrapper._searchButton.focus();
130        }
131    }
132    if (document.getElementById("en-header-popup-backdrop") != null) {
133        document.getElementById("en-header-popup-backdrop").classList.remove("en-header-popup-backdrop");
134    }
135    deletePopWrapperElement();
136}
137
138function deletePopWrapperElement() {
139    var popupWrapper = document.getElementById("en-header-popup-wrapper");
140    var popupBackdrop = document.getElementById("en-header-popup-backdrop");
141    var mainBody = document.getElementsByTagName("body")[0];
142    (!isEmpty(popupWrapper))
143    {
144        if (popupWrapper != null) {
145            mainBody.removeChild(popupWrapper);
146        }
147        if (popupBackdrop != null) {
148            mainBody.removeChild(popupBackdrop);
149        }
150    }
151}
152
153var GoogleTranslate = {
154
155    includedLanguageKeys: ['en'],
156
157    includedLanguageNames: ['English'],
158
159    excludedLanguageKeys: [],
160
161    excludedLanguageNames: [],
162
163    PLACEHOLDER_ELEMENT_ID: "googleTranslate",
164
165    WRAPPER_ELEMENT_ID: "googleTranslateElementWrapper",
166
167    init: function () {
168
169        let aContainer = document.getElementById("en-public-header-translate");
170        if (aContainer == null) {
171            return;
172        }
173        let selEl = document.createElement("select");
174        selEl.setAttribute("id", GoogleTranslate.PLACEHOLDER_ELEMENT_ID);
175        selEl.setAttribute("aria-label", "Select translation language");
176        aContainer.appendChild(selEl);
177
178        let languages = aContainer.getAttribute("en-google-translate");
179        if (languages == null || languages === "") {
180            console.log("en-google-translate property can not be empty or null for translate wrapper");
181            return;
182        }
183        if (languages.startsWith('incl:')) {
184            GoogleTranslate.extractInclude(languages);
185        } else if (languages.startsWith('all')) {
186            GoogleTranslate.includedLanguageKeys = [];
187        } else if (languages.startsWith('excl:')) {
188            languages = languages.substring(5);
189            let langArr = languages.split(",");
190            for (let i = 0; i < langArr.length; i++) {
191                let langCodeNameArr = langArr[i].split("/");
192                if (langCodeNameArr.length > 1) {
193                    let key = langCodeNameArr[0].trim();
194                    let val = langCodeNameArr[1].trim();
195                    GoogleTranslate.excludedLanguageKeys.push(key);
196                    GoogleTranslate.excludedLanguageNames.push(val);
197                } else if (langCodeNameArr.length === 1) {
198                    let key = langCodeNameArr[0].trim();
199                    GoogleTranslate.excludedLanguageKeys.push(key);
200                }
201
202            }
203        } else {
204            GoogleTranslate.extractInclude("incl:".concat(languages)
204);
205        }
206
207        let placeHolderEle = document.getElementById(GoogleTranslate.PLACEHOLDER_ELEMENT_ID);
208        if (placeHolderEle == null) {
209            return;
210        }
211        placeHolderEle.onchange = function () {
212            window.open("http://translate.google.com/translate?u=" + escape(location.href) + "&langpair=en%7C" + this.value + "&hl=en&ie=UTF-8&oe=UTF-8&prev=%2Flanguage_tools");
213        };
214
215        for (var i = 0; i < GoogleTranslate.includedLanguageNames.length; i++) {
216            var option = document.createElement("option");
217            option.value = GoogleTranslate.includedLanguageKeys[i];
218            option.innerText = unescape(GoogleTranslate.includedLanguageNames[i].replace(/[+]/g, " "));
219            placeHolderEle.appendChild(option);
220        }
221
222        var wrapperEle = document.createElement("div");
223        wrapperEle.setAttribute("id", GoogleTranslate.WRAPPER_ELEMENT_ID);
224        // select element= placeholder
225        placeHolderEle.parentNode.insertBefore(wrapperEle, placeHolderEle);
226
227        var googleTranslateScriptEle = document.createElement("script");
228        try {
229            googleTranslateScriptEle.src = "//translate.google.com/translate_a/element.js?cb=GoogleTranslate.onGoogleTranslateElementInit";
230        } catch (e) {
231            console.log(e);
232        }
233        document.getElementsByTagName("head")[0].appendChild(googleTranslateScriptEle);
234    },
235    extractInclude: function (languages) {
236        languages = languages.substring(5);
237        let langArr = languages.split(",");
238        for (let i = 0; i < langArr.length; i++) {
239            let langCodeNameArr = langArr[i].split("/");
240            if (langCodeNameArr.length > 1) {
241                let key = langCodeNameArr[0].trim();
242                let val = langCodeNameArr[1].trim();
243                GoogleTranslate.includedLanguageKeys.push(key);
244                GoogleTranslate.includedLanguageNames.push(val);
245            } else if (langCodeNameArr.length === 1) {
246                let key = langCodeNameArr[0].trim();
247                GoogleTranslate.includedLanguageKeys.push(key);
248            }
249        }
250    },
251
252
253    onGoogleTranslateElementInit: function googleTranslateElementInit() {
254        var placeHolderEle = document.getElementById(GoogleTranslate.PLACEHOLDER_ELEMENT_ID);
255        var wrapperEle = document.getElementById(GoogleTranslate.WRAPPER_ELEMENT_ID);
256
257        var origHtmlEleStyle = document.documentElement.getAttribute("style");
258        var origBodyEleStyle = document.body.getAttribute("style");
259
260        placeHolderEle.onchange = null;
261        if (GoogleTranslate.excludedLanguageKeys.length !== 0) {
262            new google.translate.TranslateElement({
263                excludedLanguages: GoogleTranslate.excludedLanguageKeys.join(","),
264                autoDisplay: false
265            }, GoogleTranslate.WRAPPER_ELEMENT_ID);
266        } else if (GoogleTranslate.includedLanguageKeys.length !== 0) {
267            new google.translate.TranslateElement({
268                includedLanguages: GoogleTranslate.includedLanguageKeys.join(","),
269                autoDisplay: false
270            }, GoogleTranslate.WRAPPER_ELEMENT_ID);
271        } else {
272            new google.translate.TranslateElement({
273                autoDisplay: false
274            }, GoogleTranslate.WRAPPER_ELEMENT_ID);
275        }
276
277        setTimeout(function () {
278            document.documentElement.setAttribute("style", origHtmlEleStyle ? origHtmlEleStyle : "");
279            document.body.setAttribute("style", origBodyEleStyle ? origBodyEleStyle : "");
280            var votingForm = document.getElementById("goog-gt-votingForm");
281            if (votingForm) {
282                votingForm.setAttribute("aria-hidden", "true");
283                votingForm.querySelectorAll("input").forEach(function (input) {
284                    input.setAttribute("type", "hidden");
285                });
286            }
287        }, 1);
288
289        var selectEle = wrapperEle.getElementsByTagName("select")[0];
290        placeHolderEle.parentNode.insertBefore(selectEle, placeHolderEle);
291
292        selectEle.setAttribute("id", "googleTranslate");
293        selectEle.className = " skiptranslate ";
294        selectEle.setAttribute("aria-label", "Select translation language");
295        selectEle.setAttribute("onfocus", "GoogleTranslate.focused(this)");
296        selectEle.setAttribute("onblur", "GoogleTranslate.blurred(this)");
297        selectEle.setAttribute("tabindex", "0");
298
299        wrapperEle.parentNode.removeChild(document.getElementById(GoogleTranslate.WRAPPER_ELEMENT_ID));
300
301        placeHolderEle.parentNode.removeChild(placeHolderEle);
302    },
303
304    focused: function (gSelect) {
305        var parent = gSelect.parentNode;
306        if (parent.id != "preGoogle") return;
307        parent.setAttribute("class", "aria-focus");
308        parent.setAttribute("style", "outline: 3px solid #3091ff!important;outline: 5px auto -webkit-focus-ring-color!important;outline: 5px auto -moz-focus-ring-color!important;");
309    },
310
311    blurred: function (gSelect) {
312        var parent = gSelect.parentNode;
313        if (parent.id != "preGoogle") return;
314        parent.setAttribute("class", "");
315        parent.setAttribute("style", "");
316    },
317
318    onReady: function (timeout) {
319        setTimeout(function () {
320            var selectEle = document.getElementById(GoogleTranslate.PLACEHOLDER_ELEMENT_ID);
321            if (selectEle.options.length > 0 && !selectEle.options[0].value) {
322                selectEle.options[0].innerText = "Google Translate";
323            }
324        }, timeout);
325    },
326
327    isLoaded: function () {
328        return true;
329    }
330}
331var Search = {
332    initSearchInputComponent: function () {
333        let inputTextSearch = document.getElementsByClassName("en-public-header-search-Inpt")[0];
334        if (inputTextSearch == null) {
335            return;
336        }
337        inputTextSearch.setAttribute("value", "Search")
338        inputTextSearch.setAttribute("onClick", "if (this.value=='Search') this.value='';");
339        inputTextSearch.setAttribute("onBlur", "if (this.value=='') this.value='Search';");
340        inputTextSearch.addEventListener("keypress", (event) => {
341            if (event.keyCode === 13) {
342                event.preventDefault();
343                Search.initForm(inputTextSearch.value);
344            }
345        });
346
347        let inputTextSearchImg = document.getElementsByClassName("en-search-wrapper-input-type")[0].querySelector('img');
348        if (inputTextSearchImg == null) {
349            return;
350        }
351        inputTextSearchImg.setAttribute("onclick", "Search.inputTextSearchImg()");
352
353    },
354    initForm: function (val) {
355        let inputTextDiv = createElement("div");
356        let inputForm = createElement("form");
357        inputForm.setAttribute("action", "/apps/search/index.jsp");
358
359        let inputTextForm = createElement("input");
360        inputTextForm.value = val;
361        inputTextForm.setAttribute("id", "search-field");
362        inputTextForm.setAttribute("name", "q");
363        inputTextForm.setAttribute("type", "text");
364        inputTextForm.setAttribute("aria-label", "Search input");
365        inputTextForm.setAttribute("placeholder", "Search");
366        inputForm.appendChild(inputTextForm);
367        inputTextDiv.appendChild(inputForm);
368        document.getElementsByTagName("body")[0].appendChild(inputTextDiv);
369        inputForm.submit();
370        document.getElementsByTagName("body")[0].removeChild(inputTextDiv);
371    },
372    inputTextSearchImg: function () {
373        let inputTextSearch = document.getElementsByClassName("en-public-header-search-Inpt")[0];
374        if (inputTextSearch == null) {
375            return;
376        }
377        Search.initForm(inputTextSearch.value);
378    }
379}
380
381
382let ENMarqueeModule = {
383    _config: {
384        getUniqueClassName: function () {
385            return "en-" + Math.floor(Math.random() * 1000) + "-marquee-module";
386        },
387        defaultContent: `{"text":"Marquee's content is missing.","delay":50}`,
388        speed: 18,
389        speedUnit: 'ms',
390    },
391
392    init: function () {
393        let marqueeList = document.querySelectorAll(".en-marquee-module");
394        marqueeList.forEach(marquee => {
395            this.createMarquee(marquee);
396        })
397    },
398
399
400    cleanInnerHtml: function (text) {
401        // Remove leading and trailing line breaks and tabs
402        if (text) return text.replace(/^\s+|\s+$/g, '');
403        return text;
404    },
405
406    resolveMarqueeJson: function (marquee) {
407        let props;
408        try {
409            const hiddenMarquee = marquee.querySelector('enmarquee');
410            if (hiddenMarquee) {
411                props = JSON.parse(hiddenMarquee.innerHTML);
412                hiddenMarquee.remove();
413            } else {
414                props = JSON.parse(marquee.innerHTML);
415            }
416            if (typeof props === 'string') {
417                return {text: this.cleanInnerHtml(props), speed: this._config.speed, speedUnit: this._config.speedUnit};
418            }
419            try {
420                props.speed = Number(props.delay);
421            } catch (e) {
422                props.speed = 18;
423            }
424            props.speedUnit = this._config.speedUnit;
425        } catch (e) {
426            // console.error(e);
427            props = {
428                text: marquee.innerHTML.trim(),
429                speed: this._config.speed,
430                speedUnit: this._config.speedUnit,
431            };
432            let speed = marquee.getAttribute("speed");
433            if (speed && /^\d+$/.test(speed)) {
434                props.speed = speed;
435                props.speedUnit = 's';
436            }
437        }
438        return props;
439    },
440
441    createMarquee: function (marquee) {
442        if (!marquee) return;
443        if (!marquee.innerHTML || marquee.innerHTML.trim().length === 0) {
444            marquee.innerHTML = ENMarqueeModule._config.defaultContent;
445        }
446        let props = this.resolveMarqueeJson(marquee);
447        if (!props || !props.text || props.text.trim().length === 0){
448            console.error("Marquee Content is empty. Marquee will be hidden. ");
449            return;
450        }
451        marquee.innerText = "";
452        marquee.style.display = "block";
453
454        let uniqueClassName = ENMarqueeModule._config.getUniqueClassName();
455        marquee.classList.add(uniqueClassName);
456
457        let textWrapper = document.createElement("div");
458        textWrapper.classList.add("en-marquee-module-content-wrapper");
459        let textP = document.createElement("p");
460        textP.classList.add("en-marquee-module-content");
461        this.log(props)
462        textP.innerHTML = props.text.trim();
463        textP.setAttribute("speed", props.speed);
464        textP.setAttribute("speed-unit", props.speedUnit);
465        textWrapper.appendChild(textP);
466        marquee.appendChild(textWrapper);
467
468        this.createPopup(marquee, uniqueClassName, props);
469        this.setMarqueeSpeed(textWrapper, textP);
470    },
471
472    modifySpeed: function () {
473        let marqueeContentList = document.querySelectorAll(".en-marquee-module-content");
474        marqueeContentList.forEach(marqueeContent => {
475            this.setMarqueeSpeed(marqueeContent.parentElement, marqueeContent)
476        })
477    },
478
479    setMarqueeSpeed: function (wrapper, textP) {
480        let contentWidth = textP.clientWidth;
481        let boxWidth = wrapper.offsetWidth + contentWidth;
482        let speed = textP.getAttribute("speed");
483        let speedUnit = textP.getAttribute("speed-unit");
484        if (!speed) {
485            speed = this._config.speed;
486        }
487        if (this._config.speedUnit === speedUnit) {
488            let duration = boxWidth * speed;
489            textP.style.cssText += " animation-duration: " + duration + "ms";
490        } else {
491            let duration = boxWidth / speed;
492            textP.style.cssText += " animation-duration: " + duration + "s";
493        }
494    },
495
496    replacePopUp: function () {
497        let marqueeWrapperList = document.querySelectorAll(".en-marquee-module");
498        marqueeWrapperList.forEach(wrapper => {
499            wrapper.classList.remove("popup-top");
500            wrapper.classList.remove("popup-bottom");
501            let innerHeight = window.innerHeight;
502            let bottom = wrapper.getBoundingClientRect().bottom;
503            let popUpHeight = 0;
504            for (let child of wrapper.children) {
505                if (child.classList.contains('en-marquee-popup-wrapper')) {
506                    popUpHeight = child.offsetHeight;
507                    break;
508                }
509            }
510            let wrapperHeight = bottom + popUpHeight + 15;
511            if (wrapperHeight >
511 innerHeight) {
512                wrapper.classList.add("popup-top");
513            } else {
514                wrapper.classList.add("popup-bottom");
515            }
516        })
517
518    },
519
520    createPopup: function (marquee, uniqueClassName, props) {
521        let targetParent = uniqueClassName;
522        let popupWrapper = document.createElement("div");
523        popupWrapper.classList.add("en-marquee-popup-wrapper");
524
525        let popupIcon = document.createElement("span");
526        popupIcon.classList.add("en-marquee-popup-icon");
527        popupWrapper.appendChild(popupIcon);
528
529        let popupIconBorders = document.createElement("span");
530        popupIconBorders.classList.add("en-marquee-popup-icon-borders");
531        popupWrapper.appendChild(popupIconBorders);
532
533        let marqueePopup = document.createElement("div");
534        marqueePopup.classList.add("en-marquee-popup");
535
536        let buttonsWrapper = document.createElement("div");
537        buttonsWrapper.classList.add("en-marquee-tooltip-buttons");
538
539        let pauseButton = document.createElement("button");
540        pauseButton.tabIndex = 0;
541        pauseButton.title = "Pause Scrolling Marquee";
542        pauseButton.onclick = function (e) {
543            ENMarqueeModule.toggleMarqueePopup(e, targetParent);
544        };
545        pauseButton.setAttribute('aria-pressed', 'false');
546        pauseButton.setAttribute('aria-label', 'Pause Scrolling Marquee');
547        pauseButton.classList.add("en-marquee-tooltip-pause-button");
548        pauseButton.innerText = "Pause";
549        buttonsWrapper.appendChild(pauseButton);
550
551        let playButton = document.createElement("button");
552        playButton.tabIndex = 0;
553        playButton.title = "Resume Scrolling Marquee";
554        playButton.onclick = function (e) {
555            ENMarqueeModule.toggleMarqueePopup(e, targetParent);
556        };
557        playButton.setAttribute('aria-pressed', 'true');
558        playButton.setAttribute('aria-label', 'Resume Scrolling Marquee');
559        playButton.classList.add("en-marquee-tooltip-play-button");
560        playButton.innerText = "Play";
561        buttonsWrapper.appendChild(playButton);
562
563        marqueePopup.appendChild(buttonsWrapper);
564
565        let popUpText = document.createElement("div");
566        popUpText.classList.add("en-marquee-popup-text");
567        popUpText.setAttribute('aria-hidden', 'true');
568        popUpText.innerHTML = props.text;
569        marqueePopup.appendChild(popUpText);
570        popupWrapper.appendChild(marqueePopup);
571        marquee.appendChild(popupWrapper);
572
573        ENMarqueeModule.modifySpeed();
574        ENMarqueeModule.replacePopUp();
575    },
576
577    toggleMarqueePopup: function (e, uniqueClassName) {
578        let animationCssClass = "pause-animation";
579        let marqueeContent = document.querySelector('.' + uniqueClassName + ' .en-marquee-module-content');
580        const marquee = document.querySelector("." + uniqueClassName);
581        if (marqueeContent) {
582            if (e.target.classList.contains('en-marquee-tooltip-pause-button')) {
583                marqueeContent.classList.add(animationCssClass);
584                marquee.classList.add("animation-paused");
585            } else {
586                marqueeContent.classList.remove(animationCssClass);
587                marquee.classList.remove("animation-paused");
588            }
589        }
590        ENMarqueeModule.removePressedAttribute(uniqueClassName);
591        e.target.setAttribute('aria-pressed', true)
592    },
593
594    removePressedAttribute: function (uniqueClassName) {
595        let buttons = document.querySelectorAll('.' + uniqueClassName + ' .en-marquee-tooltip-buttons button');
596        buttons.forEach(button => {
597            button.setAttribute('aria-pressed', false)
598        });
599    },
600
601    log: function (e) {
602        if (this.isDebugMode()) {
603            console.error(e);
604        }
605    },
606
607    isDebugMode: function () {
608        const queryString = window.location.search;
609        const urlParams = new URLSearchParams(queryString);
610        const debugAttr = urlParams.get('debug');
611        return debugAttr && debugAttr.trim() && (debugAttr.trim().toUpperCase() === 'TRUE' || debugAttr === "1");
612    }
613}
614
615
616let ENInfiniteCarousel = {
617
618    _default: {
619        slideWidth: 300,
620        duration: 20,
621        getUniqueClassName: function () {
622            return Math.floor(Math.random() * 1000);
623        },
624        contentFormat: 'html',
625    },
626
627    allowLog: false,
628
629    log: function (data) {
630        if (ENInfiniteCarousel.allowLog || this.isDebugMode()) {
631            console.error(data);
632        }
633    },
634
635    init: function () {
636        let carouselList = document.querySelectorAll('.en-infinite-carousel');
637        carouselList.forEach(carousel => {
638            this.createCarousel(carousel);
639        });
640    },
641
642    createCarousel: function (carousel) {
643        let uniqueID = this._default.getUniqueClassName();
644        carousel.classList.add("en-" + uniqueID + "-infinite-carousel");
645
646        let track = this.initCarouselTrack(carousel);
647        carousel.setAttribute("uniqueID", uniqueID);
648
649        this.locateTrackInCarousel(carousel, track);
650
651        this.listenCarouselTrackDimension(carousel, track);
652
653        this.appendAnimationToggleButton(carousel, uniqueID);
654    },
655
656    initCarouselTrack: function (carousel) {
657        let track = document.createElement("div");
658        track.classList.add("en-infinite-carousel-track");
659
660        let duration = carousel.getAttribute('duration');
661        if (!duration) {
662            duration = this._default.duration;
663        }
664        track.style.animationDuration = duration + 's';
665
666        let contentFormat = carousel.getAttribute('content-format');
667        if (!contentFormat) {
668            contentFormat = this._default.contentFormat;
669        }
670        if (contentFormat === 'html') {
671            this.initCarouselTrackFromHTML(carousel, track);
672        } else if (contentFormat === 'json') {
673            this.initCarouselTrackFromJSON(carousel, track);
674        } else {
675            console.error("Unknown/Not Implemented  Carousel contentFormat!!");
676        }
677
678        return track;
679    },
680
681    initCarouselTrackFromJSON: function (carousel, track) {
682        let elements = JSON.parse(carousel.innerText);
683        elements.forEach(json => {
684            let image = document.createElement("img");
685            image.src = json.src;
686            image.alt = json.alt;
687            let slideItem;
688            if (json.href) {
689                slideItem = document.createElement("a");
690                slideItem.href = json.href;
691                slideItem.target = "_blank";
692            } else {
693                slideItem = document.createElement("div");
694            }
695
696            if (!json.slideWidth) {
697                json.slideWidth = this._default.slideWidth;
698            }
699            slideItem.style.width = json.slideWidth;
700            slideItem.classList.add("en-infinite-carousel-slide-item");
701            if (json.slideClass) {
702                slideItem.classList.add(json.slideClass);
703            }
704            slideItem.appendChild(image);
705            track.appendChild(slideItem);
706        });
707    },
708
709    initCarouselTrackFromHTML: function (carousel, track) {
710        let carouselContent = carousel.innerHTML;
711
712        carouselContent = carouselContent.replace((/ |\r\n|\n|\r/gm), "");
713        if (carouselContent) {
714            track.innerHTML = carousel.innerHTML;
715            return;
716        }
717
718        if (this.isDebugMode()) {
719            track.innerHTML = this.getDebugContent();
720            carousel.setAttribute('debug-mode', '')
721        }
722    },
723
724    appendAnimationToggleButton: function (carousel, uniqueID) {
725        try {
726            const toggleButtonAttr = carousel.getAttribute("animation-toggle-button");
727            if (toggleButtonAttr === undefined || toggleButtonAttr === null) {
728                return;
729            }
730
731            let animationToggleButton;
732            if (toggleButtonAttr.trim().length !== 0) {
733                const b = document.getElementById(toggleButtonAttr);
734                if (b) {
735                    animationToggleButton = b;
736                } else {
737                    console.error("Infinite Carousel Toggle Button Id is wrong. Fix animation-toggle-button value. " + toggleButtonAttr)
738                }
739            } else {
740                const controlButtons = document.createElement('div');
741                controlButtons.classList.add("en-ic-control-buttons")
742                animationToggleButton = document.createElement("button");
743                animationToggleButton.classList.add("default-style");
744                animationToggleButton.classList.add("en-ic-toggle-button");
745                animationToggleButton.title = "Toggle Carousel Animation";
746                animationToggleButton.setAttribute("aria-label", "Toggle Carousel Animation");
747                animationToggleButton.setAttribute("aria-hidden", "false");
748                controlButtons.appendChild(animationToggleButton);
749                carousel.insertAdjacentElement('afterend', controlButtons);
750            }
751
752            if (animationToggleButton) {
753                animationToggleButton.setAttribute("data-ic-id", uniqueID);
754                animationToggleButton.addEventListener('click', function (e) {
755                    carousel.classList.toggle("paused");
756                    e.currentTarget.classList.toggle("paused");
757                });
758            }
759
760            if (carousel.hasAttribute("stop-animation-on-hover")) {
761                const icId = carousel.getAttribute("uniqueID");
762                const carouselToggleButtons = document.querySelectorAll("[data-ic-id='" + icId + "']");
763
764                carousel.addEventListener('mouseenter', function (e) {
765                    carouselToggleButtons.forEach(carouselToggleButton => {
766                        carouselToggleButton.classList.add("carousel-paused");
767                    })
768                });
769
770                carousel.addEventListener('mouseleave', function (e) {
771                    carouselToggleButtons.forEach(carouselToggleButton => {
772                        carouselToggleButton.classList.remove("carousel-paused");
773                    })
774                })
775            }
776        } catch (e) {
777            console.error(e);
778        }
779    },
780
781    isDebugMode: function () {
782        const queryString = window.location.search;
783        const urlParams = new URLSearchParams(queryString);
784        const debugAttr = urlParams.get('debug');
785        return debugAttr && ( "1" === debugAttr || "true" === debugAttr.trim().toLowerCase());
786    },
787
788    getDebugContent: function () {
789        return `
790          <span>Icon PlaceHolder</span>  
791          <a href="#">Link Placeholder</a>
792          <a href="#">
793            <img src="/" alt="Image Placeholder">
794          </a>
795          <div class="coloured-box"><span>Div PlaceHolder</span>   </div> 
796          <span>Span PlaceHolder</span>
797        `
798    },
799
800    locateTrackInCarousel: function (carousel, track) {
801        this.log("Carousel-" + carousel.getAttribute("uniqueID") + " is located.")
802        carousel.innerHTML = "";
803        carousel.appendChild(track);
804        if (track.offsetWidth === 0) {
805            console.error("Carousel content is empty. It should be checked!! ");
806            return;
807        }
808        let limit = Math.ceil(carousel.offsetWidth / track.offsetWidth);
809        this.log("Number of infinite carousel is: " + limit)
810        for (let index = 0; index < limit; index++) {
811            carousel.appendChild(track.cloneNode(true));
812        }
813    },
814
815    listenCarouselTrackDimension: function (carousel, track) {
816        var enInfiniteCarouselWindowWidth = window.innerWidth;
817        window.addEventListener('resize', () => {
818            // iOS triggers resize event when scrolling.
819            if (window.innerWidth === enInfiniteCarouselWindowWidth) {
820                return;
821            }
822
823            let resizeTimeOut = carousel.getAttribute("resizeTimeOut");
824            if (resizeTimeOut) {
825                clearTimeout(resizeTimeOut);
826                carousel.removeAttribute("resizeTimeOut");
827                this.log("Carousel-" + carousel.getAttribute("uniqueID") + " timeout cleared." + resizeTimeOut);
828            }
829
830            let timeOutID = setTimeout(() => {
831                this.log(`window.innerWidth: ${window.innerWidth} - CarouselWindowWidth: ${enInfiniteCarouselWindowWidth}`)
832                enInfiniteCarouselWindowWidth = window.innerWidth;
833                ENInfiniteCarousel.locateTrackInCarousel(carousel, track);
834            }, 100);
835            carousel.setAttribute("resizeTimeOut", timeOutID);
836            this.log("Carousel-" + carousel.getAttribute("uniqueID") + " timeout ID: " + timeOutID);
837        });
838    },
839}
840
841let ENPoweredBy = {
842
843    init: function () {
844        let containerList = document.getElementsByClassName("en-powered-by");
845        if (!containerList || containerList.length === 0)
846            return;
847
848        ENPoweredBy.addBoomBoxFont();
849
850        for (let container of containerList) {
851            let link = document.createElement("a");
852            link.setAttribute("href", "https://www.educationalnetworks.net/");
853            link.setAttribute("target", "_blank");
854            link.innerHTML = '<span>powered by</span><br><span>Educational Networks</span>';
855
856            container.appendChild(link);
857        }
858    },
859
860    addBoomBoxFont: function () {
861        let boomBoxFont = document.createElement('style');
862        boomBoxFont.appendChild(document.createTextNode("\
863            @font-face {\
864                font-family: " + 'BoomBox2' + ";\
865                src: url('" + '/apps-shared/fonts/boombox2.ttf' + "') format('truetype');\
866            }\
867        "));
868
869        document.head.appendChild(boomBoxFont);
870    }
871}
872
873
874function ENParallax() {
875    const parallaxElements = [];
876
877    const initialize = () => {
878        const nodes = document.querySelectorAll('[en-parallax], .en-parallax');
879
880        nodes.forEach(el => {
881            parallaxElements.push({
882                el,
883                startSliding: el.getAttribute('start-sliding') || 'full-visible',
884                finishSliding: el.getAttribute('finish-sliding') || 'partial-invisible',
885                current: 0,
886                target: 0,
887            });
888        });
889
890        return parallaxElements.length !== 0;
891    };
892
893    const updateTargets = () => {
894        const windowHeight = window.innerHeight;
895
896        parallaxElements.forEach(parallax => {
897            const rect = parallax.el.getBoundingClientRect();
898            const parallaxHeight = rect.height;
899
900            const start = parallax.startSliding === 'partial-visible'
901                ? windowHeight
902                : windowHeight - parallaxHeight;
903
904            const finish = parallax.finishSliding === 'full-invisible'
905                ? 0
906                : -parallaxHeight;
907
908            if (rect.top > start) {
909                parallax.target = 0;
910            } else if (rect.bottom < 0) {
911                parallax.target = 100;
912            } else {
913                const progress = ((start - rect.top) / (start - finish)) * 100;
914                parallax.target = Math.min(100, Math.max(0, progress));
915            }
916        });
917    };
918
919    const animate = () => {
920        let needsUpdate = false;
921
922        parallaxElements.forEach(item => {
923            const diff = item.target - item.current;
924
925            if (Math.abs(diff) > 0.1) {
926                item.current += diff * 0.1; // lerp
927                needsUpdate = true;
928            } else if (item.current !== item.target) {
929                item.current = item.target; // snap to target
930                needsUpdate = true;
931            }
932
933            const value = item.current;
934            item.el.style.setProperty('--en-parallax-background-positionY', `${value}%`);
935            item.el.style.backgroundPositionY = `${value}%`;
936        });
937
938        if (needsUpdate) {
939            requestAnimationFrame(animate);
940        }
941    };
942
943    const onScrollOrResize = () => {
944        updateTargets();
945        requestAnimationFrame(animate);
946    };
947
948    const tryInit = () => {
949        const hasParallax = initialize();
950        if (!hasParallax) return;
951
952        window.addEventListener('scroll', onScrollOrResize, { passive: true });
953        window.addEventListener('resize', onScrollOrResize);
954        window.addEventListener('load', onScrollOrResize);
955        onScrollOrResize();
956    };
957
958    document.addEventListener('DOMContentLoaded', tryInit);
959}
960
961try {
962    ENParallax();
963} catch (e) {
964    console.error(e);
965}
966
967class EnWideScreenVideoBuilder {
968
969    constructor() {
970        let sectionList = document.querySelectorAll('.en-widescreen-video');
971        if (sectionList.length === 0) return;
972        sectionList.forEach(section => new EnWideScreenVideo(section));
973        this.importCSS();
974    }
975
976    importCSS() {
977        const cssId = 'widescreen_video';
978        if (!document.getElementById(cssId)) {
979            let head = document.getElementsByTagName('head')[0];
980            let link = document.createElement('link');
981            link.id = cssId;
982            link.rel = 'stylesheet';
983            link.type = 'text/css';
984            link.href = '/apps-shared/video/css/widescreen_video.css';
985            head.appendChild(link);
986        }
987    }
988}
989
990class EnWideScreenVideo {
991
992    section;
993    source;
994    debug = false;
995
996    settings = {
997        playsInline: true,
998        autoplay: true,
999        loop: true,
1000        muted: true,
1001        preload: "metadata",
1002        controls: false,
1003        poster: null,
1004        ariaLabel: null,
1005        'en-pauseable': true,
1006        'en-onplay-pause-others': false
1007    }
1008
1009    constructor(section) {
1010        this.section = section;
1011        this.debug = 'true' === section.getAttribute("debug");
1012        this.source = section.getAttribute("source");
1013        if (!this.source && !this.debug) {
1014            console.error("Video Source is empty/null");
1015            return
1016        } else if (this.debug) {
1017            this.source = '/apps-shared/video/testing/video.mp4';
1018        }
1019
1020        const supportsDash = window.MediaSource && MediaSource.isTypeSupported(`video/mp4; codecs="avc1.4D401E, mp4a.40.2"`);
1021        const canPlayHls = document.createElement('video').canPlayType('application/vnd.apple.mpegurl');
1022
1023        if (supportsDash || canPlayHls) {
1024            fetch(this.source, {
1025                method: 'HEAD',
1026                headers: {
1027                    accept: supportsDash ? 'application/dash+xml' : 'application/vnd.apple.mpegurl'
1028                }
1029            })
1030                .then(function (response) {
1031                    const finalDestination = response.url;
1032                    this.source = finalDestination;
1033                    this.init();
1034                    const contentType = response.headers.get('content-type');
1035                    if (contentType && contentType.indexOf('application/d
1035ash+xml') != -1) {
1036                        var dashJsScriptEle = document.createElement('script');
1037                        dashJsScriptEle.src = '/apps-shared/js/dashjs/dash.all.min.js';
1038                        dashJsScriptEle.onload = function () {
1039                            var player = dashjs.MediaPlayer().create();
1040                            if (this.video.loop) {
1041                                this.video.loop = false;
1042                                player.on(dashjs.MediaPlayer.events.PLAYBACK_ENDED, function (e) {
1043                                    this.play();
1044                                }.bind(this.video));
1045                            }
1046                            player.initialize(this.video, this.source, this.settings.autoplay);
1047                            dashJsScriptEle.remove();
1048                        }.bind(this);
1049                        document.head.insertAdjacentElement('afterend', dashJsScriptEle);
1050                    } else if (contentType && contentType.indexOf('mpegurl') != -1) {
1051                        this.video.src = this.source;
1052                    }
1053                }.bind(this))
1054                .catch(function (error) {
1055                    console.error(error);
1056                    this.init();
1057                }.bind(this));
1058        } else {
1059            this.init();
1060        }
1061        section.removeAttribute("source");
1062    }
1063
1064    init() {
1065        this.loadSettings();
1066        this.createVideo();
1067        this.createButtons();
1068    }
1069
1070    overrideConfig(key) {
1071        const value = this.section.getAttribute(key);
1072        if ('true'.toLowerCase() === value || 'false'.toLowerCase() === value) {
1073            this.settings[key] = 'true'.toLowerCase() === value;
1074        }
1075    }
1076
1077    loadSettings() {
1078        const autoplay = this.section.getAttribute("autoplay");
1079        this.settings.autoplay =  autoplay === undefined || autoplay === null || autoplay === '' || autoplay === 'true';
1080
1081        if (this.settings.autoplay) {
1082            this.section.classList.remove("paused");
1083        } else {
1084            this.section.classList.add("paused");
1085        }
1086
1087        this.overrideConfig("loop");
1088        this.overrideConfig("muted");
1089        if (this.settings.muted) {
1090            this.section.classList.add("muted");
1091        } else {
1092            this.section.classList.remove("muted");
1093        }
1094        this.overrideConfig("controls")
1095        this.overrideConfig("en-pauseable")
1096        this.overrideConfig("en-onplay-pause-others")
1097
1098        const poster = this.section.getAttribute("poster");
1099        if (poster) {
1100            this.settings.poster = poster;
1101        }
1102
1103        const preload = this.section.preload;
1104        if (preload && (preload === 'metadata' || preload === 'auto' || preload === 'none' )){
1105            this.settings.preload = preload;
1106        }
1107
1108        const ariaLabel = this.section.getAttribute("aria-label");
1109        if (ariaLabel) {
1110            this.settings.ariaLabel = ariaLabel;
1111        }
1112    }
1113
1114    createVideo() {
1115        const video = document.createElement("video");
1116        Object.keys(this.settings)
1117            .filter(key => this.settings[key] !== null)
1118            .forEach(key => video[key] = this.settings[key]);
1119        video.setAttribute("en-pauseable", this.settings["en-pauseable"]);
1120        video.setAttribute("en-onplay-pause-others", this.settings["en-onplay-pause-others"]);
1121
1122        if (this.settings.poster) {
1123            video.setAttribute("poster", this.settings.poster);
1124        }
1125
1126        if (this.source.indexOf("mpd") == -1) {
1127            video.append(this.createSourceElement());
1128        }
1129
1130        const p = document.createElement("p");
1131        p.innerHTML = 'Your browser does not support the video tag';
1132        video.append(p);
1133        this.section.append(video);
1134        this.video = video;
1135    }
1136
1137    createSourceElement() {
1138        const el = document.createElement("source");
1139        el.src = this.source;
1140        return el;
1141    }
1142
1143    createButtons() {
1144        if (this.settings.controls) {
1145            this.log("IF controls option is enabled, Extra buttons are disabled.");
1146            return;
1147        }
1148        const btnWrapper = document.createElement("div");
1149        btnWrapper.classList.add("en-video-controls");
1150        this.createPlayButton(btnWrapper);
1151        this.createMuteButton(btnWrapper);
1152        this.section.append(btnWrapper);
1153    }
1154
1155    createPlayButton(wrapper) {
1156        const btnOption = this.section.getAttribute("play-button");
1157        if (!btnOption || btnOption === "0")
1158            return;
1159        const btn = document.createElement("button");
1160        btn.title = "Toggle video play & pause";
1161        btn.setAttribute("aria-label", "Toggle video play & pause");
1162        btn.setAttribute("aria-pressed", "true");
1163
1164        btn.classList.add("play-btn");
1165        btn.classList.add("play-btn-" + btnOption);
1166
1167        btn.addEventListener("click", () => {
1168            if (this.video.paused) {
1169                this.video.play();
1170                this.log("Video is played");
1171            } else {
1172                this.video.pause();
1173                this.log("Video is paused.");
1174            }
1175        });
1176        this.video.addEventListener('play', (event) => {
1177            let p = event.target.closest('.en-widescreen-video');
1178            if (p) p.classList.remove('paused')
1179        });
1180        this.video.addEventListener('pause', (event) => {
1181            let p = event.target.closest('.en-widescreen-video');
1182            if (p) p.classList.add('paused')
1183        });
1184
1185        wrapper.append(btn);
1186    }
1187
1188
1189    createMuteButton(wrapper) {
1190        const btnOption = this.section.getAttribute("mute-button");
1191        if (!btnOption || btnOption === "0")
1192            return;
1193        const btn = document.createElement("button");
1194        btn.title = "Toggle video mute & unmute";
1195        btn.setAttribute("aria-label", "Toggle video mute & unmute");
1196        btn.setAttribute("aria-pressed", "true");
1197
1198        btn.classList.add("mute-btn");
1199
1200        btn.addEventListener("click", (e) => {
1201            this.video.muted = !this.video.muted;
1202        });
1203        this.video.addEventListener('volumechange', (event) => {
1204            let p = event.target.closest('.en-widescreen-video');
1205            if (event.target.muted) {
1206                p.classList.add('muted')
1207            } else {
1208                p.classList.remove('muted')
1209            }
1210        });
1211
1212
1213        wrapper.append(btn);
1214    }
1215    
1216    isDebugMPDMode() {
1217        const queryString = window.location.search;
1218        const urlParams = new URLSearchParams(queryString);
1219        const debugAttr = urlParams.get('debugMPD');
1220        return debugAttr && debugAttr.trim() && debugAttr.trim().toUpperCase() === 'TRUE';
1221    }
1222    
1223    log(e) {
1224        if (this.debug) {
1225            console.error(e);
1226        }
1227    }
1228
1229
1230}
1231
1232class VideoPlayOrderManager {
1233
1234    paths = ['', '/', '/index.jsp']
1235
1236    videoElements = [];
1237
1238    enableUI = false;
1239    VPOM_ID = 'vpom-id';
1240
1241    constructor() {
1242
1243        this.findVideos();
1244
1245        this.loadUriParams();
1246
1247        this.createUI();
1248        this.loadHandlers();
1249    }
1250
1251    loadUriParams() {
1252        const queryString = window.location.search;
1253        const urlParams = new URLSearchParams(queryString);
1254        const ui = urlParams.get('vpom');
1255        if (ui && ('true' === ui.toLowerCase() || '1' === ui)) {
1256            this.enableUI = true;
1257        }
1258    }
1259
1260    createUI() {
1261        if (!this.enableUI) return;
1262        const ui = document.createElement('div');
1263        ui.id = 'en-vpom';
1264        ui.classList.add("vpom")
1265        ui.style.display = 'flex';
1266        ui.innerHTML = '';
1267
1268        const wrapper = document.createElement('div');
1269        wrapper.classList.add('videos');
1270
1271        wrapper.innerHTML += `<div class="videos-header video-row">
1272                                  <span>VPOM ID</span>
1273                                  <span>Paused</span>
1274                                  <span>Muted</span>
1275                                  <span>Pauseable</span>
1276                                  <span>Pause Others</span>    
1277                              </div>`
1278        for (let i = 0; i < this.videoElements.length; i++) {
1279            const video = this.videoElements[i];
1280            const vpomId = video.getAttribute(this.VPOM_ID);
1281            wrapper.innerHTML += `
1282                    <div class="video-row video-${vpomId}">
1283                      <span>${vpomId}</span>
1284                      <span class="play-toggle">${video.paused ? '&#9208;' : '&#9654;'}</span>
1285                      <span class="mute-toggle">${video.muted ? '&#128263;' : '&#128264;'}</span>
1286                      <span>${video.getAttribute('en-pauseable')}</span>
1287                      <span >${video.getAttribute('en-onplay-pause-others')}</span>
1288                    </div>
1289              `;
1290        }
1291
1292        ui.append(wrapper);
1293
1294
1295        document.getElementsByTagName('body')[0].append(ui);
1296
1297        const cssId = 'vpom-css';
1298        if (!document.getElementById(cssId)) {
1299
1300            const link = document.createElement('link');
1301            link.id = cssId;
1302            link.rel = 'stylesheet';
1303            link.type = 'text/css';
1304            link.href = '/shared/js/en-vpom.css';
1305            link.media = 'all';
1306
1307            const head = document.getElementsByTagName('head')[0];
1308            head.appendChild(link);
1309        }
1310    }
1311
1312
1313    loadHandlers() {
1314        this.videoElements.forEach(video => {
1315            video.addEventListener('volumechange', (event) => {
1316                this.createUI();
1317            });
1318            video.addEventListener('play', (event) => {
1319                const id = event.target.getAttribute('vpom-id');
1320                const pauseOthers = event.target.getAttribute('en-onplay-pause-others');
1321                if (('false' !== pauseOthers.toLowerCase())) {
1322                    this.pauseOtherVideos(id);
1323                }
1324                this.createUI();
1325            });
1326            video.addEventListener('pause', (event) => {
1327                this.createUI();
1328            });
1329        })
1330    }
1331
1332    pauseOtherVideos(vpomId) {
1333        this.videoElements
1334            .filter(video => vpomId !== video.getAttribute('vpom-id'))
1335            .filter(video => {
1336                const pauseable = video.getAttribute('en-pauseable');
1337                return !(pauseable && ('false' === pauseable.toLowerCase() || '0' === pauseable));
1338
1339            })
1340            .filter(video => !video.paused)
1341            .forEach(video => video.pause());
1342    }
1343
1344    findVideos() {
1345        const videos = document.getElementsByTagName('video');
1346        this.videoElements = [...videos];
1347        this.videoElements.forEach(video => video.setAttribute('vpom-id', Math.floor(Math.random() * 1000)))
1348
1349        this.appendTags(`en-onplay-pause-others`)
1350        this.appendTags(`en-pauseable`)
1351    }
1352
1353    appendTags(tag) {
1354        const wrapperList = document.querySelectorAll(`[${tag}]`)
1355
1356        wrapperList.forEach(wrapper => {
1357            const videoList = wrapper.getElementsByTagName('video')
1358            const tagValue = wrapper.getAttribute(tag);
1359            Array.from(videoList).forEach(video => {
1360                if (video.hasAttribute('vpom-id') && !video.hasAttribute(`${tag}`)) {
1361                    video.setAttribute(`${tag}`, tagValue);
1362                }
1363            })
1364        })
1365    }
1366
1367
1368}
1369
1370document.addEventListener("DOMContentLoaded", function () {
1371    try {
1372        ENPoweredBy.init();
1373    } catch (err) {
1374        console.log("ENInfiniteCarousel unexcepted error .", err);
1375    }
1376
1377    try {
1378        ENInfiniteCarousel.init();
1379    } catch (err) {
1380        console.log("ENInfiniteCarousel unexcepted error .", err);
1381    }
1382
1383    try {
1384        ENMarqueeModule.init();
1385    } catch (err) {
1386        console.error("MarqueeModule has an unexpected error.", err);
1387    }
1388
1389    try {
1390        GoogleTranslate.init();
1391    } catch (err) {
1392        console.log("GoogleTranslate unexcepted error .", err);
1393    }
1394    try {
1395        initENAnimateOnScroll();
1396    } catch (err) {
1397        console.log("InitAnimations unexcepted error .", err);
1398    }
1399    try {
1400        Search.initSearchInputComponent();
1401    } catch (err) {
1402        console.log("SearchInput type unexcepted error.", err);
1403    }
1404
1405    try {
1406        new EnWideScreenVideoBuilder();
1407    } catch (err) {
1408        console.log("EnWideScreenVideo throw an error.", err);
1409    }
1410
1411    try {
1412        new VideoPlayOrderManager();
1413    } catch (err) {
1414        console.log("VideoPlayOrderManager throw an error.", err);
1415    }
1416
1417});
1418
1419["DOMContentLoaded", "resize"].forEach(event => {
1420    window.addEventListener(event, function () {
1421        try {
1422            setTimeout(function () {
1423                ENMarqueeModule.modifySpeed();
1424                ENMarqueeModule.replacePopUp();
1425            }, 0);
1426        } catch (err) {
1427            console.log("ENMarqueeModule.modifySpeed unexcepted error .", err);
1428        }
1429    })
1430});
1431
1432function debounce(func, wait) {
1433    let timeout;
1434    return function () {
1435        const context = this, args = arguments;
1436        clearTimeout(timeout);
1437        timeout = setTimeout(() => func.apply(context, args), wait);
1438    };
1439}

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.