PageSourceSearch

https://www.still.co.uk/typo3conf/ext/mmpackage/Resources/Public/Js/modules/contentRow.js?1790758003

js still.co.uk collected 2026-10-02 12:43:02 UTC 8,397 bytes, 250 lines download raw bytes

1/**
2 * Content Row & Toggle Row
3 * Collection
4 * @see https://teamnet.mellowmessage.de/display/ci/Strukturelement%3A+Inhaltszeile
5 * @see https://teamnet.mellowmessage.de/display/ci/Strukturelement%3A+Aufklappzeile
6 */
7(function( app ) {
8    /**
9     * Module Namespace
10     * Use to register module and events.
11     */
12    var NAMESPACE = 'contentRow';
13
14    /**
15     * Default configuration
16     * Required configuration to ensure minimal functionality.
17     *
18     * @property {string} selector - selector string
19     * See toggleWidget documentation for the following options
20     */
21    var defaults = {
22        selector: '.content-row',
23        autoStart: true,
24        breakpoints: {
25            isMobileBelow: 992
26        },
27        toggleBtnSelector: '.content-row__toggle-trigger',
28        toggleContentSelector: function( $el ) {
29            return $el.next('.content-row--toggle-content');
30        },
31        openClass: 'content-row--toggle-is-open',
32        offsetTopShift: -150,
33        scrollDuration: 500
34    };
35
36    /**
37     * Private variables/state
38     * Variables not to be exposed, nor inherited or modified.
39     * e.g. shortcuts to dependencies or variables to spare memory.
40     */
41    var conf;
42    var $ = app.$;
43    var viewportIsMobile;
44
45    // Module startup
46    // The DOM is ready to be manipulated
47    app.ready(function() {
48        // apply custom config if present
49        conf = _.defaults({}, app.getConfig(NAMESPACE), defaults);
50
51        // set private variables and check dependencies
52        if ( !app.viewportHelper ) throw 'viewportHelper module missing';
53        if ( !app.scrollHelper ) throw 'scrollHelper module missing';
54        if ( !$.fn.toggleWidget ) throw 'jQuery ToggletWidget plugin missing';
55
56        // cross-instance subscription to spare performance
57        app.on('breakpointDebounced.viewportHelper', breakpointHandler);
58        breakpointHandler();
59
60        // Register Module
61        app.register(NAMESPACE, Module);
62
63        // Auto-initialize collection
64        if ( conf.autoStart === true ) {
65            $(conf.selector).each(function() {
66                Module({
67                    targetElem: $(this)
68                });
69            });
70        }
71
72        function breakpointHandler() {
73            viewportIsMobile = (app.viewportHelper.getViewportState().width < conf.breakpoints.isMobileBelow);
74        }
75    });
76
77    /**
78     * Module api
79     * Return new instances of a prototype or plain functionality.
80     * Depending on options supplied you may choose what object/functionality to run/return.
81     */
82    var Module = function( options ) {
83        options = _.extend({}, conf, options);
84        var $targetElem = $(options.targetElem);
85
86        if ( $targetElem.is('.content-row--bg-video, .content-row--bg-video-content-layout') ) {
87            ContentRowVideo(options);
88        }
89        else if ( $targetElem.is('.content-row--stage-video') ) {
90            ContentRowVideo(_.extend(options, {
91                videoElemSelector: '.content-row__stage-video'
92            }));
93        }
94        else if ( $targetElem.is('.content-row--stage-img') ) {
95            ContentRowStageImage(options);
96        }
97
98        if ( $targetElem.next('.content-row--toggle-content').length ) {
99            ContentToggleRow(options);
100        }
101
102        return {};
103    };
104
105    /**
106     * Background video design type and stage video
107     */
108    var ContentRowVideo = function( options ) {
109        var api;
110        var $targetElem = $(options.targetElem);
111        if ( !$targetElem.length ) return;
112
113        options = _.defaults({}, options, {
114            videoElemSelector: '.content-row__bg-video'
115        });
116
117        var video = $targetElem.find(options.videoElemSelector)[0];
118        if ( !video ) return;
119
120        // As fluid is not capable of the OR-operator we need to do it on the frontend ...
121        // Can be replaced as soon as :blank is supported or fluid is capable of basic queries.
122        if ( !$targetElem.find('.content-row__text-box-btn-wrap').children().length ) {
123            $targetElem.find('.content-row__text-box-btn-wrap').remove();
124        }
125        if ( !$targetElem.find('.content-row__text-box').children().length ) {
126            $targetElem.find('.content-row__text-box').remove();
127        }
128
129        api = {
130            // No methods yet
131        };
132
133        // expose API to public
134        //$targetElem.data(NAMESPACE, api);
135
136        return api;
137    };
138
139    /**
140     * Toggle functionality
141     */
142    var ContentToggleRow = function( options ) {
143        var api;
144        var $targetElem = $(options.targetElem);
145        if ( !$targetElem.length ) return;
146        var $targetElemContent = $targetElem.next('.content-row--toggle-content');
147        if ( !$targetElemContent.length ) return;
148        var targetElemId = $targetElem.attr('id');
149        var toggleWidgetApi;
150        if ( $targetElem.data(NAMESPACE) ) return;
151
152        $targetElem.addClass('content-row--toggle');
153
154        // I know, it's not that cool ...
155        if ( $targetElemContent.hasClass('content-row--toggle-content-default-open') ) {
156            $targetElem.addClass(options.openClass);
157            $targetElemContent.removeClass('content-row--toggle-content-default-open');
158        }
159        $targetElem.toggleWidget(_.extend({}, options));
160        toggleWidgetApi = $targetElem.data('toggleWidget');
161
162        $targetElem.on('beforeOpen.toggleWidget.' + NAMESPACE, function( event, toggleWidgetApi ) {
163            if ( !$targetElem.is(event.target) ) return;
164
165            api.scrollToContentOffsetTop();
166        });
167
168        // order intended: must scroll first, then close and animate
169        $targetElem.on('afterClose.toggleWidget.' + NAMESPACE, function( event, toggleWidgetApi ) {
170            if ( !$targetElem.is(event.target) ) return;
171
172            if ( viewportIsMobile === true ) {
173                api.scrollToContentOffsetTop();
174            }
175        });
176
177        // additional event handler for the second toggle btn in the content element
178        $targetElemContent.on('click.' + NAMESPACE, '.content-row__toggle-close-btn', function() {
179            $targetElem.data('toggleWidget').close();
180        });
181
182        if ( window.additionalContentRowToggleTriggers && window.additionalContentRowToggleTriggers.hasOwnProperty(targetElemId) ) {
183            $(window.additionalContentRowToggleTriggers[targetElemId]).on('click', function( event ) {
184                event.preventDefault();
185
186                if ( toggleWidgetApi.isOpen() ) {
187                    api.scrollToContentOffsetTop();
188                } else {
189                    toggleWidgetApi.open();
190                }
191            });
192        }
193
194        api = {
195            scrollToContentOffsetTop: function() {
196                app.scrollHelper.scrollTo($targetElemContent.offset().top + options.offsetTopShift, {
197                    duration: options.scrollDuration
198                });
199            }
200        };
201
202        // expose API to public
203        $targetElem.data(NAMESPACE, api);
204
205        return api;
206    };
207
208    /**
209     * Background image design type
210     */
211    var ContentRowBgImage = function( options ) {
212        var api;
213        var $targetElem = $(options.targetElem);
214        if ( !$targetElem.length ) return;
215
216        api = {
217            // No methods yet
218        };
219
220        // expose API to public
221        //$targetElem.data(NAMESPACE, api);
222
223        return api;
224    };
225
226    /**
227     * Stage image design type
228     */
229    var ContentRowStageImage = function( options ) {
230        var api;
231        var $targetElem = $(options.targetElem);
232        if ( !$targetElem.length ) return;
233
234        // As fluid is not capable of the OR-operator we need to do it on the frontend ...
235        // Can be replaced as soon as :blank is supported or fluid is capable of basic queries.
236        if ( !$targetElem.find('.content-row__text-box').children().length ) {
237            $targetElem.find('.content-row__text-box').remove();
238        }
239
240        api = {
241            // No methods yet
242        };
243
244        // expose API to public
245        //$targetElem.data(NAMESPACE, api);
246
247        return api;
248    };
249
250}(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.