https://www.still.co.uk/typo3conf/ext/mmpackage/Resources/Public/Js/modules/contentRow.js?1790758003
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.