{-# language OverloadedStrings #-} {-# language QuasiQuotes #-} module FlexTask.Processing.JavaScript ( setDefaultsJS, triggerDefaults, lockForm, triggerLockForm, ) where import Data.Text (Text) import Text.Julius (JavascriptUrl, julius, rawJS) import FlexTask.Processing.Text (formatForJS) setDefaultsJS :: JavascriptUrl url setDefaultsJS :: forall url. JavascriptUrl url setDefaultsJS = [julius| function setDefaults(fieldNames, values) { const handlers = { radio: (field, value) => { field.checked = field.value == value; }, select: (field, value) => { Array.from(field.options).forEach(opt => { if (Array.isArray(value)) { opt.selected = value.includes(opt.value); } else { opt.selected = (opt.value === value); } }); }, checkbox: (field, value) => { if (Array.isArray(value)) { field.checked = value.includes(field.value); } else { field.checked = (field.value == value); } }, default: (field, value) => { if (value !== "Missing" && value !== "None") { field.value = value; } } }; const getHandler = field => { const t = field.getAttribute("type")?.toLowerCase(); const tag = field.tagName.toLowerCase(); if (t === "radio") return "radio"; if (tag === "select") return "select"; if (t === "checkbox") return "checkbox"; if (t === "hidden") return null; // skip hidden return "default"; }; if (fieldNames.length == values.length) { fieldNames.forEach((names, i) => { const value = values[i]; if (names.length > 1) { names.forEach((name, j) => { document.getElementsByName(name).forEach(field => { const key = getHandler(field); if (key) handlers[key](field, value[j]); }); }); } else { const name = names[0]; const fields = Array.from(document.getElementsByName(name)); fields.forEach((field, j) => { let nextValue; const key = getHandler(field); if (Array.isArray(value)) { if (key === "checkbox" || key === "select") { nextValue = value; } else { nextValue = value[j]; } } else { nextValue = value; } if (key) handlers[key](field, nextValue); }); } }); } } |] triggerDefaults :: [[Text]] -> Text -> JavascriptUrl url triggerDefaults :: forall url. [[Text]] -> Text -> JavascriptUrl url triggerDefaults [[Text]] names Text values = [julius| window.onload = setDefaults(#{rawJS (show names)}, #{rawJS (formatForJS values)}); |] lockForm :: JavascriptUrl url lockForm :: forall url. JavascriptUrl url lockForm = [julius| function lockForm(fieldNames) { fieldNames.forEach(name => { Array.from(document.getElementsByName(name)) .forEach(elem => { if (elem.getAttribute("type")?.toLowerCase() === "radio" || elem.getAttribute("type")?.toLowerCase() === "checkbox" || elem.tagName.toLowerCase() === "select"){ elem.disabled = true; } else { elem.readOnly = true; } }); }); };|] triggerLockForm :: [[Text]] -> JavascriptUrl url triggerLockForm :: forall url. [[Text]] -> JavascriptUrl url triggerLockForm [[Text]] fieldNames = [julius|window.onload = lockForm(#{rawJS $ show $ concat fieldNames});|]