1/** 2 * Responsive layout helpers for Events Feed (grid / list / cover). 3 */ 4(function (window) { 5 'use strict'; 6 7 var BREAKPOINT_QUERIES = { 8 phone: '(max-width: 767px)', 9 tablet: '(min-width: 768px) and (max-width: 1024px)', 10 desktop: '(min-width: 1025px)' 11 }; 12 13 function getScreenWidth() { 14 if (window.visualViewport && window.visualViewport.width) { 15 return window.visualViewport.width; 16 } 17 return window.innerWidth || document.documentElement.clientWidth || screen.width; 18 } 19 20 function getScreenBreakpoint() { 21 if (typeof window.matchMedia === 'function') { 22 if (window.matchMedia(BREAKPOINT_QUERIES.phone).matches) { 23 return 'phone'; 24 } 25 if (window.matchMedia(BREAKPOINT_QUERIES.tablet).matches) { 26 return 'tablet'; 27 } 28 return 'desktop'; 29 } 30 31 var screenWidth = getScreenWidth(); 32 if (screenWidth <= 767) { 33 return 'phone'; 34 } 35 if (screenWidth <= 1024) { 36 return 'tablet'; 37 } 38 return 'desktop'; 39 } 40 41 function readLayoutParamsFromContainer($container) { 42 var params = {}; 43 44 $container.find('input.hidden-data-field').each(function () { 45 var $field = $(this); 46 params[$field.attr('name')] = $field.val() || ''; 47 }); 48 49 params.layout_desktop = params.layout_desktop || $container.attr('data-layout-desktop') || params.layout || 'grid'; 50 params.layout_tablet = params.layout_tablet || $container.attr('data-layout-tablet') || ''; 51 params.layout_phone = params.layout_phone || $container.attr('data-layout-phone') || ''; 52 params.layout_type_desktop = params.layout_type_desktop || $container.attr('data-layout-type-desktop') || params.layout_type || ''; 53 params.layout_type_tablet = params.layout_type_tablet || $container.attr('data-layout-type-tablet') || ''; 54 params.layout_type_phone = params.layout_type_phone || $container.attr('data-layout-type-phone') || ''; 55 56 return params; 57 } 58 59 function onBreakpointChange(callback) { 60 if (typeof window.matchMedia !== 'function' || typeof callback !== 'function') { 61 return function () {}; 62 } 63 64 var queries = [ 65 window.matchMedia(BREAKPOINT_QUERIES.phone), 66 window.matchMedia(BREAKPOINT_QUERIES.tablet), 67 window.matchMedia(BREAKPOINT_QUERIES.desktop) 68 ]; 69 var handler = function () { 70 callback(getScreenBreakpoint()); 71 }; 72 73 queries.forEach(function (query) { 74 if (typeof query.addEventListener === 'function') { 75 query.addEventListener('change', handler); 76 } else if (typeof query.addListener === 'function') { 77 query.addListener(handler); 78 } 79 }); 80 81 if (window.visualViewport && typeof window.visualViewport.addEventListener === 'function') { 82 window.visualViewport.addEventListener('resize', handler); 83 } 84 85 return function () { 86 queries.forEach(function (query) { 87 if (typeof query.removeEventListener === 'function') { 88 query.removeEventListener('change', handler); 89 } else if (typeof query.removeListener === 'function') { 90 query.removeListener(handler); 91 } 92 }); 93 if (window.visualViewport && typeof window.visualViewport.removeEventListener === 'function') { 94 window.visualViewport.removeEventListener('resize', handler); 95 } 96 }; 97 } 98 99 function normalizeLayout(layout) { 100 return (layout || 'grid').toString().toLowerCase(); 101 } 102 103 function getResponsiveLayout(params, breakpoint) { 104 breakpoint = breakpoint || getScreenBreakpoint(); 105 var desktop = normalizeLayout(params.layout_desktop || params.layout || 'grid'); 106 var tablet = params.layout_tablet ? normalizeLayout(params.layout_tablet) : ''; 107 var phone = params.layout_phone ? normalizeLayout(params.layout_phone) : ''; 108 109 if (breakpoint === 'phone') { 110 return phone || tablet || desktop; 111 } 112 if (breakpoint === 'tablet') { 113 return tablet || desktop; 114 } 115 return desktop; 116 } 117 118 function getResponsiveLayoutType(params, breakpoint) { 119 breakpoint = breakpoint || getScreenBreakpoint(); 120 var desktop = (params.layout_type_desktop || params.layout_type || 'off').toString(); 121 var tablet = (params.layout_type_tablet || '').toString(); 122 var phone = (params.layout_type_phone || '').toString(); 123 124 if (breakpoint === 'phone') { 125 if (phone) { 126 return phone; 127 } 128 if (tablet) { 129 return tablet;
130 } 131 return desktop; 132 } 133 if (breakpoint === 'tablet') { 134 return tablet || desktop; 135 } 136 return desktop; 137 } 138 139 function getLayoutFromContainer($container) { 140 if ($container.hasClass('cover-container')) { 141 return 'cover'; 142 } 143 if ($container.hasClass('list-container')) { 144 return 'list'; 145 } 146 if ($container.hasClass('grid-container')) { 147 return 'grid'; 148 } 149 return normalizeLayout($container.attr('data-active-layout') || ''); 150 } 151 152 function getGridColumnsClass(columns) { 153 var value = parseInt(columns, 10); 154 if (isNaN(value) || value < 1 || value > 4) { 155 value = 3; 156 } 157 return 'decm-grid-cols-' + value; 158 } 159 160 function getListColumnsClass(columns) { 161 var value = parseInt(columns, 10); 162 if (isNaN(value) || value < 1 || value > 2) { 163 value = 1; 164 } 165 return 'decm-list-cols-' + value; 166 } 167 168 function getResponsiveColumns(params, layout) { 169 var layoutKey = normalizeLayout(layout); 170 var breakpoint = getScreenBreakpoint(); 171 var desktop; 172 var tablet; 173 var phone; 174 175 if (layoutKey === 'list') { 176 desktop = params.list_columns_desktop || params.list_columns || '1'; 177 tablet = params.list_columns_tablet || desktop; 178 phone = params.list_columns_phone || tablet; 179 } else { 180 desktop = params.columns_desktop || params.columns || '3'; 181 tablet = params.columns_tablet || desktop; 182 phone = params.columns_phone || tablet; 183 } 184 185 if (breakpoint === 'phone') { 186 return phone; 187 } 188 if (breakpoint === 'tablet') { 189 return tablet; 190 } 191 return desktop; 192 } 193 194 function updateContainerLayoutClasses($container, layout, params) { 195 var layoutKey = normalizeLayout(layout); 196 var columns = getResponsiveColumns(params, layoutKey); 197 198 $container.removeClass('grid-container cover-container list-container decm-grid-cols-1 decm-grid-cols-2 decm-grid-cols-3 decm-grid-cols-4 decm-list-cols-1 decm-list-cols-2'); 199 200 if (layoutKey === 'cover') { 201 $container.addClass('grid-container cover-container'); 202 } else { 203 $container.addClass(layoutKey + '-container'); 204 if (layoutKey === 'grid') { 205 $container.addClass(getGridColumnsClass(columns)); 206 } else if (layoutKey === 'list') { 207 $container.addClass(getListColumnsClass(columns)); 208 } 209 } 210 211 $container.attr('data-active-layout', layoutKey); 212 } 213 214 function applyResponsiveLayoutParams(params, breakpoint) { 215 breakpoint = breakpoint || getScreenBreakpoint(); 216 params.layout = getResponsiveLayout(params, breakpoint); 217 params.layout_type = getResponsiveLayoutType(params, breakpoint); 218 if (params.layout === 'grid' || params.layout === 'cover') { 219 params.layout_type = ''; 220 } 221 return params; 222 } 223 224 function normalizePagedButtonAlign(align, defaultAlign) { 225 var value = (align || '').toString().trim().toLowerCase(); 226 if (value === 'left' || value === 'center' || value === 'right') { 227 return value; 228 } 229 return defaultAlign || 'left'; 230 } 231 232 function getPagedPaginationLayoutMode(prevAlign, nextAlign, hasPrev, hasNext) { 233 var prev = normalizePagedButtonAlign(prevAlign, 'left'); 234 var next = normalizePagedButtonAlign(nextAlign, 'right'); 235 236 if (hasPrev && hasNext) { 237 if (prev === next) { 238 return 'group-' + prev; 239 } 240 if (prev === 'left' && next === 'right') { 241 return 'split-lr'; 242 } 243 if (prev === 'right' && next === 'left') { 244 return 'split-rl'; 245 } 246 return 'split-mixed'; 247 } 248 if (hasNext && !hasPrev) { 249 return 'single-' + next; 250 } 251 if (hasPrev && !hasNext) { 252 return 'single-' + prev; 253 } 254 return 'empty'; 255 } 256 257 function setImportantStyle(el, prop, value) { 258 if (!el || !el.style) { 259 return; 260 } 261 el.style.setProperty(prop, value, 'important'); 262 } 263 264 function applyPagedPaginationLinkStyle(linkEl, align) { 265 var normalized = normalizePagedButtonAlign(align, 'left'); 266 var col = normalized === 'left' ? '1' : (normalized === 'center' ? '2' : '3'); 267 var self = normalized === 'left' ? 'start' : (normalized === 'center' ? 'center' : 'end'); 268 269 setImportantStyle(linkEl, 'grid-column', col); 270 setImportantStyle(linkEl, 'grid-row', '1'); 271 setImportantStyle(linkEl, 'justify-self', self); 272 setImportantStyle(linkEl, 'float', 'none'); 273 setImportantStyle(linkEl, 'clear', 'none'); 274 setImportantStyle(linkEl, 'margin-left', '0'); 275 setImportantStyle(linkEl, 'margin-right', '0'); 276 } 277 278 function applyPagedPaginationContainerStyles(containerEl, mode) { 279 setImportantStyle(containerEl, 'width', '100%'); 280 setImportantStyle(containerEl, 'gap', '1em'); 281 setImportantStyle(containerEl, 'align-items', 'center'); 282 setImportantStyle(containerEl, 'float', 'none'); 283 setImportantStyle(containerEl, 'clear', 'both'); 284 285 switch (mode) { 286 case 'group-left': 287 setImportantStyle(containerEl, 'display', 'flex'); 288 setImportantStyle(containerEl, 'flex-wrap', 'wrap'); 289 setImportantStyle(containerEl, 'justify-content', 'flex-start'); 290 break; 291 case 'group-center': 292 setImportantStyle(containerEl, 'display', 'flex'); 293 setImportantStyle(containerEl, 'flex-wrap', 'wrap'); 294 setImportantStyle(containerEl, 'justify-content', 'center'); 295 break; 296 case 'group-right': 297 setImportantStyle(containerEl, 'display', 'flex'); 298 setImportantStyle(containerEl, 'flex-wrap', 'wrap'); 299 setImportantStyle(containerEl, 'justify-content', 'flex-end'); 300 break; 301 case 'split-lr': 302 setImportantStyle(containerEl, 'display', 'flex'); 303 setImportantStyle(containerEl, 'flex-wrap', 'wrap'); 304 setImportantStyle(containerEl, 'justify-content', 'space-between'); 305 setImportantStyle(containerEl, 'flex-direction', 'row'); 306 break; 307 case 'split-rl': 308 setImportantStyle(containerEl, 'display', 'flex'); 309 setImportantStyle(containerEl, 'flex-wrap', 'wrap'); 310 setImportantStyle(containerEl, 'justify-content', 'space-between'); 311 setImportantStyle(containerEl, 'flex-direction', 'row-reverse'); 312 break; 313 case 'split-mixed': 314 setImportantStyle(containerEl, 'display', 'grid'); 315 setImportantStyle(containerEl, 'grid-template-columns', 'minmax(0,1fr) auto minmax(0,1fr)'); 316 break; 317 case 'single-left': 318 setImportantStyle(containerEl, 'display', 'flex'); 319 setImportantStyle(containerEl, 'justify-content', 'flex-start'); 320 break; 321 case 'single-center': 322 setImportantStyle(containerEl, 'display', 'flex'); 323 setImportantStyle(containerEl, 'justify-content', 'center'); 324 break; 325 case 'single-right': 326 setImportantStyle(containerEl, 'display', 'flex'); 327 setImportantStyle(containerEl, 'justify-content', 'flex-end'); 328 break; 329 default: 330 break; 331 } 332 } 333 334 function readPagedAlignmentsFromHiddenFields($moduleRoot) { 335 var $hidden = $moduleRoot.find('.hidden_feild'); 336 return { 337 prev: $hidden.find('input[name="paged_prev_button_align"]').val() || 'left', 338 next: $hidden.find('input[name="paged_next_button_align"]').val() || 'right' 339 }; 340 } 341 342 function applyPagedPaginationLayout(target) { 343 var $container = target && target.jquery ? target : window.jQuery(target); 344 if (!$container || !$container.length) { 345 return; 346 } 347 348 $container = $container.closest('.dec-pagination.dec-prev-next').length 349 ? $container.closest('.dec-pagination.dec-prev-next') 350 : $container.filter('.dec-pagination.dec-prev-next'); 351 352 if (!$container.length) { 353 return; 354 } 355 356 var containerEl = $container.get(0); 357 var $prev = $container.find('a.prev'); 358 var $next = $container.find('a.next'); 359 var hasPrev = $prev.length > 0; 360 var hasNext = $next.length > 0; 361 var prevAlign = $container.attr('data-paged-prev-align') || ''; 362 var nextAlign = $container.attr('data-paged-next-align') || ''; 363 364 if (!prevAlign || !nextAlign) { 365 var $moduleRoot = $container.closest('.events-main__container'); 366 if ($moduleRoot.length) { 367 var hiddenAlign = readPagedAlignmentsFromHiddenFields($moduleRoot); 368 prevAlign = prevAlign || hiddenAlign.prev; 369 nextAlign = nextAlign || hiddenAlign.next; 370 } 371 } 372 373 prevAlign = normalizePagedButtonAlign(prevAlign, 'left'); 374 nextAlign = normalizePagedButtonAlign(nextAlign, 'right'); 375 376 var mode = getPagedPaginationLayoutMode(prevAlign, nextAlign, hasPrev, hasNext); 377 applyPagedPaginationContainerStyles(containerEl, mode); 378 379 $prev.each(function () { 380 setImportantStyle(this, 'float', 'none'); 381 setImportantStyle(this, 'clear', 'none'); 382 if (mode === 'split-mixed') { 383 applyPagedPaginationLinkStyle(this, prevAlign); 384 } 385 }); 386 387 $next.each(function () { 388 setImportantStyle(this, 'float', 'none'); 389 setImportantStyle(this, 'clear', 'none'); 390 if (mode === 'split-mixed') { 391 applyPagedPaginationLinkStyle(this, nextAlign); 392 } 393 }); 394 } 395 396 function applyAllPagedPaginationLayouts() { 397 if (!window.jQuery) { 398 return; 399 } 400 window.jQuery('.dec-pagination.dec-prev-next').each(function () { 401 applyPagedPaginationLayout(window.jQuery(this)); 402 }); 403 } 404 405 if (window.jQuery) { 406 window.jQuery(function () { 407 applyAllPagedPaginationLayouts(); 408 }); 409 } else { 410 document.addEventListener('DOMContentLoaded', applyAllPagedPaginationLayouts); 411 } 412 413 window.decmEventDisplayResponsiveLayout = { 414 getScreenBreakpoint: getScreenBreakpoint, 415 getScreenWidth: getScreenWidth, 416 getResponsiveLayout: getResponsiveLayout, 417 getResponsiveLayoutType: getResponsiveLayoutType, 418 getLayoutFromContainer: getLayoutFromContainer, 419 updateContainerLayoutClasses: updateContainerLayoutClasses, 420 applyResponsiveLayoutParams: applyResponsiveLayoutParams, 421 getResponsiveColumns: getResponsiveColumns, 422 readLayoutParamsFromContainer: readLayoutParamsFromContainer, 423 onBreakpointChange: onBreakpointChange, 424 applyPagedPaginationLayout: applyPagedPaginationLayout, 425 applyAllPagedPaginationLayouts: applyAllPagedPaginationLayouts 426 }; 427})(window);
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.