@@ -194,9 +194,7 @@ function option(string $value, string $desc, $attributes = []): string
194194 <?= array_key_exists ('source ' , $ options ) && $ options ['source ' ] === 'Y ' ? 'checked ' : '' ?> />
195195 </label>
196196
197- <noscript>
198197 <button type="submit" class="button">Update Instructions</button>
199- </noscript>
200198</form>
201199
202200<div class="tip">
@@ -254,13 +252,77 @@ function option(string $value, string $desc, $attributes = []): string
254252<?php endif ; ?>
255253
256254 <script>
257- window.onload = function () {
258- let form = document.getElementById("instructions-form")
255+ let currentController = null;
256+
257+ function loadInstructions(url) {
258+ const form = document.querySelector('#instructions-form')
259+ const instructions = document.getElementById('instructions')
260+
261+ if (currentController) {
262+ currentController.abort()
263+ }
264+ currentController = new AbortController()
265+
266+ fetch(url, {signal: currentController.signal})
267+ .then(response => {
268+ if (!response.ok) {
269+ instructions.innerHTML = `<p class="error">Error ${response.status}: Unable to load data.</p>`
270+ throw new Error(`HTTP ${response.status} ${response.statusText}`)
271+ }
272+ return response.text()
273+ })
274+ .then(html => {
275+ const parser = new DOMParser();
276+ const doc = parser.parseFromString(html, 'text/html')
277+
278+ const newForm = doc.querySelector('#instructions-form')
279+ const newInstructions = doc.querySelector('#instructions')
280+
281+ if (newForm && form) form.innerHTML = newForm.innerHTML
282+ if (newInstructions && instructions) instructions.innerHTML = newInstructions.innerHTML
283+
284+ removeUpdateInstructionsButton()
285+
286+ if (window.Prism && typeof Prism.highlightAll === 'function') {
287+ Prism.highlightAll()
288+ }
289+ })
290+ .catch(err => {
291+ if (err.name === 'AbortError') return;
292+ console.error('Request failed:', err)
293+ if (!instructions.querySelector('.error')) {
294+ instructions.innerHTML = `<p class="error">An unexpected error occurred.</p>`
295+ }
296+ });
297+ }
259298
260- form.addEventListener('change', function () {
261- form.submit();
262- });
299+ function removeUpdateInstructionsButton() {
300+ const btn = document.querySelector('#instructions-form button[type="submit"]')
301+ if (btn && window.fetch && window.AbortController) {
302+ btn.remove()
303+ }
263304 }
305+
306+ document.addEventListener('DOMContentLoaded', function () {
307+ removeUpdateInstructionsButton()
308+ })
309+
310+ document.addEventListener('change', function (e) {
311+ if (e.target.closest('#instructions-form')) {
312+ const form = e.target.closest('#instructions-form')
313+ const params = new URLSearchParams(new FormData(form)).toString()
314+ const newUrl = form.action.split('?')[0] + '?' + params
315+
316+ history.pushState({url: newUrl}, '', newUrl)
317+ loadInstructions(newUrl)
318+ }
319+ })
320+
321+ window.addEventListener('popstate', function (e) {
322+ if (e.state && e.state.url) {
323+ loadInstructions(e.state.url)
324+ }
325+ })
264326 </script>
265327
266328<?php
0 commit comments