PluginProbe ʕ •ᴥ•ʔ
FrontBlocks for Gutenberg/GeneratePress / 1.3.5
FrontBlocks for Gutenberg/GeneratePress v1.3.5
trunk 0.2.0 0.2.1 0.2.2 0.2.3 0.2.4 0.2.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 ci-artifacts
frontblocks / assets / container-edge-alignment / frontblocks-edge-alignment-frontend.js
frontblocks / assets / container-edge-alignment Last commit date
frontblocks-edge-alignment-frontend.js 7 months ago frontblocks-edge-alignment-option.jsx 1 month ago frontblocks-edge-alignment.css 7 months ago frontblocks-edge-alignment.js 7 months ago
frontblocks-edge-alignment-frontend.js
159 lines
1 /**
2 * Container Edge Alignment - Frontend Script
3 *
4 * Calculates and applies dynamic margins to containers with edge alignment.
5 * This ensures the "other side" stays exactly where it was while one side extends to the edge.
6 *
7 * @package FrontBlocks
8 */
9
10 (function() {
11 'use strict';
12
13 /**
14 * Calculate and apply edge alignment margins.
15 */
16 function applyEdgeAlignmentMargins() {
17 // Get all containers with edge alignment.
18 const edgeContainers = document.querySelectorAll('.frbl-edge-left, .frbl-edge-right');
19
20 if ( ! edgeContainers.length ) {
21 return;
22 }
23
24 edgeContainers.forEach( function( container ) {
25 // Skip if already processed.
26 if ( container.hasAttribute( 'data-frbl-processed' ) ) {
27 return;
28 }
29
30 // Get the container's original width (before edge alignment).
31 // We need to temporarily remove the classes to get the original computed width.
32 const hasLeft = container.classList.contains( 'frbl-edge-left' );
33 const hasRight = container.classList.contains( 'frbl-edge-right' );
34 const hasBoth = hasLeft && hasRight;
35
36 // If both sides, just make it full width.
37 if ( hasBoth ) {
38 container.style.marginLeft = '0';
39 container.style.marginRight = '0';
40 container.style.width = '100vw';
41 container.style.maxWidth = '100vw';
42 container.setAttribute( 'data-frbl-processed', 'true' );
43 return;
44 }
45
46 // Temporarily remove edge classes to get original width.
47 container.classList.remove( 'frbl-edge-left', 'frbl-edge-right' );
48
49 // Also temporarily clear any inline styles that might interfere.
50 const originalInlineStyles = {
51 marginLeft: container.style.marginLeft,
52 marginRight: container.style.marginRight,
53 width: container.style.width,
54 maxWidth: container.style.maxWidth
55 };
56 container.style.marginLeft = '';
57 container.style.marginRight = '';
58 container.style.width = '';
59 container.style.maxWidth = '';
60
61 // Force reflow to get accurate measurements.
62 void container.offsetWidth;
63
64 // Get the container's original computed width and margins.
65 const computedStyle = window.getComputedStyle( container );
66 const originalWidth = parseFloat( computedStyle.maxWidth ) || parseFloat( computedStyle.width );
67 const originalMarginLeft = parseFloat( computedStyle.marginLeft );
68 const originalMarginRight = parseFloat( computedStyle.marginRight );
69
70 // Get viewport width.
71 const viewportWidth = window.innerWidth;
72
73 // Restore classes.
74 if ( hasLeft ) {
75 container.classList.add( 'frbl-edge-left' );
76 }
77 if ( hasRight ) {
78 container.classList.add( 'frbl-edge-right' );
79 }
80
81 // IMPORTANT: Only apply edge alignment if viewport is wider than container.
82 // On small screens (mobile, tablet), disable the effect to avoid overflow.
83 if ( viewportWidth <= originalWidth ) {
84 // Viewport is too small, reset to normal centered layout.
85 container.style.marginLeft = '';
86 container.style.marginRight = '';
87 container.style.width = '';
88 container.style.maxWidth = '';
89 container.setAttribute( 'data-frbl-processed', 'true' );
90 return;
91 }
92
93 // Calculate the margin that was on each side (when centered with auto).
94 // If margins are "auto", they will show as equal values.
95 // Formula: (viewport - containerWidth) / 2.
96 let sideMargin;
97
98 // If margins are already calculated (not auto), use them.
99 if ( originalMarginLeft > 0 && originalMarginRight > 0 && Math.abs( originalMarginLeft - originalMarginRight ) < 2 ) {
100 // Margins are equal, use the actual value.
101 sideMargin = originalMarginLeft;
102 } else {
103 // Calculate from viewport and width.
104 sideMargin = ( viewportWidth - originalWidth ) / 2;
105 }
106
107 // Apply the calculated values.
108 if ( hasLeft ) {
109 // Remove left side, keep right side fixed.
110 container.style.marginLeft = '0';
111 container.style.marginRight = sideMargin + 'px';
112 container.style.width = ( viewportWidth - sideMargin ) + 'px';
113 container.style.maxWidth = ( viewportWidth - sideMargin ) + 'px';
114 } else if ( hasRight ) {
115 // Remove right side, keep left side fixed.
116 container.style.marginRight = '0';
117 container.style.marginLeft = sideMargin + 'px';
118 container.style.width = ( viewportWidth - sideMargin ) + 'px';
119 container.style.maxWidth = ( viewportWidth - sideMargin ) + 'px';
120 }
121
122 // Mark as processed.
123 container.setAttribute( 'data-frbl-processed', 'true' );
124 });
125 }
126
127 /**
128 * Recalculate margins on window resize.
129 */
130 function handleResize() {
131 // Remove processed flag to allow recalculation.
132 const edgeContainers = document.querySelectorAll('.frbl-edge-left, .frbl-edge-right');
133 edgeContainers.forEach( function( container ) {
134 container.removeAttribute( 'data-frbl-processed' );
135 });
136
137 // Recalculate.
138 applyEdgeAlignmentMargins();
139 }
140
141 // Initialize on DOM ready.
142 if ( document.readyState === 'loading' ) {
143 document.addEventListener( 'DOMContentLoaded', applyEdgeAlignmentMargins );
144 } else {
145 applyEdgeAlignmentMargins();
146 }
147
148 // Recalculate on window resize (debounced).
149 let resizeTimer;
150 window.addEventListener( 'resize', function() {
151 clearTimeout( resizeTimer );
152 resizeTimer = setTimeout( handleResize, 250 );
153 });
154
155 // Also run after page load to catch any late-loading content.
156 window.addEventListener( 'load', applyEdgeAlignmentMargins );
157 })();
158
159