PageSourceSearch

https://www.scientologi.no/js-static/decade-in-review-2020.js

js scientologi.no collected 2026-09-25 08:29:44 UTC 62,021 bytes, 1,454 lines download raw bytes

1var Decade2020 = (function () {
2    'use strict';
3
4    var videos = {};
5    var yearBounceEase = "M0,0 C0,0 0.03961,0.01383 0.06044,0.02525 0.07224,0.03172 0.08174,0.03797 0.08908,0.04884 0.11565,0.08812 0.13201,0.11932 0.1553,0.16553 0.17338,0.20138 0.18471,0.22343 0.19617,0.26127 0.22147,0.34475 0.23406,0.39597 0.25182,0.4841 0.28976,0.6723 0.30237,0.79391 0.33842,0.96685 0.34202,0.98412 0.34874,0.99872 0.36147,1.01005 0.44387,1.0834 0.51583,1.13969 0.60902,1.20774 0.62607,1.22019 0.64205,1.2239 0.66256,1.22993 0.67849,1.23462 0.69237,1.23935 0.70707,1.2366 0.73171,1.23199 0.75634,1.22523 0.77703,1.20851 0.86083,1.14083 1,1 1,1 ";
6    var superEaseOut = "M0,0 C0,0 0.03023,0.14845 0.04258,0.245 0.06736,0.43878 0.06665,0.56314 0.0948,0.74133 0.10068,0.77855 0.11679,0.80402 0.13613,0.83706 0.15339,0.86656 0.16906,0.88701 0.19365,0.91027 0.21969,0.9349 0.24201,0.95299 0.27397,0.96743 0.31445,0.98572 0.34869,0.99884 0.39425,1.00088 0.61529,1.0108 1,1 1,1 ";
7
8    function Decade2020() {
9        // enforces new
10        if (!(this instanceof Decade2020)) {
11            return new Decade2020();
12        }
13    }
14
15    Decade2020.prototype.Init = function () {
16        var self = this;
17        self.controller = new ScrollMagic.Controller();
18
19        self.initOdometers();
20        self.initGrowingLines();
21        self.init2020Animation();
22        self.initFloats();
23        self.initParallax();
24        self.initPlayer();
25
26
27        if (JavascriptHandler.Path == "/decade-in-review-2020/scientology-orgs/" || JavascriptHandler.Path == "/decade-in-review-2020/scientology-orgs/alt.html") {
28            self.initYears();
29            self.initOrgLogos();
30            self.initOrgOpenings();
31            self.initMapDots();
32            self.setupOrgNav();
33            self.initScroll();
34        }
35
36        self.initLinkTracking();
37    }
38
39    Decade2020.prototype.initLinkTracking = function () {
40        $('a').click(function(event) {
41            trackEvent("Link", "Clicked", $(this).attr('href'));
42        });
43        setTimeout(function(){
44            EventTracker.trackScroll();
45        }, 1000);
46    }
47
48    Decade2020.prototype.initScroll = function () {
49        var self = this;
50        $('.decade-2020--alt-link').click(function(e){
51            var index = self.activeChurchIndex || 0;
52            var $container = $('.decade-2020-opening--church-container[data-id=' + index + ']');
53            if($container.length == 0) {
54                return;
55            }
56            e.preventDefault();
57            var id = $container.attr('id');
58            var link = $(this).attr('href');
59            window.location = link + '?anchor=1#' + id;
60        });
61            var hash = window.location.hash;
62        if(!!hash) {
63            console.log('hash = ',hash);
64            setTimeout(function(){
65             window.location.hash = hash;
66            }, 1000);
67        }
68    }
69
70    Decade2020.prototype.initPlayer = function () {
71        if ($('.decade-2020--top-wrapper .video-js').length == 0) {
72            return
73        }
74        var ua = navigator.userAgent.toLowerCase();
75        var isAndroid = ua.indexOf("android") > -1;
76
77        var is_safari = navigator.userAgent.toLowerCase().indexOf('safari/') > -1;
78        var options = {
79            nativeControlsForTouch: !is_safari,
80            autoplay: true,
81            controls: true,
82            html5: {
83                nativeAudioTracks: is_safari,
84                nativeVideoTracks: is_safari,
85                hls: {
86                    withCredentials: false,
87                    overrideNative: !is_safari,
88                },
89            },
90        };
91
92
93        if (isAndroid) {
94            options = {
95                nativeControlsForTouch: false,
96                autoplay: true,
97                controls: true,
98                html5: {
99                    nativeAudioTracks: false,
100                    nativeVideoTracks: false,
101                    hls: {
102                        withCredentials: true,
103                        overrideNative: true,
104                    },
105                },
106            };
107        }
108
109        if (window.location.hash != "") {
110            options.autoplay = false;
111        }
112
113        videojs($('.decade-2020--top-wrapper .video-js')[0], options).ready(function () {
114            EventTracker.trackVideo(this);
115            this.src([{
116                "src": $('.decade-2020--top-wrapper .video-js').data("videosrc"),
117                "type": "application/x-mpegURL",
118                withCredentials: false,
119            }]);
120            if (options.autoplay) {
121                this.play();
122            }
123        });
124    }
125
126    Decade2020.prototype.initOdometers = function () {
127        var self = this;
128
129        $('[data-odomerter] counter').each(function () {
130            var $odom = $(this).css('visibility', 'hidden');
131            $odom.attr('data-number', $odom.text());
132            $odom.text('1');
133            new Odometer({
134                el: this,
135                format: $odom.closest('[data-odomerter]').data('format') || 'd',
136            });
137
138            var $el = $(this);
139            new ScrollMagic.Scene({ triggerElement: this, triggerHook: 1, reverse: false, offset: 100, duration: 1 })
140                .on("start", function (e) {
141                    $el.html($el.attr('data-number'));
142                    $el.css('visibility', 'visible');
143                })
144                // .setTween(tween)
145                // .addIndicators() // add indicators (requires plugin)
146                .addTo(self.controller);
147        });
148    }
149
150    Decade2020.prototype.init2020Animation = function () {
151        var self = this;
152
153        var tl = new TimelineMax();
154        tl.fromTo($('.year-2010'), 0.35, { scale: 5, autoAlpha: 0 }, { scale: 0.8, autoAlpha: 1 });
155        tl.to($('.year-2010'), 0.3, { scale: 1, ease: Power4.easeOut });
156
157        tl.fromTo($('.year-dash'), 0.35, { autoAlpha: 0 }, { autoAlpha: 1 }, 0.4);
158
159        tl.fromTo($('.year-2020'), 0.35, { scale: 5, autoAlpha: 0 }, { scale: 0.8, autoAlpha: 1 }, 0.4);
160        tl.to($('.year-2020'), 0.3, { scale: 1, ease: Power4.easeOut });
161
162        new ScrollMagic.Scene({ triggerElement: '#decade-2020-years-trigger', triggerHook: 1, reverse: true, offset: 100, duration: 0 })
163            .setTween(tl)
164            .setClassToggle('.decade-2020-large-title__years', 'visible')
165            // .addIndicators() // add indicators (requires plugin)
166            .addTo(self.controller);
167
168
169        $('.decade-2020-growing-underline--inside').each(function () {
170            var $el = $(this);
171            var delay = 0;
172            var offset = 30;
173
174            if (typeof $el.data('offset') != "undefined") {
175                offset = $el.data('offset');
176            }
177            if (typeof $el.data('delay') != "undefined") {
178                delay = $el.data('delay');
179            }
180
181            var tween = TweenMax.from(this, 0.7, { delay: delay, scaleX: 0 });
182
183            new ScrollMagic.Scene({ triggerElement: this, triggerHook: 1, reverse: true, offset: offset, duration: 0 })
184                .setTween(tween)
185                .setClassToggle(this, 'visible')
186                // .addIndicators() // add indicators (requires plugin)
187                .addTo(self.controller);
188        });
189    }
190
191    Decade2020.prototype.initGrowingLines = function () {
192        var self = this;
193
194        $('.decade-2020-vertical-line--inner').each(function () {
195            var $el = $(this);
196            var tween = TweenMax.from(this, 0.7, { scaleY: 0 });
197            new ScrollMagic.Scene({ triggerElement: this, triggerHook: 1, reverse: true, offset: 80, duration: 0 })
198                .setTween(tween)
199                .setClassToggle(this, 'visible')
200                // .addIndicators() // add indicators (requires plugin)
201                .addTo(self.controller);
202        });
203
204
205    }
206
207    Decade2020.prototype.initParallax = function () {
208        var self = this;
209
210        _.each($('.decade-2020---parallax'), function (element, index) {
211            var offset = element.getAttribute('data-parallax-offset');
212
213            if (self.isMobile() && element.getAttribute('data-parallax-offset-mobile')) {
214                offset = element.getAttribute('data-parallax-offset-mobile');
215            }
216
217            var tween = TweenMax.to(element.querySelector('img'), 0.5, { y: offset });
218            new ScrollMagic.Scene({ triggerElement: element, triggerHook: 0.5, reverse: true, duration: $(window).height() })
219                .setTween(tween)
220                // .addIndicators() // add indicators (requires plugin)
221                .addTo(self.controller);
222        });
223    }
224
225    Decade2020.prototype.initFloats = function () {
226        var self = this;
227
228        $('.decade-2020--float-bottom').each(function () {
229            var $el = $(this);
230            var yOffset = 50;
231            var xOffset = 0;
232            var offset = 100;
233            var duration = 0.5;
234            var delay = 0;
235            var triggerElement = this;
236
237            if (typeof $el.data('trigger') != "undefined") {
238                triggerElement = $el.data('trigger');
239            }
240            if (typeof $el.data('yoffset') != "undefined") {
241                yOffset = $el.data('yoffset');
242            }
243            if (typeof $el.data('xoffset') != "undefined") {
244                xOffset = $el.data('xoffset');
245            }
246            if (typeof $el.data('offset') != "undefined") {
247                offset = $el.data('offset');
248            }
249            if (typeof $el.data('duration') != "undefined") {
250                duration = $el.data('duration');
251            }
252            if (typeof $el.data('delay') != "undefined") {
253                delay = $el.data('delay');
254            }
255
256            var tween = TweenMax.from(this, duration, { delay: delay, y: yOffset, x: xOffset, autoAlpha: 0, ease: Power4.easeOut });
257            new ScrollMagic.Scene({ triggerElement: triggerElement, triggerHook: 1, reverse: true, offset: offset, duration: 0 })
258                .setTween(tween)
259                .setClassToggle(this, 'visible')
260                // .addIndicators() // add indicators (requires plugin)
261                .addTo(self.controller);
262        });
263
264        $('.decade-2020-scalable-bounce').each(function () {
265            var $el = $(this);
266            var scale = 1.5;
267            var offset = 100;
268            var duration = 0.5;
269
270            if (typeof $el.data('scale') != "undefined") {
271                scale = $el.data('scale');
272            }
273            if (typeof $el.data('offset') != "undefined") {
274                offset = $el.data('offset');
275            }
276            if (typeof $el.data('duration') != "undefined") {
277                duration = $el.data('duration');
278            }
279
280            var tween = TweenMax.from($el.find('.inner'), duration, { scale: scale, autoAlpha: 0, ease: Bounce.easeOut });
281            new ScrollMagic.Scene({ triggerElement: this, triggerHook: 1, reverse: true, offset: offset, duration: 0 })
282                .setTween(tween)
283                .setClassToggle(this, 'visible')
284                // .addIndicators() // add indicators (requires plugin)
285                .addTo(self.controller);
286        });
287
288        $('.decade-2020-scalable').each(function () {
289            var $el = $(this);
290            var scale = 1.5;
291            var offset = 100;
292            var duration = 0.5;
293            var triggerElement = this;
294
295            if (typeof $el.data('trigger') != "undefined") {
296                triggerElement = $el.data('trigger');
297            }
298            if (typeof $el.data('scale') != "undefined") {
299                scale = $el.data('scale');
300            }
301            if (typeof $el.data('offset') != "undefined") {
302                offset = $el.data('offset');
303            }
304            if (typeof $el.data('duration') != "undefined") {
305                duration = $el.data('duration');
306            }
307
308            var tween = TweenMax.from($el.find('.inner'), duration, { scale: scale, autoAlpha: 0, ease: Power4.easeOut });
309            new ScrollMagic.Scene({ triggerElement: triggerElement, triggerHook: 1, reverse: true, offset: offset, duration: 0 })
310                .setTween(tween)
311                .setClassToggle(this, 'visible')
312                // .addIndicators() // add indicators (requires plugin)
313                .addTo(self.controller);
314        });
315
316    }
317
318    Decade2020.prototype.isMobile = function () {
319        return $(window).width() < 767;
320    }
321
322    Decade2020.prototype.initYears = function () {
323        var self = this;
324
325        $('.decade-2020--churches-year').each(function () {
326            var $el = $(this);
327            var yOffset = 400;
328            var xOffset = 0;
329            var offset = 100;
330            var duration = 1;
331            var delay = 0;
332            var triggerElement = this;
333            var inner = $el.find('.inner');
334
335            var tl = new TimelineMax();
336            tl.from(inner, duration, { delay: delay, y: yOffset, x: xOffset, ease: Power4.easeOut });
337            tl.from(this, duration, { delay: delay, autoAlpha: 0, ease: Power4.easeOut }, 0);
338
339            new ScrollMagic.Scene({ triggerElement: triggerElement, triggerHook: 1, reverse: true, offset: offset, duration: 0 })
340                .setTween(tl)
341                .setClassToggle(this, 'visible')
342                // .addIndicators() // add indicators (requires plugin)
343                .addTo(self.controller);
344
345            var tl2 = new TimelineMax({
346                delay: 0,
347            });
348            tl2.fromTo(inner, duration * 0.7, { scale: 0.9 }, { scale: 1.4 });
349            tl2.to(inner, 5, { scale: 1, ease: CustomEase.create("custom", superEaseOut) });
350            new ScrollMagic.Scene({ triggerElement: triggerElement, triggerHook: 1, reverse: true, offset: offset, duration: 0 })
351                .setTween(tl2)
352                .on("start", function (event) {
353                    $('.decade-2020--timeline-year').removeClass('decade-2020--timeline-year__active');
354                    var id = $el.attr('id');
355                    $('[href="#' + id + '"]').parent().addClass('decade-2020--timeline-year__active');
356                    history.replaceState(null, null, ' ');
357                })
358                .on("leave", function (event) {
359                    if (event.state == "BEFORE" && event.scrollDirection == "REVERSE") {
360                        $('.decade-2020--timeline-year').removeClass('decade-2020--timeline-year__active');
361                        var year = parseInt($el.data('year')) - 1;
362                        var id = "decade-year-" + year;
363                        if (year < 2010) {
364                            id = "decade-year-map";
365                        }
366                        $('[href="#' + id + '"]').parent().addClass('decade-2020--timeline-year__active');
367
368                    }
369                    history.replaceState(null, null, ' ');
370                })
371                // .addIndicators() // add indicators (requires plugin)
372                .addTo(self.controller);
373        });
374    }
375
376    Decade2020.prototype.initOrgLogos = function () {
377        var self = this;
378
379        $('.decade-2020-vertical-logo').each(function () {
380            var $el = $(this);
381            var yOffset = 0;
382            var xOffset = 0;
383            var offset = 200;
384            var duration = 1;
385            var delay = 0;
386            var triggerElement = this;
387            var inner = $el.find('.inner');
388
389            var tl = new TimelineMax();
390            tl.from(inner, duration, { delay: delay, scale: 0.2, autoAlpha: 0, ease: Power4.easeOut }, 0);
391            tl.from(inner, 1.2, { delay: 0, rotationY: -90, ease: CustomEase.create("custom", yearBounceEase) }, 0);
392
393            new ScrollMagic.Scene({ triggerElement: this, triggerHook: 1, reverse: true, offset: offset, duration: 0 })
394                .setTween(tl)
395                .setClassToggle(this, 'visible')
396                // .addIndicators() // add indicators (requires plugin)
397                .addTo(self.controller);
398        });
399    }
400
401    Decade2020.prototype.setupOrgNav = function () {
402        var self = this;
403
404        $('.decade-2020--churches-nav__up').click(function () {
405            if (self.prevInset()) {
406                return;
407            }
408
409            if (typeof self.activeChurchIndex == "undefined") {
410                var index = 0;
411            } else {
412                var index = self.activeChurchIndex - 1;
413            }
414            if (self.scrollToIndex > -1) {
415                index = self.scrollToIndex - 1;
416            }
417
418            var $lastInset = self.getLastInsetFor(index);
419            if ($lastInset) {
420                self.scrollToElement($lastInset);
421            } else {
422                self.jumpToOrg(index);
423            }
424
425        });
426
427        $('.decade-2020--churches-nav__down').click(function () {
428            if (self.nextInset()) {
429                return;
430            }
431            if (typeof self.activeChurchIndex == "undefined") {
432                var index = 0;
433            } else {
434                var index = self.activeChurchIndex + 1;
435            }
436            if (self.scrollToIndex > -1) {
437                index = self.scrollToIndex + 1;
438            }
439            self.jumpToOrg(index);
440        });
441
442        $('.decade-2020--churches-nav__play').click(function () {
443            self.autoPlayOrgs();
444        });
445
446        this.scrollToIndex = -1;
447
448        $(document).on('mousewheel', function () {
449            if (new Date().getTime() - self.lastScrollTs > 400) {
450                if (self.lastScrollAnimation) {
451                    self.lastScrollAnimation.pause();
452                }
453                self.stopOrgAutoPlay();
454            }
455        });
456    };
457
458    Decade2020.prototype.autoPlayOrgs = function (force) {
459        var self = this;
460
461        if (this.autoplayInterval != null) {
462            self.stopOrgAutoPlay();
463            if (!force) {
464                return;
465            }
466        }
467
468        if (self.insetTimers) {
469            self.insetTimers.forEach(function (timer) {
470                clearTimeout(timer);
471            });
472        }
473        this.insetTimers = [];
474
475        // disable nav
476        $('.decade-2020--churches-nav__up, .decade-2020--churches-nav__down').addClass('decade-2020--churches-nav_disabled');
477
478        if (self.activeChurchIndex < 0) {
479            self.jumpToOrg(0);
480        } else {
481            self.jumpToOrg(self.activeChurchIndex || 0);
482        }
483
484
485        this.lastScrollTs = new Date().getTime();
486        $('.decade-2020--churches-nav__play').addClass('decade-2020--churches-nav__autoplaying');
487
488        var insetTimeout = self.insetAutoplay(self.activeChurchIndex);
489        if (insetTimeout > 0) {
490            $('.decade-2020--churches-nav__play').addClass('decade-2020-circle-progress--three');
491        }
492
493        this.autoplayInterval = setInterval(function () {
494            var index = self.activeChurchIndex + 1;
495            var $el = $(".decade-2020-opening--video[data-id=" + index + "]")
496
497            $('.decade-2020--churches-nav__play').removeClass('decade-2020--churches-nav__autoplaying');
498            $('.decade-2020--churches-nav__play').removeClass('decade-2020-circle-progress--three');
499
500            if ($el.length > 0) {
501                self.activeChurchIndex = self.activeChurchIndex + 1;
502                self.autoPlayOrgs(true);
503                $('.decade-2020--churches-nav__play').addClass('decade-2020--churches-nav__autoplaying');
504            } else {
505                self.stopOrgAutoPlay();
506            }
507
508        }, insetTimeout || 8200);
509    }
510
511    Decade2020.prototype.nextInset = function () {
512        var self = this;
513        var index = self.activeChurchIndex || 0;
514        var $container = $('.decade-2020-opening--church-container[data-id=' + index + ']');
515        var $insets = $container.find('.decade-2020-opening--insets');
516        if ($insets.length == 0) {
517            return false;
518        }
519        var $activeInset;
520        var activeInsetIndex = 0;
521        var scrollTop = $(window).scrollTop();
522
523        $insets.each(function (index, inset) {
524            var $inset = $(inset);
525            if ($inset.offset().top - 100 < scrollTop) {
526                $activeInset = $inset;
527                activeInsetIndex = index;
528            }
529        });
530
531        var $target;
532
533        // did not scroll past first inset, go to it
534        if (!$activeInset) {
535            $target = $($insets[0]);
536        } else if (activeInsetIndex + 1 >= $insets.length) {
537            return false;
538        } else {
539            $target = $($insets[activeInsetIndex + 1]);
540        }
541
542        self.scrollToElement($target);
543
544        return true;
545    }
546
547    Decade2020.prototype.prevInset = function () {
548        var self = this;
549        var index = self.activeChurchIndex || 0;
550        var $container = $('.decade-2020-opening--church-container[data-id=' + index + ']');
551        var $insets = $container.find('.decade-2020-opening--insets');
552        if ($insets.length == 0) {
553            return false;
554        }
555        var $activeInset;
556        var activeInsetIndex = -1;
557        var scrollTop = $(window).scrollTop();
558
559        $insets.each(function (index, inset) {
560            var $inset = $(inset);
561            if ($inset.offset().top - 100 < scrollTop) {
562                $activeInset = $inset;
563                activeInsetIndex = index;
564            }
565        });
566
567        var $target;
568
569        // did not scroll past first inset, go to it
570        if (activeInsetIndex == -1) {
571            // $target = $($insets[0]);
572            return false;
573        } else if (activeInsetIndex == 0) {
574            $target = $($container.find('.decade-2020-opening--img'));
575        } else if (activeInsetIndex - 1 < 0) {
576            return false;
577        } else {
578            $target = $($insets[activeInsetIndex - 1]);
579        }
580
581        self.scrollToElement($target);
582
583        return true;
584    }
585
586    Decade2020.prototype.getLastInsetFor = function (index) {
587        var $container = $('.decade-2020-opening--church-container[data-id=' + index + ']');
588        var $insets = $container.find('.decade-2020-opening--insets');
589        if ($insets.length == 0) {
590            return false;
591        }
592        return $insets.last();
593    }
594
595    Decade2020.prototype.scrollToElement = function (el) {
596        self.lastScrollAnimation = TweenMax.to(window, 2, {
597            scrollTo: {
598                y: el.offset().top - 70,
599            },
600            ease: Power4.easeInOut,
601        });
602    }
603
604    Decade2020.prototype.insetAutoplay = function (index) {
605        var self = this;
606
607        var $container = $('.decade-2020-opening--church-container[data-id=' + index + ']');
608        var $insets = $container.find('.decade-2020-opening--insets');
609        if ($insets.length == 0) {
610            return 0;
611        }
612        var totalInsetTime = 5000;
613        var insetTime = 3000;
614
615        self.insetTimers = [];
616        $insets.each(function (index, inset) {
617            var $inset = $(inset);
618            self.insetTimers.push(setTimeout(function () {
619                self.lastScrollAnimation = TweenMax.to(window, 2, {
620                    scrollTo: {
621                        y: $inset.offset().top - 70,
622                    },
623                    ease: Power4.easeInOut,
624                });
625            }, insetTime + index * totalInsetTime));
626        });
627
628        return (0.5 + $insets.length) * totalInsetTime;
629    }
630
631    Decade2020.prototype.stopOrgAutoPlay = function (index) {
632        var self = this;
633
634        if (self.insetTimers) {
635            self.insetTimers.forEach(function (timer) {
636                clearTimeout(timer);
637            });
638        }
639
640        if (self.autoplayInterval) {
641            clearInterval(self.autoplayInterval);
642            self.autoplayInterval = null;
643        }
644        $('.decade-2020--churches-nav__up, .decade-2020--churches-nav__down').removeClass('decade-2020--churches-nav_disabled');
645        $('.decade-2020--churches-nav__play').removeClass('decade-2020--churches-nav__autoplaying');
646    }
647
648    Decade2020.prototype.jumpToOrg = function (index) {
649        var self = this;
650        var $container = $(".decade-2020-opening--video[data-id=" + index + "]").closest('.decade-2020-opening--church-container');
651
652        if ($container.length == 0) {
653            return;
654        }
655
656        if (self.lastScrollAnimation) {
657            self.lastScrollAnimation.pause();
658        }
659
660        var duration = 1;
661        if (this.autoplayInterval != null) {
662            duration = 3;
663        }
664
665        self.lastScrollAnimation = TweenMax.to(window, duration, {
666            scrollTo: {
667                y: $container.find('.decade-2020--scroll-anchor').offset().top - 50,
668            },
669            ease: Power4.easeInOut,
670            onComplete: function () {
671                if (index >= 0) {
672                    self.activeChurchIndex = index;
673                }
674                self.scrollToIndex = -1;
675            }
676        });
677
678        self.scrollToIndex = index;
679        this.lastScrollTs = new Date().getTime();
680    }
681
682
683
684    Decade2020.prototype.initOrgOpenings = function () {
685        var self = this;
686
687        // lazyload videos or posters
688        document.addEventListener('lazybeforeunveil', function (e) {
689            var videoSource = e.target.getAttribute('data-opening-video');
690            if (videoSource) {
691                self.initOrgVideo(e.target);
692            }
693        });
694
695        $('.lazyloaded[data-opening-video]').each(function () {
696            self.initOrgVideo(this);
697        });
698
699        $('[data-opening-video]').each(function (index) {
700            var shouldPlayVideo = true;
701            var $el = $(this);
702            var src = $el.data('opening-video');
703
704            var $openingVideo = $el.find(".decade-2020-opening--video");
705            // var tween = TweenMax.fromTo($openingVideo, 0.5, { autoAlpha: 0 }, { autoAlpha: 1});
706
707            new ScrollMagic.Scene({ triggerElement: this, triggerHook: 1, reverse: true, offset: 500, duration: 0 })
708                // .setTween(tween)
709                .on("start", function (event) {
710                    var video = videos[src];
711                    if (video && shouldPlayVideo) {
712                        shouldPlayVideo = false;
713                        video.currentTime(0);
714                        video.play();
715                    }
716                    $el.find(".decade-2020-opening--video").addClass('decade-2020-opening--video__fixed decade-2020-opening--video__visible');
717
718                    var prevId = $el.find(".decade-2020-opening--video").data('id') - 3;
719                    $(".decade-2020-opening--video[data-id=" + prevId + "]").hide();
720
721                    self.activeChurchIndex = index;
722                })
723                .on("leave", function (event) {
724
725                    var prevId = $el.find(".decade-2020-opening--video").data('id') - 1;
726
727                    if (event.state == "BEFORE" && event.scrollDirection == "REVERSE") {
728                        if (prevId >= -1) {
729                            self.activeChurchIndex = prevId
730                        }
731                        shouldPlayVideo = true;
732                    }
733
734                    $(".decade-2020-opening--video[data-id=" + prevId + "]").addClass('decade-2020-opening--video__fixed decade-2020-opening--video__visible');
735
736                    $(".decade-2020-opening--video[data-id=" + (prevId - 2) + "]").show();
737
738                    $el.find(".decade-2020-opening--video").removeClass('decade-2020-opening--video__visible');
739                    setTimeout(function () {
740                        if (self.activeChurchIndex != index) {
741                            $el.find(".decade-2020-opening--video").removeClass('decade-2020-opening--video__fixed');
742                        }
743                    }, 1000);
744                })
745                // .addIndicators() // add indicators (requires plugin)
746                .addTo(self.controller);
747        });
748    }
749
750    Decade2020.prototype.videoBG = function () {
751        var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);;
752        return iOS == false;
753    }
754
755    Decade2020.prototype.initOrgVideo = function (el) {
756        var self = this;
757
758        var $el = $(el);
759        if ($el.find('.decade-2020-opening--video.decade-2020-opening--video__inited').length > 0) {
760            return;
761        }
762
763        var videoWrapper = el.querySelector('.decade-2020-opening--video');
764        videoWrapper.classList.add("decade-2020-opening--video__inited");
765
766        // Poster fallback
767        if (!self.videoBG()) {
768            videoWrapper.classList.add("decade-2020-opening--video-bg-only");
769            videoWrapper.setAttribute("style", "background-image: url('" + $el.data('opening-image-background') + "')");
770            $el.append(videoWrapper);
771            return;
772        }
773
774        var videoEl = document.createElement('video');
775        videoEl.setAttribute('muted', 'true');
776        $(videoWrapper).append(videoEl);
777
778        $el.append(videoWrapper);
779        var src = $el.data('opening-video');
780        videojs(videoEl, { controls: false, muted: true }).ready(function () {
781            this.src([
782                { src: src + '.webm', type: 'video/webm; codecs="vp9"' },
783                { src: src + '-h265.mp4', type: 'video/mp4; codecs="hvc1"' },
784                { src: src + '.mp4', type: 'video/mp4; codecs="avc1"' }
785            ]);
786            this.pause();
787            videos[src] = this;
788        });
789    }
790
791    Decade2020.prototype.initMapDots = function () {
792        var tl = new TimelineMax();
793        var $map = $('#decade-year-map');
794        mapDots.forEach(function (dot, index) {
795            var div = document.createElement('A');
796            div.classList.add('decade-2020--map--dot');
797            $(div).css({
798                'left': dot.x + '%',
799                'top': dot.y + '%',
800            });
801
802            var $openingDiv = $('.decade-2020-opening--button[href^="' + dot.pressrelease + '"]').closest('.decade-2020-opening--church-container');
803            if (!$openingDiv.attr('id')) {
804                console.error('map !!', dot);
805            }
806            div.setAttribute('href', '#' + $openingDiv.attr('id'));
807
808            $map.append(div);
809            tl.from(div, 1, { scale: 0.3, ease: CustomEase.create("custom", yearBounceEase) }, 0.05 * index);
810        });
811
812        loadjs.ready('bootstrapjs', function () {
813            _.each($('.decade-2020--map--dot'), function (element, index) {
814                var href = element.getAttribute('href');
815                var location = $(href).find('.decade-2020--churches-location-name-text').html();
816                if ($(href).find('.decade-2020--churches-location-name-text__alt').length > 0) {
817                    location = $(href).find('.decade-2020--churches-location-name-text__alt').html();
818                }
819                $(element).tooltip({
820                    html: true,
821                    template: '<div class="tooltip tooltip--decade-2020" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',
822                    title: location,
823                    placement: 'top',
824                });
825            });
826        });
827        loadjs(['/plugins/bootstrap/js/bootstrap.bundle.min.js?_=' + cacheId], 'bootstrapjs');
828
829    }
830
831    var mapDots = [
832        { "pressrelease": "/scientology-today/church-openings/new-church-of-scientology-opens-in-quebec-city.html", "x": 21.666666666666668, "y": 19.68051664473016 },
833        { "pressrelease": "/scientology-today/church-openings/new-branch-of-churches-of-scientology-for-europe-opens-in-brussels.html", "x": 42.432432432432435, "y": 17.00895329929168 },
834        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-los-angeles.html", "x": 5.325225225225225, "y": 28.904353134367167 },
835        { "pressrelease": "/scientology-today/church-openings/new-40000-square-foot-church-scientology-opens-las-vegas-responding-growth.html", "x": 6.846846846846847, "y": 27.873310904074845 },
836        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-mexico-city.html", "x": 8.91891891891892, "y": 39.093876954916475 },
837        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-pasadena.html", "x": 5.975675675675675, "y": 29.051415127104075 },
838        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-seattle.html", "x": 6.036036036036036, "y": 21.639663098051717 },
839        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-melbourne-australia.html", "x": 86.44144144144144, "y": 79.16732713649372 },
840        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-tampa-florida.html", "x": 15.045045045045045, "y": 32.860229148893346 },
841        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-twin-cities-minnesota.html", "x": 13.693693693693694, "y": 20.036725090788625 },
842        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-inglewood-california.html", "x": 5.025225225225225, "y": 3
8420.90108269557179 },
843        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-hamburg-germany.html", "x": 44.14414414414414, "y": 17.00895329929168 },
844        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-sacramento-california.html", "x": 5.585585585585585, "y": 24.13312222046097 },
845        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-cincinnati-ohio.html", "x": 15.81081081081081, "y": 24.667434889548662 },
846        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-orange-county.html", "x": 5.965675675675675, "y": 30.82297847254256 },
847        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-stevens-creek.html", "x": 4.818828828828829, "y": 25.52364333560713 },
848        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-denver.html", "x": 9.144144144144144, "y": 26.80468556589945 },
849        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-phoenix-arizona.html", "x": 7.837837837837838, "y": 30.90108269557179 },
850        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-buffalo-new-york.html", "x": 18.783783783783782, "y": 21.10535042896402 },
851        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-los-gatos.html", "x": 5.115315315315315, "y": 26.748477119840987 },
852        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-tel-aviv.html", "x": 52.072072072072075, "y": 31.257291141630258 },
853        { "pressrelease": "/scientology-today/church-openings/grand-opening-church-of-scientology-national-office-washington-dc.html", "x": 18.153153153153152, "y": 24.845539112577896 },
854        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-padova.html", "x": 44.5945945945946, "y": 20.749141982905556 },
855        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-cambridge.html", "x": 19.684684684684683, "y": 20.036725090788625 },
856        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-pretoria.html", "x": 50.31531531531532, "y": 70.79642865411981 },
857        { "pressrelease": "/scientology-today/church-openings/grand-opening-scientology-ideal-organization-portland.html", "x": 4.54954954954955, "y": 22.88639265925634 },
858        { "pressrelease": "/scientology-today/church-openings/grand-opening-church-of-scientology-kaohsiung.html", "x": 78.96396396396396, "y": 36.956626278565686 },
859        { "pressrelease": "/scientology-today/church-openings/grand-opening-advanced-organization-europe.html", "x": 44.5045045045045, "y": 14.87170262294089 },
860        // { "pressrelease": "/scientology-today/church-openings/grand-opening-ideal-pacifica-base.html", "x": 5.54054054054054, "y": 30.144874249513327 },
861        { "pressrelease": "/scientology-today/church-openings/grand-opening-church-of-scientology-sydney.html", "x": 87.55325225225225, "y": 76.84349335225987 },
862        { "pressrelease": "/scientology-today/church-openings/grand-opening-church-of-scientology-basel-switzerland.html", "x": 43.648648648648646, "y": 19.858620867759395 },
863        { "pressrelease": "/scientology-today/church-openings/scientology-cuts-ribbon-on-first-south-american-ideal-org-bogota-colombia.html", "x": 16.17117117117117, "y": 49.24581766758271 },
864        { "pressrelease": "/scientology-today/church-openings/epic-scientology-summer-continues-with-opening-of-tokyo-ideal-org.html", "x": 83.01801801801801, "y": 26.448477119840987 },
865        { "pressrelease": "/scientology-today/church-openings/advanced-org-saint-hill-united-kingdom-grand-opening.html", "x": 40.4054054054054, "y": 18.07757863746707 },
866        { "pressrelease": "/scientology-today/church-openings/grand-opening-church-of-scientology-milano-italy.html", "x": 44.729729729729726, "y": 23.064496882285574 },
867        { "pressrelease": "/scientology-today/church-openings/grand-opening-church-of-scientology-atlanta-georgia.html", "x": 14.36936936936937, "y": 3
8670.366770026484094 },
868        { "pressrelease": "/scientology-today/church-openings/grand-opening-church-of-scientology-budapest.html", "x": 47.7027027027027, "y": 21.10535042896402 },
869        { "pressrelease": "/scientology-today/church-openings/grand-opening-church-of-scientology-harlem.html", "x": 19.324324324324323, "y": 23.59880955137327 },
870        { "pressrelease": "/scientology-today/church-openings/advanced-org-saint-hill-anzo-grand-opening.html", "x": 87.88288288288288, "y": 75.96145112196754 },
871        { "pressrelease": "/scientology-today/church-openings/church-of-scientology-cuts-a-ribbon-on-national-affairs-office-in-the-emerald-isle.html", "x": 39.193693693693696, "y": 17.185161745350143 },
872        { "pressrelease": "/scientology-today/church-openings/grand-opening-san-diego.html", "x": 5.18018018018018, "y": 33.57264604101027 },
873        { "pressrelease": "/scientology-today/church-openings/grand-opening-auckland-new-zealand.html", "x": 91.66666666666667, "y": 80.05784825163988 },
874        { "pressrelease": "/scientology-today/church-openings/grand-opening-valley.html", "x": 4.66036036036036, "y": 29.051415127104075 },
875        { "pressrelease": "/scientology-today/church-openings/grand-opening-miami.html", "x": 15.18018018018018, "y": 34.8193756022149 },
876        { "pressrelease": "/scientology-today/church-openings/grand-opening-denmark.html", "x": 43.78378378378378, "y": 14.87170262294089 },
877        { "pressrelease": "/scientology-today/church-openings/grand-opening-dublin.html", "x": 38.593693693693696, "y": 17.18705752232091 },
878        { "pressrelease": "/scientology-today/church-openings/grand-opening-birmingham.html", "x": 40.765765765765764, "y": 15.762223738087052 },
879        { "pressrelease": "/scientology-today/church-openings/grand-opening-amsterdam.html", "x": 41.666666666666664, "y": 18.789995529584 },
880        { "pressrelease": "/scientology-today/church-openings/grand-opening-johannesburg-north.html", "x": 49.414414414414416, "y": 72.57747088441214 },
881        { "pressrelease": "/scientology-today/church-openings/grand-opening-salt-lake-city.html", "x": 7.882882882882883, "y": 26.982789788928685 },
882        { "pressrelease": "/scientology-today/church-openings/grand-opening-silicon-valley.html", "x": 4.2342342342342345, "y": 26.626581342870217 },
883        { "pressrelease": "/scientology-today/church-openings/grand-opening-perth.html", "x": 76.53153153153153, "y": 75.96145112196754 },
884        { "pressrelease": "/scientology-today/church-openings/grand-opening-orlando.html", "x": 15.27027027027027, "y": 33.92885448706874 },
885        { "pressrelease": "/scientology-today/church-openings/grand-opening-stuttgart.html", "x": 42.65765765765766, "y": 19.68051664473016 },
886        { "pressrelease": "/scientology-today/church-openings/grand-opening-detroit.html", "x": 16.8018018018018, "y": 21.283454651993253 },
887        { "pressrelease": "/scientology-today/church-openings/grand-opening-advanced-org-saint-hill-africa.html", "x": 49.414414414414416, "y": 71.68694976926598 },
888        { "pressrelease": "/scientology-today/church-openings/grand-opening-kansas-city.html", "x": 12.837837837837839, "y": 24.845539112577896 },
889        { "pressrelease": "/scientology-today/church-openings/grand-opening-central-ohio.html", "x": 16.8018018018018, "y": 24.489330666519432 },
890    ];
891
892    return Decade2020;
893}())();
894
895var Decade2020Animator = (function () {
896    'use strict';
897
898    function Decade2020Animator() {
899        // enforces new
900        if (!(this instanceof Decade2020Animator)) {
901            var animatior = new Decade2020Animator();
902            $(window).resize(function () {
903                animatior.resize();
904            });
905            return animatior;
906        }
907    }
908
909    Decade2020Animator.prototype.Init = function () {
910        var self = this;
911        
912        this.scenes = [];
913        this.fontName = 'Jost';
914        this.fontSize = 72;
915        this.textTopPadding = 55;
916        this.rectHeight = 90;
917
918        var ua = navigator.userAgent.toLowerCase();
919
920        if (ua.indexOf('safari') != -1 && ua.indexOf('chrome') == -1) {
921            this.textTopPadding = 45;
922        }
923
924        if (this.isMobile()) {
925            this.rectHeight = 60;
926            this.fontSize = 42;
927            this.textTopPadding = 35;
928        }
929
930        this.controller = new ScrollMagic.Controller();
931
932        var pixelRatio = this.getPixelRatio();
933
934
935        // text
936        this.textEl = $('.decade-2020-reveal-text');
937        this.text = this.textEl.text().trim();
938
939        // Calculate Rect Fill coordinates
940        this.textElPos = this.textEl.offset();
941        this.parentPos = this.textEl.parent().offset();
942
943        this.rectOffset = {
944            top: this.textElPos.top - this.parentPos.top + 10,
945            left: this.textElPos.left - this.parentPos.left
946        }
947
948        this.leftPos = this.textEl.find('span').offset().left;
949        this.rectWidth = this.textEl.find('span').width() + 16 * 2;
950
951        //
952
953        this.scaledFontSize = this.fontSize * pixelRatio;
954        this.scaledWindowHeight = window.innerHeight * pixelRatio;
955        this.scaledWindowWidth = window.innerWidth * pixelRatio;
956
957        this.scaledWindowHeight += this.getPinOffset() * pixelRatio;
958
959        // scale for the retina screens
960
961        this.rectOffset.top *= pixelRatio;
962        this.rectOffset.left *= pixelRatio;
963        this.leftPos *= pixelRatio;
964        this.rectWidth *= pixelRatio;
965        this.rectHeight *= pixelRatio;
966
967        // end
968
969        if (JavascriptHandler.Path == "/decade-in-review-2020/") {
970            this.initEmeterAnimation();
971            if(document.fonts && document.fonts.ready) {
972                document.fonts.ready.then(function(){
973                    self.initRevealCanvas();
974                });
975            } else {
976                self.initRevealCanvas();
977            }
978            this.initEndTitles();
979            // this.initVideoEnd();
980
981            // this is hack to correctly determine all positions before animation starts
982            var self = this;
983            if (!self.resizerInitied) {
984                self.resizerInitied = true;
985                new ScrollMagic.Scene({ triggerElement: '.decade-2020-reveal--trigger', triggerHook: 1, offset: 0, reverse: true, duration: 0 })
986                    // .setPin('.decade-2020-reveal-canvas', { pushFollowers: true })
987                    .on("start", function (event) {
988                        self.resize();
989                    })
990                    // .addIndicators() // add indicators (requires plugin)
991                    .addTo(self.controller)
992            }
993        }
994    }
995
996
997    Decade2020Animator.prototype.initVideoEnd = function () {
998        var self = this;
999        var video = $('.decade-2020--top-wrapper video')[0];
1000        video.addEventListener('ended', function () {
1001            if (!self.isMobile() && $(window).scrollTop() < 500) {
1002                $('.decade-2020--arrow-down a').click();
1003            }
1004        });
1005        $('.decade-2020--arrow-down').click(function(){
1006            for (var player in videojs.players) {
1007                if (videojs.players.hasOwnProperty(player)) {
1008                    videojs.players[player].pause();
1009                }
1010            }
1011        });
1012    }
1013
1014    Decade2020Animator.prototype.initEmeterAnimation = function () {
1015        var self = this;
1016        var emeter = '.decade-2020--emeter';
1017        var emeterPin = '.decade-2020--emeter--pin';
1018        var releasePhoto = '.decade-2020--emeter-release';
1019        var screenHeight = $(window).height();
1020
1021        // var offset = screenHeight * 0.2 * this.getPixelRatio();
1022        var offset = ($(window).height() - $(emeterPin).height()) * 0.5;
1023
1024        // pin emeter
1025        self.scenes.push(
1026            new ScrollMagic.Scene({ triggerElement: '#decade-2020--emeter-trigger', triggerHook: 0, reverse: true, offset: -offset, duration: offset + screenHeight * 0.6 })
1027                .setPin(emeterPin, { pushFollowers: true })
1028                // .addIndicators() // add indicators (requires plugin)
1029                .addTo(self.controller)
1030        );
1031
1032        // preload needle video
1033        self.scenes.push(
1034            new ScrollMagic.Scene({ triggerElement: '#decade-2020--emeter-trigger', triggerHook: 0, reverse: false, offset: -$(window).height() * 2, duration: 0 })
1035                .on("start", function (event) {
1036                    var $videoEl = $(".decade-2020--emeter-needle");
1037                    var scale = $(emeterPin).width() / 1110;
1038                    TweenMax.set($videoEl, { scale: scale });
1039
1040                    if ($videoEl.hasClass('vjs-has-started')) {
1041                        return;
1042                    }
1043
1044                    var src = "https://d1en0cs4s0ez90.cloudfront.net/hls/scientology/en/decade-of-expansion-backgrounds_en/mark-ultra-viii-dial-only";
1045                    videojs($videoEl.find('video')[0], { controls: false, muted: true, autoplay: true }).ready(function () {
1046                        this.src([
1047                            { src: src + '-h265.mp4', type: 'video/mp4; codecs="hvc1"' },
1048                            { src: src + '.mp4', type: 'video/mp4; codecs="avc1"' }
1049                        ]);
1050                        this.play();
1051                    });
1052
1053                })
1054                // .addIndicators() // add indicators (requires plugin)
1055                .addTo(self.controller)
1056        );
1057
1058
1059        var tween = new TimelineMax();
1060        tween.to(emeter, 1.6, { scale: 0.11, y: '-14.7%', x: '-0.5%' });
1061        tween.to(emeter, 0.2, { autoAlpha: 0 });
1062
1063        // var emeterOffset = offset + screenHeight * 0.25;
1064        // var emeterDuration = screenHeight * 2 - offset * 3;
1065        // var emeterOffset = screenHeight * 0.2;
1066        var emeterOffset = 0;
1067        var emeterDuration = screenHeight * 0.5;
1068
1069        // scale down meter
1070        self.scenes.push(
1071            new ScrollMagic.Scene({ triggerElement: '#decade-2020--emeter-trigger', triggerHook: 0, reverse: true, offset: emeterOffset, duration: emeterDuration })
1072                .setTween(tween)
1073                .on("destroy", function (event) {
1074                    tween.progress(0);
1075                })
1076                // .addIndicators() // add indicators (requires plugin)
1077                .addTo(self.controller)
1078        );
1079
1080        // fade in stage photo
1081
1082        var tween2 = TweenMax.from(releasePhoto, 1, { autoAlpha: 0 });
1083        self.scenes.push(
1084            new ScrollMagic.Scene({ triggerElement: '#decade-2020--emeter-trigger', triggerHook: 0, reverse: true, offset: emeterOffset, duration: emeterDuration * 0.7 })
1085                .setTween(tween2)
1086                .on("destroy", function (event) {
1087                    TweenMax.set(releasePhoto, { autoAlpha: 1 });
1088                })
1089                // .addInd
1090                .on("destroy", function (event) {
1091                    TweenMax.set('.decade-2020-churches-reveal', { scale: 1 });
1092                })
1093                // .addIndicators() // add indicators (requires plugin)
1094                .addTo(self.controller)
1095        );
1096
1097    }
1098
1099    Decade2020Animator.prototype.initEndTitles = function () {
1100        var self = this;
1101
1102        var fadeDuration = $(window).outerHeight() * 0.2;
1103        var height = $(window).outerHeight() * 0.5;
1104
1105        var items = $('.decade-2020-end-title-wrapper');
1106
1107        // var pinOffset = ($(window).height() - height) / 2;
1108        var pinOffset = 0
1109
1110        var total = 0;
1111
1112        _.each(items, function (trigger, index) {
1113            //
1114            var el = trigger.querySelector(".decade-2020-end-title");
1115
1116            var first = index == 0;
1117            var lastItem = index + 1 == items.length;
1118
1119            self.scenes.push(
1120                new ScrollMagic.Scene({ triggerElement: trigger, triggerHook: 0, reverse: true, offset: -pinOffset, duration: height })
1121                    .setPin(trigger, { pushFollowers: false })
1122                    .addTo(self.controller)
1123            );
1124
1125            total += height + fadeDuration;
1126
1127            if(first == true) {
1128                var tweenMove = TweenMax.fromTo(el, 1, { y: 0 }, { y: -100 });
1129            } else if (lastItem == false) {
1130                var tweenMove = TweenMax.fromTo(el, 1, { y: 30 }, { y: -70 });
1131            } else {
1132                var tweenMove = TweenMax.fromTo(el, 1, { y: 100 }, { y: 0 });
1133            }
1134            
1135            self.scenes.push(
1136                new ScrollMagic.Scene({ triggerElement: trigger, triggerHook: 0, reverse: true, offset: 0, duration: height })
1137                    .setTween(tweenMove)
1138                    .addTo(self.controller)
1139            );
1140
1141            if (first == false) {
1142                var tween1 = TweenMax.from(el, 1, { autoAlpha: 0 });
1143                self.scenes.push(
1144                    new ScrollMagic.Scene({ triggerElement: trigger, triggerHook: 0, reverse: true, offset: 0, duration: fadeDuration })
1145                        .setTween(tween1)
1146                        .on("destroy", function (event) {
1147                            TweenMax.set(el, { autoAlpha: 1 });
1148                        })
1149                        .addTo(self.controller)
1150                );
1151            }
1152
1153            if (lastItem == false) {
1154                var tweenFadeOut = TweenMax.to(el, 1, { autoAlpha: 0 });
1155                self.scenes.push(
1156                    new ScrollMagic.Scene({ triggerElement: trigger, triggerHook: 0, reverse: true, offset: height - fadeDuration, duration: fadeDuration })
1157                        .setTween(tweenFadeOut)
1158                        .on("destroy", function (event) {
1159                            TweenMax.set(el, { autoAlpha: 1 });
1160                        })
1161                        .addTo(self.controller)
1162                );
1163            }
1164        });
1165
1166        // Pin background
1167        var bgSelector = '.decade-2020-end-background';
1168
1169        var length = items.length;
1170
1171        self.scenes.push(
1172            new ScrollMagic.Scene({ triggerElement: '.decade-2020-end-background--trigger', triggerHook: 0, reverse: true, offset: 0, duration: height * (length * 2 - 1) })
1173                .setPin(bgSelector, { pushFollowers: false })
1174                .on("destroy", function (event) {
1175                    TweenMax.set(bgSelector, { autoAlpha: 1 });
1176                })
1177                .addTo(self.controller)
1178        );
1179    }
1180
1181    Decade2020Animator.prototype.resize = function () {
1182        var self = this;
1183
1184        // clean up from previous canvases
1185        self.destroy();
1186        self.Init();
1187    }
1188
1189    Decade2020Animator.prototype.destroy = function () {
1190        var self = this;
1191
1192        // clean up from previous canvases
1193        this.cachedPixelRatio = null;
1194        this.cachedPinOffset = null;
1195        self.scenes.forEach(function (scene) {
1196            scene.destroy(true);
1197        });
1198        $('.decade-2020-reveal-canvas').remove();
1199    }
1200
1201    Decade2020Animator.prototype.initRevealCanvas = function () {
1202        var self = this;
1203
1204        var isAndroid = /(android)/i.test(navigator.userAgent);
1205        // dont animate this on IE, android and ipods
1206        if (isIE || isAndroid || navigator.userAgent.match(/iPod/i)) {
1207            $('.decade-2020--churches-cover').removeClass('decade-2020--churches-cover');
1208            $('.decade-2020--churches-cover--text').addClass('pb-5');
1209            return;
1210        }
1211
1212        $('.decade-2020-reveal-text').addClass('invisible');
1213
1214        // add canvas
1215        // using Original screen width
1216        var canvas = self.createHiDPICanvas(window.innerWidth, window.innerHeight);
1217        $('.decade-2020--churches-cover').before(canvas);
1218        canvas.classList.add('decade-2020-reveal-canvas');
1219        var ctx = canvas.getContext("2d");
1220        self.drawCanvasText(canvas, ctx, 0);
1221
1222
1223        var startOffset = 200 * this.getPixelRatio();
1224        var screenHeight = $(window).height() * 0.5;
1225
1226        // for mobile center word decade
1227        var pinOffset = this.getPinOffset();
1228
1229        // pin canvas
1230        self.scenes.push(
1231            new ScrollMagic.Scene({ triggerElement: '.decade-2020-reveal--trigger', triggerHook: 0, offset: pinOffset, reverse: true, duration: screenHeight * 2 + startOffset })
1232                .setPin('.decade-2020-reveal-canvas', { pushFollowers: true })
1233                // .addIndicators() // add indicators (requires plugin)
1234                .addTo(self.controller)
1235        );
1236
1237
1238        // pin text over churches
1239        var fadeOutChurchesCover = TweenMax.to('.decade-2020--churches-cover .decade-2020--churches-cover--text', 1, { autoAlpha: 0 });
1240        self.scenes.push(
1241            new ScrollMagic.Scene({ triggerElement: '.decade-2020-reveal--trigger', triggerHook: 0, offset: pinOffset, reverse: true, duration: screenHeight * 0.1 + startOffset })
1242                .setPin('.decade-2020--churches-cover', { pushFollowers: false })
1243                .setTween(fadeOutChurchesCover)
1244                // .addIndicators() // add indicators (requires plugin)
1245                .addTo(self.controller)
1246        );
1247
1248        // pin what is underneath of canvas to reveal with longer duration
1249        self.scenes.push(
1250            new ScrollMagic.Scene({ triggerElement: '.decade-2020-reveal--trigger', triggerHook: 0, offset: 0, reverse: true, duration: screenHeight * 1.9 })
1251                .setPin('.decade-2020-churches-reveal', { pushFollowers: true })
1252                // .addIndicators() // add indicators (requires plugin)
1253                .addTo(self.controller)
1254        );
1255
1256        var $cover = $('.decade-2020--churches-cover');
1257
1258        // scale back pinned churches for cool animation
1259        var tweenScaleChurchesBack = TweenMax.from('.decade-2020-churches-reveal', 1, { scale: 1.5 });
1260        self.scenes.push(
1261            new ScrollMagic.Scene({ triggerElement: '.decade-2020-reveal--trigger', triggerHook: 0, offset: startOffset, reverse: true, duration: screenHeight * 1.4 })
1262                .setTween(tweenScaleChurchesBack)
1263                .on("destroy", function (event) {
1264                    TweenMax.set('.decade-2020-churches-reveal', { scale: 1 });
1265                })
1266                .on("progress", function (event) {
1267                    if (event.progress == 1) {
1268                        $cover.addClass('d-none');
1269                    } else {
1270                        $cover.removeClass('d-none');
1271                    }
1272                })
1273                // .addIndicators() // add indicators (requires plugin)
1274                .addTo(self.controller)
1275        );
1276
1277        var fadeOutDuration = screenHeight * 2;
1278        if(this.isMobile() == false) {
1279            fadeOutDuration -= 250;
1280        }
1281
1282        // fade out canvas at the end of the animation for safety if did not fully revealed
1283        var fadeOutCanvas = TweenMax.to(canvas, 1, { autoAlpha: 0 });
1284        self.scenes.push(
1285            new ScrollMagic.Scene({ triggerElement: '.decade-2020-reveal--trigger', triggerHook: 0, offset: screenHeight * 2, reverse: true, duration: screenHeight * 0.3 })
1286                .setTween(fadeOutCanvas)
1287                // .addIndicators() // add indicators (requires plugin)
1288                .addTo(self.controller)
1289        );
1290
1291        // redraw canvas for reveal animation
1292        self.scenes.push(
1293            new ScrollMagic.Scene({ triggerElement: '.decade-2020-reveal--trigger', triggerHook: -300, offset: startOffset, reverse: true, duration: screenHeight * 2 })
1294                .on("progress", function (event) {
1295                    var progress = event.progress;
1296                    if (progress > 0) {
1297                        $('.decade-2020--churches-cover').removeClass('decade-2020--black-background');
1298                    } else {
1299                        $('.decade-2020--churches-cover').addClass('decade-2020--black-background');
1300                    }
1301
1302                    self.drawCanvasText(canvas, ctx, progress);
1303                })
1304                .addTo(self.controller)
1305        );
1306
1307    }
1308
1309    Decade2020Animator.prototype.drawCanvasText = function (canvas, ctx, progress) {
1310        var self = this;
1311        var pixelRatio = this.getPixelRatio();
1312
1313        // var maxZoom = self.scaledWindowHeight / self.rectHeight * pixelRatio * zoomK;
1314
1315        // 200 arbitrary number to make text appear off screen
1316        var maxZoom = 200 * pixelRatio;
1317
1318        // slow down a bit for a better animation feel
1319        if (progress < 0.4) {
1320            var slowProgress = progress * 1 / 0.4;
1321            progress = slowProgress * progress;
1322        }
1323
1324        // how much to zoom
1325        var zoomfactor = 1 + (maxZoom - 1) * progress;
1326
1327        // offsetting Y to make it happen faster (feels much better)
1328        var yoffsetK = 1.1;
1329
1330        // Y offset
1331        var moveY = -self.rectOffset.top * maxZoom * progress * yoffsetK;
1332
1333        ctx.setTransform(zoomfactor, 0, 0, zoomfactor, -(zoomfactor - 1) * self.scaledWindowWidth / 2, moveY);
1334        ctx.globalCompositeOperation = 'source-over';
1335
1336        // Draw black background
1337        ctx.fillStyle = "#000000";
1338        if (progress == 0) {
1339            ctx.globalAlpha = 0;
1340            // only blackness
1341            ctx.globalCompositeOperation = 'copy';
1342        }
1343        ctx.fillRect(0, 0, self.scaledWindowWidth, self.scaledWindowHeight);
1344        ctx.globalAlpha = 1;
1345
1346
1347        self.drawTextRectBg(ctx, progress);
1348        self.drawText(ctx);
1349    }
1350
1351
1352    Decade2020Animator.prototype.drawTextRectBg = function (ctx, progress) {
1353        var self = this;
1354
1355        // Fill text rect
1356        ctx.globalCompositeOperation = 'source-over';
1357        ctx.fillStyle = "#ffffff";
1358
1359        // cut out rect for background
1360        ctx.globalCompositeOperation = 'destination-out'
1361        ctx.fillRect(self.leftPos, self.rectOffset.top, self.rectWidth, self.rectHeight);
1362        ctx.globalCompositeOperation = 'source-over';
1363
1364
1365        // fill in background with white for the first 10% for nice transition
1366        if (progress == 0) {
1367
1368        } else if (progress <= 0.1) {
1369            ctx.globalAlpha = 1 - (1 - (0.1 - progress) * 10);
1370        } else {
1371            ctx.globalCompositeOperation = 'destination-out'
1372        }
1373
1374        //cut out rect
1375        ctx.fillRect(self.leftPos, self.rectOffset.top, self.rectWidth, self.rectHeight);
1376
1377        ctx.globalCompositeOperation = 'source-over'
1378
1379        ctx.globalAlpha = 1;
1380    }
1381
1382    Decade2020Animator.prototype.drawText = function (ctx) {
1383        var self = this;
1384        var pixelRatio = this.getPixelRatio();
1385
1386        // Fill text
1387        ctx.fillStyle = "#000000";
1388        ctx.font = self.scaledFontSize + "px " + self.fontName;
1389        ctx.textAlign = "center";
1390        ctx.textBaseline = "middle";
1391
1392        var textTop = (self.rectOffset.top + self.textTopPadding * pixelRatio);
1393        var textLeft = (self.leftPos + self.rectWidth * 0.5);
1394
1395        ctx.globalCompositeOperation = 'source-over'
1396        ctx.fillText(self.text, textLeft, textTop);
1397    }
1398
1399
1400    Decade2020Animator.prototype.createHiDPICanvas = function (w, h, ratio) {
1401        if (!ratio) { ratio = this.getPixelRatio(); }
1402        var can = document.createElement("canvas");
1403
1404        h += this.getPinOffset();
1405
1406        can.width = w * ratio;
1407        can.height = h * ratio;
1408        can.style.width = w + "px";
1409        can.style.height = h + "px";
1410        can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
1411        return can;
1412    }
1413
1414    Decade2020Animator.prototype.getPixelRatio = function () {
1415        if (this.cachedPixelRatio) {
1416            return this.cachedPixelRatio;
1417        }
1418        var ctx = document.createElement("canvas").getContext("2d"),
1419            dpr = window.devicePixelRatio || 1,
1420            bsr = ctx.webkitBackingStorePixelRatio ||
1421                ctx.mozBackingStorePixelRatio ||
1422                ctx.msBackingStorePixelRatio ||
1423                ctx.oBackingStorePixelRatio ||
1424                ctx.backingStorePixelRatio || 1;
1425
1426        this.cachedPixelRatio = dpr / bsr;
1427        return this.cachedPixelRatio;
1428    }
1429
1430    Decade2020Animator.prototype.isMobile = function () {
1431        return $(window).width() < 767;
1432    }
1433
1434    // used to center word decade
1435    Decade2020Animator.prototype.getPinOffset = function () {
1436        if (this.cachedPinOffset) {
1437            return this.cachedPinOffset;
1438        }
1439
1440        this.textElPos = this.textEl.offset();
1441        this.parentPos = this.textEl.parent().offset();
1442
1443        var topOffset = this.textElPos.top - this.parentPos.top + 10;
1444
1445        this.cachedPinOffset = topOffset - $(window).height() * 0.5 + 90 * 0.5;
1446
1447        this.cachedPinOffset = Math.abs(this.cachedPinOffset);
1448
1449        return this.cachedPinOffset;
1450    }
1451
1452
1453    return Decade2020Animator;
1454}())();

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.