1/**
2 * CSS Grid Helper for Elementor
3 *
4 * This plugin, created by Mark Harris, is designed for use with the Elementor page builder
5 * in WordPress. It allows you to easily generate CSS code for defining grid layouts
6 * within Elementor using CSS Grid. You can customize the number of rows and columns
7 * and add multiple block sets with specific grid positions.
8 *
9 * Instructions:
10 * 1. Enter the total number of rows and columns in the grid.
11 * 2. Add block sets with specific grid positions (start and end rows/columns).
12 * 3. Click "Generate Block CSS" to generate the CSS code.
13 *
14 * The generated CSS code will be displayed below and can be used in your Elementor custom CSS settings.
15 *
16 * Author: Mark Harris
17 * Version: 1.0
18 *
19 * @package CSS_Grid_Helper
20 * @version 1.0
21 */
22
23// Add a new menu item in the WordPress admin for the CSS Grid Helper
24function css_grid_helper_add_admin_page()
25{
26 add_menu_page(
27 "CSS Grid Helper", // Page title
28 "CSS Grid Helper", // Menu title
29 "manage_options", // Capability
30 "css-grid-helper", // Menu slug
31 "css_grid_helper_admin_page", // Function to display the page
32 "dashicons-layout", // Icon
33 110 // Position
34 );
35}
36
37// Display the admin page content
38function css_grid_helper_admin_page()
39{
40 ?>
41 <div class="wrap">
42 <h1>CSS Grid Helper</h1>
43 <form id="css-grid-helper-form">
44 <h2>Grid Size</h2>
45 <div class="input-group">
46 <label for="grid-rows">Total Rows:</label>
47 <input type="number" id="grid-rows" name="grid_rows" min="1" value="4">
48 </div>
49
50 <div class="input-group">
51 <label for="grid-columns">Total Columns:</label>
52 <input type="number" id="grid-columns" name="grid_columns" min="1" value="4">
53 </div>
54
55 <h2>Block Position and Span</h2>
56 <div class="block-set">
57 <h3>Block Set 1</h3>
58 <div class="input-group">
59 <label for="block-start-row">Start Row:</label>
60 <input type="number" class="block-start-row" name="block_start_row" min="1" value="1">
61 </div>
62
63 <div class="input-group">
64 <label for="block-end-row">End Row:</label>
65 <input type="number" class="block-end-row" name="block_end_row" min="1" value="2">
66 </div>
67
68 <div class="input-group">
69 <label for="block-start-column">Start Column:</label>
70 <input type="number" class="block-start-column" name="block_start_column" min="1" value="1">
71 </div>
72
73 <div class="input-group">
74 <label for="block-end-column">End Column:</label>
75 <input type="number" class="block-end-column" name="block_end_column" min="1" value="2">
76 </div>
77 </div>
78
79 <button id="add-block-set" type="button" class="button button-secondary">Add Block Set</button>
80 <input type="submit" class="button button-primary" value="Generate Block CSS">
81 </form>
82
83 <h2>Generated Block CSS</h2>
84 <textarea id="generated-css" rows="5" readonly></textarea>
85
86 <h2>Grid Preview</h2>
87 <div id="grid-preview" class="grid-container">
88 <!-- Grid items for visualization will be added here -->
89 </div>
90 </div>
91
92 <!-- JavaScript Section -->
93 <script type="text/javascript">
94 jQuery(document).ready(function($) {
95 var blockSetColors = ['#FFA07A', '#20B2AA', '#778899', '#9370DB', '#3CB371', '#FFD700',
96 '#FF6347', '#4682B4', '#DA70D6', '#32CD32', '#FF4500', '#6A5ACD'];
97
98 var totalRows = parseInt($('#grid-rows').val(), 10);
99 var totalColumns = parseInt($('#grid-columns').val(), 10);
100
101 function updateGridContainerStyle() {
102 var gridContainer = $('.grid-container');
103 gridContainer.css({
104 'grid-template-columns': 'repeat(' + totalColumns + ', 50px)'
105 });
106 }
107
108 function validateBlockSetInput() {
109 $('.block-set').each(function() {
110 $(this).find('.block-start-row, .block-end-row').attr('max', totalRows);
111 $(this).find('.block-start-column, .block-end-column').attr('max', totalColumns);
112 });
113 }
114
115 function updateGridPreview() {
116 var gridPreview = $('#grid-preview');
117 gridPreview.empty();
118
119 for (let row = 1; row <= totalRows; row++) {
120 for (let col = 1; col <= totalColumns; col++) {
121 gridPreview.append($('<div class="grid-item">R' + row + ' C' + col + '</div>'));
122 }
123 }
124
125 var css = '';
126 $('.block-set').each(function(index) {
127 var startRow = parseInt($(this).find('.block-start-row').val(), 10);
128 var endRow = parseInt($(this).find('.block-end-row').val(), 10);
129 var startColumn = parseInt($(this).find('.block-start-column').val(), 10);
130 var endColumn = parseInt($(this).find('.block-end-column').val(), 10);
131
132 var blockColor = blockSetColors[index % blockSetColors.length];
133
134 var blockCss =
135 "/* Block " + (index + 1) + " */\n" +
136 "selector {\n" + // Replace "selector" with your custom selector
137 " grid-row: " + startRow + "/" + (endRow + 1) + ";\n" +
138 " grid-column: " + startColumn + "/" + (endColumn + 1) + ";\n" +
139 "}\n";
140 css += blockCss;
141
142 $('#grid-preview .grid-item').each(function() {
143 var itemRow = parseInt($(this).text().match(/R(\d+)/)[1], 10);
144 var itemCol = parseInt($(this).text().match(/C(\d+)/)[1], 10);
145
146 if (itemRow >= startRow && itemRow <= endRow && itemCol >= startColumn && itemCol <= endColumn) {
147 $(this).css('background-color', blockColor);
148 }
149 });
150 });
151
152 $('#generated-css').val(css);
153 updateGridContainerStyle();
154 }
155
156 function updateBlockSetLabels() {
157 $('.block-set').each(function(index) {
158 var blockColor = blockSetColors[index % blockSetColors.length];
159 $(this).find('h3').html('Block Set ' + (index + 1) + ' <span class="color-indicator" style="background-color: ' + blockColor + ';"></span>');
160 });
161 }
162
163 function addBlockSet() {
164 var blockSet = $('.block-set').first().clone();
165 blockSet.find('input').val('');
166 $('.block-set').last().after(blockSet);
167
168 updateBlockSetLabels();
169 updateGridPreview();
170 validateBlockSetInput();
171 }
172
173 $('#add-block-set').click(function() {
174 addBlockSet();
175 });
176
177 $('#grid-rows, #grid-columns').change(function() {
178 totalRows = parseInt($('#grid-rows').val(), 10);
179 totalColumns = parseInt($('#grid-columns').val(), 10);
180
181 validateBlockSetInput();
182 updateGridPreview();
183 });
184
185 $('#css-grid-helper-form').submit(function(event) {
186 event.preventDefault();
187 updateGridPreview();
188 });
189
190 updateBlockSetLabels();
191 updateGridPreview();
192 validateBlockSetInput();
193 });
194</script>
195
196
197 <!-- CSS Section -->
198 <style type="text/css">
199 .wrap {
200 margin: 20px;
201 }
202 .input-group {
203 margin-bottom: 15px;
204 }
205 label {
206 display: block;
207 margin-bottom: 5px;
208 }
209 input[type="number"] {
210 width: 50px;
211 }
212 .button-secondary {
213 margin-left: 10px;
214 }
215 #generated-css {
216 width: 100%;
217 font-family: monospace;
218 background-color: #f7f7f7;
219 border: 1px solid #ccc;
220 padding: 10px;
221 }
222 .grid-container {
223 margin-top: 20px;
224 max-width: 100%;
225 display: grid;
226 grid-template-columns: repeat(4, 50px);
227 grid-gap: 4px;
228 background-color: #fff;
229 padding: 4px;
230 }
231 .grid-container .grid-item {
232 background-color: rgba(255, 255, 255, 0.8);
233 border: 1px solid rgba(0, 0, 0, 0.8);
234 padding: 8px;
235 font-size: 14px;
236 text-align: center;
237 overflow: hidden;
238 transition: background-color 0.3s;
239 }
240 .block-set {
241 background-color: #f0f0f0;
242 border: 1px solid #ccc;
243 padding: 10px;
244 margin-top: 20px;
245 }
246 .block-set h3 {
247 margin: 0;
248 padding: 0;
249 font-size: 16px;
250 }
251 .color-indicator {
252 display: inline-block;
253 width: 15px;
254 height: 15px;
255 border-radius: 50%;
256 margin-left: 10px;
257 vertical-align: middle;
258 }
259 </style>
260 <?php
261}
262
263add_action("admin_menu", "css_grid_helper_add_admin_page");