@hytts/hytts
Advanced tools
Comparing version 0.2.3 to 0.2.4
@@ -298,17 +298,28 @@ "use strict"; | ||
} | ||
} else { | ||
forEachFormField(form, markAsTouched); | ||
forEachFormField(form, updateValidationErrorVisibility); | ||
} | ||
} | ||
async function validateForm({ href, form }) { | ||
await updateFrame(getFormFrameId(form), async (frame, signal) => | ||
extractFrameFromResponse( | ||
frame, | ||
await fetchFrame(frame, href, { | ||
method: "POST", | ||
body: createFormRequestBody(form), | ||
signal, | ||
headers: { "x-hy-validate-form": "true" }, | ||
}), | ||
async function updateForm({ href, form, additionalData, markFieldsAsTouched }) { | ||
let validationState = void 0; | ||
await updateFrame(getFormFrameId(form), async (frame, signal) => { | ||
const response = await fetchFrame(frame, href, { | ||
method: "POST", | ||
body: createFormRequestBody(form, additionalData), | ||
signal, | ||
), | ||
); | ||
headers: { "x-hy-validate-form": "true" }, | ||
}); | ||
validationState = response.status < 300 ? "valid" : "invalid"; | ||
const newFrame = await extractFrameFromResponse(frame, response, signal); | ||
if (markFieldsAsTouched === "existing") { | ||
forEachFormField(form, markAsTouched); | ||
} | ||
return newFrame; | ||
}); | ||
if (markFieldsAsTouched === "all") { | ||
forEachFormField(form, markAsTouched); | ||
} | ||
forEachFormField(form, updateValidationErrorVisibility); | ||
return validationState; | ||
} | ||
@@ -322,7 +333,3 @@ function interceptForms() { | ||
e.preventDefault(); | ||
void submitForm({ | ||
href: form.action, | ||
form, | ||
frameId: options.hyFrame, | ||
}); | ||
void submitForm({ href: form.action, form, frameId: options.hyFrame }); | ||
}); | ||
@@ -335,7 +342,20 @@ document.addEventListener("change", (e) => { | ||
e.preventDefault(); | ||
void validateForm({ | ||
href: options.hyValidate, | ||
form, | ||
}); | ||
void updateForm({ href: options.hyValidate, form }); | ||
}); | ||
document.addEventListener("focusin", (e) => { | ||
if (isFormField(e.target)) { | ||
markAsTouched(e.target); | ||
storeServerValue(e.target); | ||
} | ||
}); | ||
document.addEventListener("focusout", (e) => { | ||
if (isFormField(e.target) && stillHasServerValue(e.target)) { | ||
updateValidationErrorVisibility(e.target); | ||
} | ||
}); | ||
document.addEventListener("input", (e) => { | ||
if (isFormField(e.target)) { | ||
showValidationError(e.target, false); | ||
} | ||
}); | ||
function getForm(e) { | ||
@@ -345,12 +365,15 @@ const form = | ||
? e.target | ||
: e.target && "form" in e.target && e.target.form instanceof HTMLFormElement | ||
: isFormField(e.target) | ||
? e.target.form | ||
: void 0; | ||
if (e.defaultPrevented || !form) { | ||
const options = form?.dataset; | ||
if ( | ||
e.defaultPrevented || | ||
!form || | ||
form.method.toUpperCase() !== "POST" || | ||
!form.action || | ||
!options?.hyValidate | ||
) { | ||
return [void 0, void 0]; | ||
} | ||
const options = form.dataset; | ||
if (form.method.toUpperCase() !== "POST" || !form.action || !options?.hyValidate) { | ||
return [void 0, void 0]; | ||
} | ||
return [form, options]; | ||
@@ -364,3 +387,3 @@ } | ||
} | ||
return params.toString() + (additionalData ? `"&${additionalData}` : ""); | ||
return params.toString() + (additionalData ? `&${additionalData}` : ""); | ||
} | ||
@@ -370,2 +393,40 @@ function getFormFrameId(form) { | ||
} | ||
function updateValidationErrorVisibility(field) { | ||
const showError = !isValid(field) && isTouched(field); | ||
showValidationError(field, showError); | ||
} | ||
function showValidationError(field, showError) { | ||
const errorShown = "invalid"; | ||
const errorHidden = ""; | ||
field.setCustomValidity(showError ? errorShown : errorHidden); | ||
} | ||
function isValid(field) { | ||
return field.getAttribute("aria-invalid") !== "true"; | ||
} | ||
function markAsTouched(field) { | ||
field.setAttribute("data-hy-view-touched", "true"); | ||
} | ||
function isTouched(field) { | ||
return field.getAttribute("data-hy-view-touched") === "true"; | ||
} | ||
function storeServerValue(field) { | ||
field.setAttribute("data-hy-server-value", field.value); | ||
} | ||
function stillHasServerValue(field) { | ||
return field.getAttribute("data-hy-server-value") === field.value; | ||
} | ||
function forEachFormField(form, action) { | ||
for (const e of form.elements) { | ||
if (isFormField(e)) { | ||
action(e); | ||
} | ||
} | ||
} | ||
function isFormField(element) { | ||
return ( | ||
element instanceof HTMLInputElement || | ||
element instanceof HTMLTextAreaElement || | ||
element instanceof HTMLSelectElement | ||
); | ||
} | ||
@@ -419,4 +480,3 @@ // source/browser/navigation.browser.ts | ||
break; | ||
case "POST": { | ||
let bodyParams = options.hyBody; | ||
case "POST": | ||
if (options.hyForm) { | ||
@@ -427,14 +487,19 @@ const form = document.getElementById(options.hyForm); | ||
} | ||
bodyParams = createFormRequestBody(form, bodyParams); | ||
void updateForm({ | ||
href, | ||
form, | ||
additionalData: options.hyBody, | ||
markFieldsAsTouched: options.hyMarkAsTouched, | ||
}); | ||
} else { | ||
void navigateTo({ | ||
frameId: options.hyFrame, | ||
href, | ||
httpMethod: "POST", | ||
bodyParams: options.hyBody, | ||
updateHistory: !!options.hyUpdateHistory, | ||
historyHref: options.hyUpdateHistory, | ||
}); | ||
} | ||
void navigateTo({ | ||
frameId: options.hyFrame, | ||
href, | ||
httpMethod: "POST", | ||
bodyParams, | ||
updateHistory: !!options.hyUpdateHistory, | ||
historyHref: options.hyUpdateHistory, | ||
}); | ||
break; | ||
} | ||
case void 0: | ||
@@ -441,0 +506,0 @@ break; |
{ | ||
"name": "@hytts/hytts", | ||
"version": "0.2.3", | ||
"version": "0.2.4", | ||
"author": "Axel Habermaier", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
210376
5246