diff --git a/src/FMInput.ts b/src/FMInput.ts
index a64ba61..7a23711 100644
--- a/src/FMInput.ts
+++ b/src/FMInput.ts
@@ -1,4 +1,5 @@
import FormManager from "./FormManager"
+import { realType } from "./Functions"
export default class FMInput {
@@ -10,18 +11,18 @@ export default class FMInput {
this.element = element as HTMLInputElement
this.form = form
this.required = element.hasAttribute("required")
-
- // Set element value to it's default one
- this.setToDefault()
}
/**
* Set the element Value
*
- * @param {*} value
+ * @param {*} value the input value
+ *
+ * _hint: pass it through this.formatValue_
+ *
* @memberof FMInput
*/
- setValue(value: any) {
+ public setValue(value: any) {
this.element.value = value
}
@@ -31,41 +32,24 @@ export default class FMInput {
* @returns {*} the value
* @memberof FMInput
*/
- getValue(): any {
+ public getValue(): any {
return this.formatValue(this.element.value)
}
/**
- * Format the value
- * ex: if the value is "1" it will return the value as a number 1
+ * Format the value into a usable one by the module
+ *
+ * for elements like `select` if the value don't correspond to something
+ * it will return the default `value`
*
- * @protected
* @param {*} value
* @returns {*}
* @memberof FMInput
*/
- protected formatValue(value: any): any {
+ public formatValue(value: any): any {
// if the value is a number return it as a number obj
- if (!isNaN(Number(value))) return Number(value)
- return value
-
- }
-
- getDefault(args?: string): any {
- // if arg is set and startsWith run: run the function in it
- if (args && args.startsWith("run:")) {
- args = args.split("run:")[1]
- return eval(args)
- }
- return args
- }
-
- setToDefault() {
- if (this.element.hasAttribute("data-default")) {
- return this.setValue(this.getDefault(this.element.dataset.default))
- }
- return this.setValue(this.getDefault(""))
+ return realType(value)
}
/**
@@ -74,7 +58,7 @@ export default class FMInput {
* @returns {string}
* @memberof FMInput
*/
- getName(): string {
+ public getName(): string {
// while we search for inputs containing [name] we search for the input real name in [name] or [data-name]
// (Allow other inputs to play with inputs)
let attr = this.element.getAttribute("name") || this.element.dataset.name;
@@ -88,16 +72,11 @@ export default class FMInput {
* @returns {boolean}
* @memberof FMInput
*/
- verify(): boolean {
+ public verify(): boolean {
let val: any = this.getValue()
// if element is required and value is undefined retur false
if (this.required && (val === undefined || val === null || val === "")) return false
- // check regex
- const regex = this.element.dataset.regex
- if(regex) {
- return new RegExp(regex, 'g').test(val + "")
- }
return true
}
}
diff --git a/src/FormManager.ts b/src/FormManager.ts
index d2c24a0..2a9c8e6 100644
--- a/src/FormManager.ts
+++ b/src/FormManager.ts
@@ -1,5 +1,7 @@
-import { InputArrayInterface, FMAssignInterface } from './Interfaces';
+import { InputArray, InputAssignment } from './Interfaces';
import FMInput from "./FMInput"
+import AttributesManager from './AttributesManager';
+import { FMAttributeListeners } from './FMAttribute';
/*!
* FormManager by DZEIO's team
@@ -7,100 +9,6 @@ import FMInput from "./FMInput"
* https://dze.io
*/
-/**
- *
- * `datalist` upgrade:
- * the value submitted won't be the `value` attribute but the `data-value` attribute
- * a `data-strict` attribute if set will return undefined if input value is not from data-value else it will return the input value if not foudn in options
- * ex:
- * ```html
- *
- *
- * ```
- * **ATTENTION if multiple `option` have the same `value` attribute the submitted value will be the first one**
- *
- *
- * a `data-ignore` attribute:
- * the input with the data-ignore won't send datas to server _still need the `name` attribute_
- * awesome for usage with `data-autoset`
- *
- * a `data-regex` attribute:
- * when the element is getting verified it will be passed through the regex
- * ex:
- * ```html
- *
- *
- *
- *
- *
- * ```
- * _please note that you still have to verify that server-side_
- *
- *
- * a `data-default` attribute:
- * if the value is not something controlable by html it will be set by here
- * depending on the input type different defaults are possibles
- * ex: `date` `datetime` `time` if it's set it will be the current time
- * ```html
- *
- *
- *
- * ```
- *
- *
- * a `data-autoset` attribute:
- * this attribute will change it's value regarding other inputs
- * DON'T name any input `x` as it will break the repeat element
- * (you SHOULD use `readonly` or `disabled` attribute with it)
- * ex:
- * ```html
- *
- *
- * ```
- * the test input should always contain `testing-autoset-(the value of input)
- *
- *
- * a `repeat` type:
- * container: `.fm-repeat` with a name attribute
- * template (in container): `.fmr-template`
- * element (DO NOT PLACE IT YOURSELF) (in container): `.fmr-element`
- * add button (in container): `.fmr-add`
- * delete button (in template): `.fmr-del`
- *
- * input *MUST* have `data-name` and *NOT* `name` attributes
- * if `data-default` or `data-autoset` contains `{x}` it will be replaced by the index
- *
- * ```html
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- * ```
- *
- *
- * TODO:
- * check if input has attribute `form` and that the value is the current form id
- * if so add it to current form
- */
-
-
/**
* Manager for Forms
*
@@ -113,19 +21,19 @@ export default class FormManager {
* List of inputs
*
* @private
- * @type {InputArrayInterface}
+ * @type {InputArray}
* @memberof FormManager
*/
- private inputs: InputArrayInterface = {}
+ public inputs: InputArray = {}
/**
* List of interfaces
*
* @private
- * @type {FMAssignInterface[]}
+ * @type {InputAssignment[]}
* @memberof FormManager
*/
- private FMInputs: FMAssignInterface[] = []
+ private FMInputs: InputAssignment[] = []
/**
* The last verified `FMInput` that returned an error
@@ -143,6 +51,8 @@ export default class FormManager {
*/
public form: HTMLFormElement
+ public attributeManager: AttributesManager
+
/**
* Creates an instance of FormManager.
@@ -151,6 +61,7 @@ export default class FormManager {
*/
constructor(form: HTMLFormElement) {
this.form = form
+ this.attributeManager = new AttributesManager(this)
//Prevent default submit action
form.onsubmit = (e) => {
@@ -164,16 +75,6 @@ export default class FormManager {
//Setup the system for basic inputs
this.setupInputs()
-
- setInterval(() => {
- (this.form.querySelectorAll("[data-autoset]") as NodeListOf).forEach((el: HTMLInputElement) => {
- let autosetStr = el.dataset.autoset
- if (autosetStr && autosetStr.startsWith("run:")) {
- let tmp = autosetStr.split("run:")[1]
- el.value = eval(tmp)
- }
- })
- }, 500)
}
/**
@@ -182,7 +83,17 @@ export default class FormManager {
* @param {FMAssignInterface} inter the interface used
* @memberof FormManager
*/
- public assign(inter: FMAssignInterface) {
+ public assign(...inter: InputAssignment[]) {
+ this.FMInputs.unshift(...inter)
+ }
+
+ /**
+ * Assign a single Module
+ *
+ * @param {FMAssignInterface} inter
+ * @memberof FormManager
+ */
+ public assignSingle(inter: InputAssignment) {
this.FMInputs.unshift(inter)
}
@@ -197,6 +108,7 @@ export default class FormManager {
let el = this.getInit(element)
if (el) this.inputs[el.getName()] = el
});
+ this.attributeManager.trigger(FMAttributeListeners.FORM_INIT)
}
/**
@@ -206,7 +118,7 @@ export default class FormManager {
* @returns {FMInput}
* @memberof FormManager
*/
- public getInit(element: Element): FMInput|undefined {
+ public getInit(element: Element): FMInput|void {
inputsLoop: for (const input of this.FMInputs) {
if (input.classes != undefined) {
let tmpList: string[] = []
@@ -246,7 +158,9 @@ export default class FormManager {
for (const name in this.inputs) {
if (this.inputs.hasOwnProperty(name)) {
const input = this.inputs[name];
- if(!input.verify()) {
+ const res = this.attributeManager.triggerElement(FMAttributeListeners.VERIFY, input) as boolean
+ if(!input.verify() || !res) {
+ console.log(input.verify(), res)
this.lastErroredInput = input
return false
}
@@ -268,11 +182,16 @@ export default class FormManager {
*/
public submit(url: string, callback?: (this: XMLHttpRequest, ev: ProgressEvent) => void, verify: boolean = true): boolean {
if (verify && !this.verify()) return false
+ let toSend = this.getJSON()
+ let event = this.attributeManager.trigger(FMAttributeListeners.FORM_SUBMIT, toSend)
+ if (typeof event !== "boolean" && event.datas && event.result) {
+ toSend = event.datas
+ }
let ajax = new XMLHttpRequest
ajax.open("POST", url, true)
ajax.setRequestHeader("Content-Type", "application/json")
if (callback != undefined) ajax.addEventListener("loadend", callback)
- ajax.send(JSON.stringify(this.getJSON()))
+ ajax.send(JSON.stringify(toSend))
return true
}
@@ -281,7 +200,7 @@ export default class FormManager {
*
* @memberof FormManager
*/
- public getJSON(): any {
+ public getJSON(): {[key: string]: any} {
const jsonObject: any = {}
for (const name in this.inputs) {
if (this.inputs.hasOwnProperty(name)) {
@@ -295,7 +214,7 @@ export default class FormManager {
/**
* Fill the form from JSON
*
- * Hint: _to see what the json is made of use `fm.getJSON`_
+ * Hint: _to see what the json look like, use `fm.getJSON`_
*
* @param {*} json the JSON
* @memberof FormManager
@@ -308,6 +227,7 @@ export default class FormManager {
else console.warn(`${key} is not a valid input name`)
}
}
+ this.attributeManager.trigger(FMAttributeListeners.FORM_FILL)
}
/**
@@ -353,7 +273,6 @@ export default class FormManager {
}
public setModeForInput(mode: FMMode, inputName: string) {
- console.log(mode)
if (mode == FMMode.ViewMode) {
if (this.inputs[inputName]) {
this.inputs[inputName].element.setAttribute("disabled", "")
@@ -373,14 +292,16 @@ export default class FormManager {
* @memberof FormManager
*/
public clear() {
+ if (this.attributeManager.trigger(FMAttributeListeners.PRE_CLEAR) === false) return
(this.form.querySelectorAll("[name]") as NodeListOf).forEach((el: HTMLInputElement) => {
for (const name in this.inputs) {
if (this.inputs.hasOwnProperty(name)) {
const input = this.inputs[name];
- input.setToDefault()
+ input.setValue(undefined)
}
}
})
+ this.attributeManager.trigger(FMAttributeListeners.POST_CLEAR)
}
}
diff --git a/src/Interfaces.ts b/src/Interfaces.ts
index 30bdad1..19b751c 100644
--- a/src/Interfaces.ts
+++ b/src/Interfaces.ts
@@ -3,10 +3,10 @@ import FMInput from "./FMInput"
/**
* this interface is used for fetching and setting `name` to `FMInput` link
*
- * @interface InputArrayInterface
+ * @interface InputArray
*/
-export interface InputArrayInterface {
- [key:string]: FMInput
+export interface InputArray {
+ [key: string]: FMInput
}
/**
@@ -21,3 +21,11 @@ export interface FMAssignInterface {
type?: string
tagName?: string
}
+
+export interface InputAssignment {
+ input: typeof FMInput
+ classes?: string[] | string
+ attributes?: string[] | string
+ type?: string
+ tagName?: string
+}
diff --git a/src/modules/FMDatalistInput.ts b/src/modules/FMDatalistInput.ts
index 65baa07..d58ad3a 100644
--- a/src/modules/FMDatalistInput.ts
+++ b/src/modules/FMDatalistInput.ts
@@ -1,4 +1,4 @@
-import { FMAssignInterface } from '../Interfaces';
+import { InputAssignment } from '../Interfaces';
import FormManager from "../FormManager"
import FMInput from "../FMInput"
@@ -29,7 +29,7 @@ export default class FMDatalistInput extends FMInput {
setValue(value: string) {
// if value is "" set value to ""
- if (value == "") {
+ if (value == "" || value === undefined) {
this.element.value = ""
return
}
@@ -64,7 +64,7 @@ export default class FMDatalistInput extends FMInput {
}
}
-export const FMDatalistAssignement: FMAssignInterface = {
+export const FMDatalistAssignement: InputAssignment = {
input: FMDatalistInput,
attributes: "list",
tagName: "input"
diff --git a/src/modules/FMDateInput.ts b/src/modules/FMDateInput.ts
index ffb62dd..8bbc7cb 100644
--- a/src/modules/FMDateInput.ts
+++ b/src/modules/FMDateInput.ts
@@ -1,4 +1,4 @@
-import { FMAssignInterface } from '../Interfaces';
+import { InputAssignment } from '../Interfaces';
import FMInput from "../FMInput"
/**
@@ -8,12 +8,13 @@ import FMInput from "../FMInput"
*/
export default class FMDateInput extends FMInput {
- setValue(value: Date|string) {
- // if value is a string set value to the date of the string
- if (typeof(value) == "string") {
- value = new Date(value)
+ setValue(value: any) {
+ // handle GO null value
+ const format = this.formatValue(value)
+ if (format) {
+ this.element.valueAsDate = format
}
- this.element.valueAsDate = value
+ this.element.value = format
}
getValue(): Date|undefined {
@@ -22,13 +23,21 @@ export default class FMDateInput extends FMInput {
return date == null ? undefined : date
}
- getDefault(args: string): Date {
- // if data-default is present return the current date
- return new Date
+ public formatValue(val: any): Date|undefined {
+ if (val === "0001-01-01T00:00:00Z") {
+ return undefined
+ }
+ if (typeof val === "string" || typeof val === "number") {
+ return new Date(val)
+ }
+ if (typeof val === "object" && typeof val.getDate === "function") {
+ return (val as Date)
+ }
+ return undefined
}
}
-export const FMDateAssignement: FMAssignInterface = {
+export const FMDateAssignement: InputAssignment = {
input: FMDateInput,
type: "date",
tagName: "input"
diff --git a/src/modules/FMFileInput.ts b/src/modules/FMFileInput.ts
index 8879f73..7c7e65a 100644
--- a/src/modules/FMFileInput.ts
+++ b/src/modules/FMFileInput.ts
@@ -1,4 +1,4 @@
-import { FMAssignInterface } from '../Interfaces';
+import { InputAssignment } from '../Interfaces';
import FMInput from "../FMInput"
import FormManager from '../FormManager';
@@ -111,7 +111,7 @@ export default class FMFileInput extends FMInput {
}
-export const FMFileAssignement: FMAssignInterface = {
+export const FMFileAssignement: InputAssignment = {
input: FMFileInput,
type: "file",
tagName: "input"
diff --git a/src/modules/FMRepeatInput.ts b/src/modules/FMRepeatInput.ts
index 19d3b21..f8c6a60 100644
--- a/src/modules/FMRepeatInput.ts
+++ b/src/modules/FMRepeatInput.ts
@@ -1,4 +1,4 @@
-import { FMAssignInterface } from './../Interfaces';
+import { InputAssignment } from './../Interfaces';
import FormManager from "../FormManager"
import FMInput from "../FMInput"
@@ -68,6 +68,9 @@ export default class FMRepeatInput extends FMInput {
let sub: FMInput[] = []
node.querySelectorAll("[data-input]").forEach((el: Element) => {
let input = this.form.getInit(el)
+ if (!input) {
+ return
+ }
if (this.element.hasAttribute("disabled")) {
input.element.disabled = true
}
@@ -142,7 +145,7 @@ export default class FMRepeatInput extends FMInput {
}
}
-export const FMRepeatAssignment: FMAssignInterface = {
+export const FMRepeatAssignment: InputAssignment = {
input: FMRepeatInput,
classes: "fm-repeat",
tagName: "div"
diff --git a/src/modules/FMSelectInput.ts b/src/modules/FMSelectInput.ts
index c61daf0..229976e 100644
--- a/src/modules/FMSelectInput.ts
+++ b/src/modules/FMSelectInput.ts
@@ -1,5 +1,6 @@
-import { FMAssignInterface } from '../Interfaces';
+import { InputAssignment } from '../Interfaces';
import FMInput from "../FMInput"
+import { realType } from '../Functions';
/**
*
@@ -8,16 +9,16 @@ import FMInput from "../FMInput"
*/
export default class FMSelectInput extends FMInput {
- getDefault(): any {
- // check if element as a selected element and if true return it's value
- let def = this.element.querySelector("option[selected]")
- if (def) {
- return (def as HTMLOptionElement).value
+ public formatValue(val: any): any {
+ const opt = this.element.querySelector(`option[value="${val}"]`) || this.element.querySelector("option[selected]")
+ if (opt) {
+ return realType(opt.getAttribute("value") || "")
}
+ return undefined
}
}
-export const FMSelectAssignement: FMAssignInterface = {
+export const FMSelectAssignement: InputAssignment = {
input: FMSelectInput,
tagName: "select"
}