1// Function to add the calculator to the admin menu
2function ft_calculator_admin_menu()
3{
4 add_menu_page(
5 "Fluid Typography Calculator", // Page title
6 "Typography Calculator", // Menu title
7 "manage_options", // Capability
8 "fluid-typography-calculator", // Menu slug
9 "ft_calculator_page" // Function that displays the page content
10 );
11}
12
13add_action("admin_menu", "ft_calculator_admin_menu");
14
15// Function that generates the calculator page
16function ft_calculator_page() {
17 // Initialize the $useRem variable at the start of the function
18 $useRem = false;
19
20 echo '<div class="wrap"><h1>Fluid Typography Calculator</h1>';
21
22 // Basic styles for the form and output
23 echo '<style>
24 .ft-form input[type="number"] {
25 width: 100px;
26 padding: 8px;
27 margin: 4px 0;
28 box-sizing: border-box;
29 border: 1px solid #ccc;
30 border-radius: 4px;
31 }
32 .ft-form label {
33 font-weight: bold;
34 }
35 .ft-form div {
36 margin-bottom: 10px;
37 }
38 .ft-form textarea {
39 width: 100%; // Adjust this to your preference
40 height: 150px; // Or any height that suits your layout
41 padding: 8px;
42 border: 1px solid #ccc;
43 border-radius: 4px;
44 margin-top: 10px;
45 }
46
47 #cssOutput, #cssVariablesOutput {
48 width: 50%; // Makes the textarea take up the full width of its container
49 max-width: 50%; // You can adjust this as needed
50 min-width: 300px; // Ensures a minimum width
51 padding: 8px;
52 border: 1px solid #ccc;
53 border-radius: 4px;
54 margin-top: 10px;
55 }
56
57 .ft-form button {
58 background-color: #4CAF50;
59 color: white;
60 padding: 10px 15px;
61 border: none;
62 border-radius: 4px;
63 cursor: pointer;
64 }
65 .ft-form button:hover {
66 background-color: #45a049;
67 }
68 .grid-container {
69 display: grid;
70 grid-template-columns: repeat(5, 1fr);
71 gap: 10px;
72 }
73 </style>';
74
75// Initialize variables
76 $rootFontSize = isset($_POST["rootFontSize"]) ? $_POST["rootFontSize"] : 16;
77 $defaultValues = [
78 "h1" => [
79 "MinWidth" => 380,
80 "MinFontSize" => 29,
81 "MaxWidth" => 1600,
82 "MaxFontSize" => 68,
83 ],
84 "h2" => [
85 "MinWidth" => 380,
86 "MinFontSize" => 24,
87 "MaxWidth" => 1600,
88 "MaxFontSize" => 51,
89 ],
90 "h3" => [
91 "MinWidth" => 380,
92 "MinFontSize" => 20,
93 "MaxWidth" => 1600,
94 "MaxFontSize" => 38,
95 ],
96 "h4" => [
97 "MinWidth" => 380,
98 "MinFontSize" => 17,
99 "MaxWidth" => 1600,
100 "MaxFontSize" => 29,
101 ],
102 "h5" => [
103 "MinWidth" => 380,
104 "MinFontSize" => 14,
105 "MaxWidth" => 1600,
106 "MaxFontSize" => 22,
107 ],
108 "h6" => [
109 "MinWidth" => 380,
110 "MinFontSize" => 12,
111 "MaxWidth" => 1600,
112 "MaxFontSize" => 16,
113 ],
114 "body" => [
115 "MinWidth" => 380,
116 "MinFontSize" => 16,
117 "MaxWidth" => 1600,
118 "MaxFontSize" => 24,
119 ],
120 "p" => [
121 "MinWidth" => 380,
122 "MinFontSize" => 16,
123 "MaxWidth" => 1600,
124 "MaxFontSize" => 24,
125 ],
126 ];
127
128 $cssOutput = ""; // Initialize traditional CSS output string
129 $cssVariablesOutput = ""; // Initialize CSS variables output string
130
131 // Check if form is submitted
132 if ($_SERVER["REQUEST_METHOD"] == "POST") {
133 $useRem = isset($_POST["unitToggle"]) && $_POST["unitToggle"] === 'on';
134 // Security check using nonce
135 if (!isset($_POST["ft_calculator_nonce_field"]) || !wp_verify_nonce($_POST["ft_calculator_nonce_field"], "ft_calculator_action")) {
136 echo "<p>Security check failed. Please try again.</p>";
137 return;
138 }
139
140foreach (["h1", "h2", "h3", "h4", "h5", "h6", "body", "p"] as $tag) {
141 $minWidth = $_POST[$tag . "MinWidth"]; // In pixels
142 $minFontSizePx = $_POST[$tag . "MinFontSize"]; // In pixels or REM based on $useRem
143 $maxWidth = $_POST[$tag . "MaxWidth"]; // In pixels
144 $maxFontSizePx = $_POST[$tag . "MaxFontSize"]; // In pixels or REM based on $useRem
145
146 // Handle unit conversion
147 if ($useRem) {
148 // Convert REM to Pixels for internal calculation
149 $minFontSizePx *= $rootFontSize;
150 $maxFontSizePx *= $rootFontSize;
151 }
152
153 // Convert pixel values to REM for CSS generation
154 $minFontSize = $minFontSizePx / $rootFontSize; // In rem
155 $maxFontSize = $maxFontSizePx / $rootFontSize; // In rem
156
157 // Convert widths from px to vw (assuming 1rem = rootFontSize px)
158 $minWidthVW = $minWidth / $rootFontSize; // In vw
159 $maxWidthVW = $maxWidth / $rootFontSize; // In vw
160
161 // Calculate the CSS
162 $vwUnit =
163 (($maxFontSize - $minFontSize) / ($maxWidthVW - $minWidthVW)) *
164 100;
165 $constant = $minFontSize - ($vwUnit * $minWidthVW) / 100;
166
167 // Format to a maximum of 5 decimal places
168 $vwUnitFormatted = number_format($vwUnit, 5, ".", "");
169 $constantFormatted = number_format($constant, 5, ".", "");
170
171 // Add to traditional CSS output
172 $cssOutput .=
173 "{$tag} {font-size: clamp(" .
174 $minFontSize .
175 "rem, " .
176 $constantFormatted .
177 "rem + " .
178 $vwUnitFormatted .
179 "vw, " .
180 $maxFontSize .
181 "rem);}\n";
182
183 // Add to CSS variables output
184 $cssVariablesOutput .=
185 " --{$tag}-font-size: clamp(" .
186 $minFontSize .
187 "rem, " .
188 $constantFormatted .
189 "rem + " .
190 $vwUnitFormatted .
191 "vw, " .
192 $maxFontSize .
193 "rem);\n";
194 }
195
196 // Wrap CSS variables in a :root selector
197 $cssVariablesOutput = ":root {\n" . $cssVariablesOutput . "}\n";
198 }
199
200// Display the form
201echo '<form class="ft-form" method="post">';
202wp_nonce_field("ft_calculator_action", "ft_calculator_nonce_field");
203
204echo '<div>
205 <label for="rootFontSize">Root HTML Font Size (px):</label>
206 <input type="number" id="rootFontSize" name="rootFontSize" required value="' . htmlspecialchars($rootFontSize) . '">
207 </div>
208 <div>
209 <label for="unitToggle">Use REM Units for Font Size:</label>
210 <input type="checkbox" id="unitToggle" name="unitToggle" ' . ($useRem ? 'checked' : '') . ' onchange="toggleUnits()">
211 </div>';
212
213echo '<div class="grid-container">
214 <div><strong>Tag</strong></div>
215 <div><strong>Min Width (px)</strong></div>
216 <div><strong>Min Font Size (' . ($useRem ? 'rem' : 'px') . ')</strong></div>
217 <div><strong>Max Width (px)</strong></div>
218 <div><strong>Max Font Size (' . ($useRem ? 'rem' : 'px') . ')</strong></div>';
219
220// Display input fields for each tag
221foreach (["h1", "h2", "h3", "h4", "h5", "h6", "body", "p"] as $tag) {
222 $minWidthValue = isset($_POST[$tag . "MinWidth"]) ? $_POST[$tag . "MinWidth"] : $defaultValues[$tag]["MinWidth"];
223 $minFontSizeValue = isset($_POST[$tag . "MinFontSize"]) ? $_POST[$tag . "MinFontSize"] : $defaultValues[$tag]["MinFontSize"];
224 $maxWidthValue = isset($_POST[$tag . "MaxWidth"]) ? $_POST[$tag . "MaxWidth"] : $defaultValues[$tag]["MaxWidth"];
225 $maxFontSizeValue = isset($_POST[$tag . "MaxFontSize"]) ? $_POST[$tag . "MaxFontSize"] : $defaultValues[$tag]["MaxFontSize"];
226
227echo "<div><strong>{$tag}</strong></div>
228 <div><input type='number' id='{$tag}MinWidth' name='{$tag}MinWidth' class='unit-input' required value='{$minWidthValue}'></div>
229 <div><input type='number' id='{$tag}MinFontSize' name='{$tag}MinFontSize' class='unit-input' step='0.01' required value='{$minFontSizeValue}'></div>
230 <div><input type='number' id='{$tag}MaxWidth' name='{$tag}MaxWidth' class='unit-input' required value='{$maxWidthValue}'></div>
231 <div><input type='number' id='{$tag}MaxFontSize' name='{$tag}MaxFontSize' class='unit-input' step='0.01' required value='{$maxFontSizeValue}'></div>";
232}
233
234
235echo '</div><input type="submit" value="Generate CSS"></form>';
236
237
238 // Display the traditional CSS output
239 if (!empty($cssOutput)) {
240 echo "<h2>Generated CSS:</h2>";
241 echo '<textarea id="cssOutput" rows="10">' . htmlspecialchars($cssOutput) . "</textarea><br>";
242 echo '<button onclick="copyToClipboard(\'cssOutput\')">Copy CSS</button>';
243 }
244
245 // Display the CSS variables output
246 if (!empty($cssVariablesOutput)) {
247 echo "<h2>Generated CSS Variables:</h2>";
248 echo '<textarea id="cssVariablesOutput" rows="10">' . htmlspecialchars($cssVariablesOutput) . "</textarea><br>";
249 echo '<button onclick="copyToClipboard(\'cssVariablesOutput\')">Copy CSS Variables</button>';
250 }
251
252 // JavaScript for copy to clipboard functionality and unit conversion
253 echo '<script>
254 function copyToClipboard(elementId) {
255 var copyText = document.getElementById(elementId);
256 copyText.select();
257 document.execCommand("copy");
258 }
259
260function toggleUnits() {
261 var useRem = document.getElementById("unitToggle").checked;
262 var rootFontSize = parseFloat(document.getElementById("rootFontSize").value);
263 var fontSizeElements = document.querySelectorAll(".unit-input"); // Class for font size inputs
264
265 fontSizeElements.forEach(function(element) {
266 if (element.id.endsWith("MinFontSize") || element.id.endsWith("MaxFontSize")) {
267 var value = parseFloat(element.value);
268 if (!isNaN(value)) {
269 if (useRem) {
270 element.value = (value / rootFontSize).toFixed(2); // Convert to REM
271 } else {
272 element.value = (value * rootFontSize).toFixed(0); // Convert to Pixels
273 }
274 }
275 }
276 });
277}
278
279 </script>';
280
281 echo "</div>";
282}
283
284
285// Define the function for the fluid typography calculator
286function fluid_typography_calculator() {
287 // Call the existing function to display the fluid typography calculator
288 ft_calculator_page();
289}
290
291// Add the shortcode
292add_shortcode('Fluid_calc', 'fluid_typography_calculator');