PageSourceSearch

https://www.still.fr/typo3conf/ext/mmpackage/Resources/Public/Js/m…/modules/contentSplashTeaser.js?1789559271

js still.fr collected 2026-09-29 02:37:58 UTC 10,213 bytes, 279 lines download raw bytes

1/**
2 * Content Splash Teaser
3 * Collection
4 * @see @todo
5 */
6(function( app ) {
7    /**
8     * Module Namespace
9     * Use to register module and events.
10     */
11    var NAMESPACE = 'contentSplashTeaser';
12
13    /**
14     * Default configuration
15     * Required configuration to ensure minimal functionality.
16     *
17     * @property {string} selector - selector string
18     */
19    var defaults = {
20        selector: '.content-splash-teaser',
21        autoStart: true,
22        displayDelay: 2000
23    };
24
25    /**
26     * Private variables/state
27     * Variables not to be exposed, nor inherited or modified.
28     * e.g. shortcuts to dependencies or variables to spare memory.
29     */
30    var conf;
31    var $ = app.$;
32
33    // Module startup
34    // The DOM is ready to be manipulated
35    app.ready(function() {
36        // apply custom config if present
37        conf = _.defaults({}, app.getConfig(NAMESPACE), defaults);
38
39        // set private variables and check dependencies
40        if ( !app.scrollHelper ) throw 'scrollHelper module missing';
41        if ( !app.viewportHelper ) throw 'viewportHelper module missing';
42
43        // Register Module
44        app.register(NAMESPACE, Module);
45
46        // Auto-initialize collection
47        if ( conf.autoStart === true ) {
48            $(conf.selector).each(function() {
49                Module({
50                    targetElem: $(this)
51                });
52            });
53        }
54    });
55
56    /**
57     * Module api
58     * Return new instances of a prototype or plain functionality.
59     * Depending on options supplied you may choose what object/functionality to run/return.
60     */
61    var Module = function( options ) {
62        options = _.extend({}, conf, options);
63
64        if ( $(options.targetElem).hasClass('content-splash-teaser--type-5') ) {
65            options.initEvents = false;
66            return ContentSplashTeaser(options);
67        }
68        else {
69            return ContentSplashTeaser(options);
70        }
71    };
72
73    var ContentSplashTeaser = function( options ) {
74        var api;
75        var $targetElem = $(options.targetElem);
76        if ( !$targetElem.length ) return;
77        var isEnabled = getIsEnabledState();
78        var isVisible = false;
79        let showNonStop = false;
80
81        // instance already running
82        if ( $targetElem.data(NAMESPACE) ) return;
83
84        if ($targetElem.data('showNonStop') === 1) {
85            showNonStop = true;
86        }
87
88        if ( options.initEvents !== false ) {
89            // esc key handling
90            $(document).on('keydown.' + NAMESPACE, function( event ) {
91                if ( event.keyCode !== 27 || isVisible === false ) return;
92
93                // hide modal if the escape key has been pressed
94                api.hide();
95            });
96
97            // modal event handling
98            $targetElem.on('click.' + NAMESPACE, function( event ) {
99                var $evtTarget = $(event.target);
100
101                // hide modal on click on overlay
102                if ( $evtTarget.hasClass('content-splash-teaser') ) {
103                    api.hide();
104                }
105                // permanently disable modal on click on disable-permanent btn
106                else if ( $evtTarget.hasClass('content-splash-teaser__disable-permanent-btn') || $evtTarget.closest('.content-splash-teaser__disable-permanent-btn').length ) {
107                    $targetElem.one('afterHide.' + NAMESPACE, function() {
108                        // disable after transition and save state
109                        api.disable(true);
110                    });
111                    api.hide();
112                }
113                // disable modal on click on a disable-btn
114                else if ( $evtTarget.hasClass('content-splash-teaser__disable-btn') || $evtTarget.closest('.content-splash-teaser__disable-btn').length ) {
115                    if ( isVisible ) {
116                        $targetElem.one('afterHide.' + NAMESPACE, function() {
117                            // disable after transition
118                            api.disable();
119                        });
120                        api.hide();
121                    } else {
122                        api.disable();
123                    }
124                }
125                // toggle modal on click on a toggle-btn
126                else if ( $evtTarget.hasClass('content-splash-teaser__toggle-btn') || $evtTarget.closest('.content-splash-teaser__toggle-btn').length ) {
127                    api.toggle();
128                }
129            });
130        }
131
132        // hide teaser when scrolled to the bottom of the page
133        // to ensure full visibility of the footer
134        app.on('scroll.scrollHelper', function( data ) {
135            var windowHeight = app.viewportHelper.getViewportState().height;
136            // 100 is just 100, no specific source
137            var scrollTreshold = app.scrollHelper.getDocumentScrollHeight() - windowHeight - 100;
138
139            $targetElem.toggleClass('content-splash-teaser--on-page-bottom', data.scrollY >= scrollTreshold);
140        });
141
142        api = {
143            show: function() {
144
145                if(showNonStop) {
146                    $targetElem.trigger('show.' + NAMESPACE, api);
147                    return this;
148                }
149
150                if ( isEnabled === false ) return this;
151                if ( isVisible === true ) return this;
152
153                $targetElem.on('transitionend.show.' + NAMESPACE + ' webkitTransitionEnd.show.' + NAMESPACE, function( event ) {
154                    if ( !$targetElem.is(event.target) ) return;
155
156                    $targetElem.trigger('afterShow.' + NAMESPACE, api);
157                    $targetElem.off('.show.' + NAMESPACE);
158                });
159
160                $targetElem.addClass('content-splash-teaser--visible');
161                isVisible = true;
162                $targetElem.trigger('show.' + NAMESPACE, api);
163                return this;
164            },
165            hide: function() {
166                if ( isEnabled === false ) return this;
167                if ( isVisible === false ) return this;
168
169                $targetElem.on('transitionend.hide.' + NAMESPACE + ' webkitTransitionEnd.hide.' + NAMESPACE, function( event ) {
170                    if ( !$targetElem.is(event.target) ) return;
171
172                    $targetElem.trigger('afterHide.' + NAMESPACE, api);
173                    $targetElem.off('.hide.' + NAMESPACE);
174                });
175
176                $targetElem.removeClass('content-splash-teaser--visible');
177                isVisible = false;
178                $targetElem.trigger('hide.' + NAMESPACE, api);
179                return this;
180            },
181            toggle: function() {
182                if ( isVisible === true ) {
183                    return this.hide();
184                } else {
185                    return this.show();
186                }
187            },
188
189            /**
190             * Enable the teaser
191             * @param [permanent] {boolean} - save enabled state permanently
192             * @param [force] {boolean} - ignore current state and run state-change process anyway
193             * @returns {api}
194             */
195            enable: function( permanent, force ) {
196                if ( isEnabled === true && force !== true ) return this;
197
198                $targetElem.addClass('content-splash-teaser--enabled');
199                isEnabled = true;
200                $targetElem.trigger('enabled.' + NAMESPACE, api);
201                if ( permanent === true ) {
202                    saveIsEnabledState();
203                }
204                return this;
205            },
206            /**
207             * Disable the teaser
208             * @param [permanent] {boolean} - save enabled state permanently
209             * @param [force] {boolean} - ignore current state and run state-change process anyway
210             * @returns {api}
211             */
212            disable: function( permanent, force ) {
213                if ( isEnabled === false && force !== true ) return this;
214
215                $targetElem.removeClass('content-splash-teaser--enabled');
216                isEnabled = false;
217                $targetElem.trigger('disabled.' + NAMESPACE, api);
218                if ( permanent === true ) {
219                    saveIsEnabledState();
220                }
221                return this;
222            },
223
224            isVisible: function() {
225                return isVisible;
226            },
227            isEnabled: function() {
228                return isEnabled;
229            }
230        };
231
232        if ( isEnabled === true ) {
233            setTimeout(function() {
234                api.enable(false, true);
235            }, options.displayDelay);
236        }
237
238        // expose API to public
239        $targetElem.data(NAMESPACE, api);
240
241        return api;
242
243        /**
244         * Save enabled state permanently in cookie
245         */
246        function saveIsEnabledState() {
247
248            var exdate = new Date;
249
250            if ($targetElem.data('showNonStop') === 0) {
251                exdate.setDate(exdate.getDate() + 30);
252            } else {
253                // Set expire date in past to delete cookie
254                exdate.setDate(exdate.getDate() - 60);
255            }
256
257            exdate = "; expires=" + exdate.toUTCString() + '; path=/; domain=.' + location.hostname.replace(/(?:.+\.)?([a-z0-9\-]+\.[a-z]{2,})$/, '$1');
258            document.cookie = "mmKitContentSplashTeaserEnabled=" + isEnabled + exdate;
259
260
261        }
262
263        /**
264         * Get enabled state
265         * @returns {boolean}
266         */
267        function getIsEnabledState() {
268
269            if($targetElem.data('showNonStop') === 1) return true;
270
271            var isEnabledCookie = document.cookie.match(/mmKitContentSplashTeaserEnabled=(.*?)(?:;|$)/);
272            if ( isEnabledCookie ) isEnabledCookie = isEnabledCookie[1];
273
274            // if not explicitly false, it's always true by default
275            return isEnabledCookie === null || (isEnabledCookie !== 'false' && isEnabledCookie !== false);
276        }
277    };
278
279}(app));

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.