Moved objects

This commit is contained in:
Florian Bouillon 2019-11-14 12:15:48 +01:00
parent 135f6aa770
commit dc40b373ff
No known key found for this signature in database
GPG Key ID: B143FF27EF555D16
25 changed files with 408 additions and 302 deletions

View File

@ -1,4 +1,5 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

View File

@ -1,6 +1,9 @@
import FormManager from "./FormManager"; import FormManager from "./FormManager";
import FMAttribute, { FMAttributeAssignment, FMAttributeListeners, TriggerCallback } from "./FMAttribute"; import FMAttribute, { FMAttributeAssignment, FMAttributeListeners, TriggerCallback } from "./FMAttribute";
import FMInput from "./FMInput"; import InputAbstract from "./modules/InputAbstract";
import AttributeAbstract from "./attributes/AttributeAbstract";
import AttributeIdentity from "./attributes/Interfaces/AttributeIdentity";
import AttributeListeners from "./attributes/AttributeListeners";
export default class AttributesManager { export default class AttributesManager {
@ -8,7 +11,7 @@ export default class AttributesManager {
private form: FormManager private form: FormManager
private attributesArray: FMAttributeAssignment[] = [] private attributesArray: AttributeIdentity[] = []
private eventsListenersItems: listenerItems = {} private eventsListenersItems: listenerItems = {}
@ -17,15 +20,13 @@ export default class AttributesManager {
AttributesManager.instance = this AttributesManager.instance = this
} }
public register(...attribute: FMAttributeAssignment[]) { public register(...attribute: typeof AttributeAbstract[]) {
this.attributesArray.push(...attribute) for (const attr of attribute) {
this.attributesArray.push(attr.identity)
}
} }
public registerSingle(attribute: FMAttributeAssignment) { public trigger(event: AttributeListeners, data?: any): boolean|object {
this.attributesArray.push(attribute)
}
public trigger(event: FMAttributeListeners, data?: any): boolean|TriggerCallback {
if (!this.eventsListenersItems[event]) return true if (!this.eventsListenersItems[event]) return true
for (const el of this.eventsListenersItems[event]) { for (const el of this.eventsListenersItems[event]) {
const res = el.trigger(event, data) const res = el.trigger(event, data)
@ -34,7 +35,7 @@ export default class AttributesManager {
return true return true
} }
public triggerElement(event: FMAttributeListeners, input: FMInput, data?: any): boolean|TriggerCallback { public triggerElement(event: AttributeListeners, input: InputAbstract, data?: any): boolean|object {
if (!this.eventsListenersItems[event]) return true if (!this.eventsListenersItems[event]) return true
for (const el of this.eventsListenersItems[event]) { for (const el of this.eventsListenersItems[event]) {
if (el.input === input) { if (el.input === input) {
@ -47,7 +48,7 @@ export default class AttributesManager {
public onChange(this: HTMLInputElement) { public onChange(this: HTMLInputElement) {
const self = AttributesManager.instance const self = AttributesManager.instance
console.log(self.trigger(FMAttributeListeners.CHANGE, self.form.inputs[this.name])) self.trigger(AttributeListeners.CHANGE, self.form.inputs[this.name])
} }
// private onChange // private onChange
@ -84,5 +85,5 @@ export default class AttributesManager {
} }
interface listenerItems { interface listenerItems {
[key:string]: FMAttribute[] [key:string]: AttributeAbstract[]
} }

View File

@ -1,82 +0,0 @@
import FormManager from "./FormManager"
import { realType } from "./Functions"
export default class FMInput {
element: HTMLInputElement
form: FormManager
required: boolean
constructor(element: Element, form: FormManager) {
this.element = element as HTMLInputElement
this.form = form
this.required = element.hasAttribute("required")
}
/**
* Set the element Value
*
* @param {*} value the input value
*
* _hint: pass it through this.formatValue_
*
* @memberof FMInput
*/
public setValue(value: any) {
this.element.value = value
}
/**
* Get the element value
*
* @returns {*} the value
* @memberof FMInput
*/
public getValue(): any {
return this.formatValue(this.element.value)
}
/**
* 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`
*
* @param {*} value
* @returns {*}
* @memberof FMInput
*/
public formatValue(value: any): any {
// if the value is a number return it as a number obj
return realType(value)
}
/**
* Retrieve the input name
*
* @returns {string}
* @memberof FMInput
*/
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;
if (attr) return attr
throw Error("Error: could not get input name!")
}
/**
* Verify if the element is correct
*
* @returns {boolean}
* @memberof FMInput
*/
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
return true
}
}

View File

@ -1,7 +1,10 @@
import { InputArray, InputAssignment } from './Interfaces';
import FMInput from "./FMInput"
import AttributesManager from './AttributesManager'; import AttributesManager from './AttributesManager';
import { FMAttributeListeners } from './FMAttribute'; import { FMAttributeListeners } from './FMAttribute';
import InputIdentity from './modules/Interfaces/InputIdentity';
import DefaultInput from './modules/DefaultInput';
import InputAbstract from './modules/InputAbstract';
import InputArray from "./modules/Interfaces/InputArray";
import AttributeListeners from './attributes/AttributeListeners';
/*! /*!
* FormManager by DZEIO's team * FormManager by DZEIO's team
@ -30,10 +33,10 @@ export default class FormManager {
* List of interfaces * List of interfaces
* *
* @private * @private
* @type {InputAssignment[]} * @type {InputIdentity[]}
* @memberof FormManager * @memberof FormManager
*/ */
private FMInputs: InputAssignment[] = [] private FMInputs: InputIdentity[] = []
/** /**
* The last verified `FMInput` that returned an error * The last verified `FMInput` that returned an error
@ -41,7 +44,7 @@ export default class FormManager {
* @type {FMInput} * @type {FMInput}
* @memberof FormManager * @memberof FormManager
*/ */
public lastErroredInput: FMInput|undefined public lastErroredInput: InputAbstract|undefined
/** /**
* The Form Element of the FM * The Form Element of the FM
@ -69,32 +72,22 @@ export default class FormManager {
} }
//assign default form interface //assign default form interface
this.assign({ this.assign(DefaultInput)
input: FMInput
})
//Setup the system for basic inputs //Setup the system for basic inputs
this.setupInputs() this.setupInputs()
} }
/** /**
* Add the the FM an Input Manager * Add to the Manager an Input
* *
* @param {FMAssignInterface} inter the interface used * @param {InputIdentity[]} inter the interface used
* @memberof FormManager * @memberof FormManager
*/ */
public assign(...inter: InputAssignment[]) { public assign(...inter: (typeof InputAbstract[])) {
this.FMInputs.unshift(...inter) for (const input of inter) {
this.FMInputs.unshift(input.identity)
} }
/**
* Assign a single Module
*
* @param {FMAssignInterface} inter
* @memberof FormManager
*/
public assignSingle(inter: InputAssignment) {
this.FMInputs.unshift(inter)
} }
/** /**
@ -103,12 +96,12 @@ export default class FormManager {
* @memberof FormManager * @memberof FormManager
*/ */
public setupInputs() { public setupInputs() {
this.inputs = {} this.inputs = {};
this.form.querySelectorAll("[name]:not([data-name])").forEach((element: Element) => { (this.form.querySelectorAll("[name]:not([data-name])") as NodeListOf<HTMLElement>).forEach((element: HTMLElement) => {
let el = this.getInit(element) let el = this.getInit(element)
if (el) this.inputs[el.getName()] = el if (el) this.inputs[el.getName()] = el
}); });
this.attributeManager.trigger(FMAttributeListeners.FORM_INIT) this.attributeManager.trigger(AttributeListeners.FORM_INIT)
} }
/** /**
@ -118,7 +111,7 @@ export default class FormManager {
* @returns {FMInput} * @returns {FMInput}
* @memberof FormManager * @memberof FormManager
*/ */
public getInit(element: Element): FMInput|void { public getInit(element: HTMLElement): InputAbstract|void {
inputsLoop: for (const input of this.FMInputs) { inputsLoop: for (const input of this.FMInputs) {
if (input.classes != undefined) { if (input.classes != undefined) {
let tmpList: string[] = [] let tmpList: string[] = []
@ -158,7 +151,7 @@ export default class FormManager {
for (const name in this.inputs) { for (const name in this.inputs) {
if (this.inputs.hasOwnProperty(name)) { if (this.inputs.hasOwnProperty(name)) {
const input = this.inputs[name]; const input = this.inputs[name];
const res = this.attributeManager.triggerElement(FMAttributeListeners.VERIFY, input) as boolean const res = this.attributeManager.triggerElement(AttributeListeners.VERIFY, input) as boolean
if(!input.verify() || !res) { if(!input.verify() || !res) {
console.log(input.verify(), res) console.log(input.verify(), res)
this.lastErroredInput = input this.lastErroredInput = input
@ -183,9 +176,9 @@ export default class FormManager {
public submit(url: string, callback?: (this: XMLHttpRequest, ev: ProgressEvent) => void, verify: boolean = true): boolean { public submit(url: string, callback?: (this: XMLHttpRequest, ev: ProgressEvent) => void, verify: boolean = true): boolean {
if (verify && !this.verify()) return false if (verify && !this.verify()) return false
let toSend = this.getJSON() let toSend = this.getJSON()
let event = this.attributeManager.trigger(FMAttributeListeners.FORM_SUBMIT, toSend) let event = this.attributeManager.trigger(AttributeListeners.FORM_SUBMIT, toSend)
if (typeof event !== "boolean" && event.datas && event.result) { if (typeof event !== "boolean" && event) {
toSend = event.datas toSend = event
} }
let ajax = new XMLHttpRequest let ajax = new XMLHttpRequest
ajax.open("POST", url, true) ajax.open("POST", url, true)
@ -227,7 +220,7 @@ export default class FormManager {
else console.warn(`${key} is not a valid input name`) else console.warn(`${key} is not a valid input name`)
} }
} }
this.attributeManager.trigger(FMAttributeListeners.FORM_FILL) this.attributeManager.trigger(AttributeListeners.FORM_FILL)
} }
/** /**
@ -292,7 +285,7 @@ export default class FormManager {
* @memberof FormManager * @memberof FormManager
*/ */
public clear() { public clear() {
if (this.attributeManager.trigger(FMAttributeListeners.PRE_CLEAR) === false) return if (this.attributeManager.trigger(AttributeListeners.PRE_CLEAR) === false) return
(this.form.querySelectorAll("[name]") as NodeListOf<HTMLInputElement>).forEach((el: HTMLInputElement) => { (this.form.querySelectorAll("[name]") as NodeListOf<HTMLInputElement>).forEach((el: HTMLInputElement) => {
for (const name in this.inputs) { for (const name in this.inputs) {
if (this.inputs.hasOwnProperty(name)) { if (this.inputs.hasOwnProperty(name)) {
@ -301,7 +294,7 @@ export default class FormManager {
} }
} }
}) })
this.attributeManager.trigger(FMAttributeListeners.POST_CLEAR) this.attributeManager.trigger(AttributeListeners.POST_CLEAR)
} }
} }

View File

@ -20,8 +20,8 @@ export function evalF(str: string, callback?: (str: string) => void): boolean {
* *
* @param str the string to transform * @param str the string to transform
*/ */
export function toNumber(str: string): number|undefined { export function toNumber(str: any): number|undefined {
if (str === "") return undefined if (str === "" || str === undefined) return undefined
// return undefined if it must be shown as string // return undefined if it must be shown as string
if ((str.startsWith("0") || str.startsWith("+")) && str.length > 1) return undefined if ((str.startsWith("0") || str.startsWith("+")) && str.length > 1) return undefined
const n = Number(str) const n = Number(str)
@ -31,7 +31,11 @@ export function toNumber(str: string): number|undefined {
return undefined return undefined
} }
export function toBoolean(str: string): boolean|undefined { export function isNumber(el: any): boolean {
return typeof el === "number"
}
export function toBoolean(str: any): boolean|undefined {
if (str === "true") return true if (str === "true") return true
if (str === "false") return false if (str === "false") return false
return undefined return undefined
@ -44,7 +48,8 @@ export function strToNum(str: string): number|string {
} }
export function realType(el: string): string|number|boolean { export function realType(el: any): string|number|boolean {
if (isNumber(el)) return el
const isBool = toBoolean(el) const isBool = toBoolean(el)
const isNum = toNumber(el) const isNum = toNumber(el)
return typeof isBool === "boolean" ? isBool : typeof isNum === "number" ? isNum : el return typeof isBool === "boolean" ? isBool : typeof isNum === "number" ? isNum : el

View File

@ -1,31 +0,0 @@
import FMInput from "./FMInput"
/**
* this interface is used for fetching and setting `name` to `FMInput` link
*
* @interface InputArray
*/
export interface InputArray {
[key: string]: FMInput
}
/**
* this interface is used when adding a new `FMInput` class to the FormManager
*
* @interface FMAssignInterface
*/
export interface FMAssignInterface {
input: typeof FMInput
classes?: string[] | string
attributes?: string[] | string
type?: string
tagName?: string
}
export interface InputAssignment {
input: typeof FMInput
classes?: string[] | string
attributes?: string[] | string
type?: string
tagName?: string
}

View File

@ -0,0 +1,23 @@
import AttributeIdentity from './Interfaces/AttributeIdentity';
import InputAbstract from "../modules/InputAbstract";
import AttributeListeners from "./AttributeListeners";
export default abstract class AttributeAbstract {
public input: InputAbstract
public static listeners: AttributeListeners[]
public static identity: AttributeIdentity
public constructor(input: InputAbstract) {
this.input = input
}
/**
* Function launched on Listener trigger
* it MUST be implemented and SHOULD return boolean
*
* @param ev Attribue triggered
*/
public abstract trigger(event: AttributeListeners, data?: any): object|boolean|void
}

View File

@ -0,0 +1,11 @@
enum AttributeListeners {
PRE_CLEAR, // Event run before clearing the form
POST_CLEAR, // Event run after learing the form
CHANGE, // Event runs on Form Change (datas wil be filled with the FMInput element)
FORM_INIT, // Event runs on form init
FORM_SUBMIT, // Event run before submitting (datas is filled with the datas that will be submitted, MUST return TriggerCallback)
VERIFY, // Event run on element verification (return true or false only)
FORM_FILL, // Event run after the form was filled
}
export default AttributeListeners

View File

@ -1,5 +1,8 @@
import FMAttribute, { FMAttributeListeners, FMAttributeAssignment, TriggerCallback } from "../FMAttribute"; import FMAttribute, { FMAttributeListeners, FMAttributeAssignment, TriggerCallback } from "../FMAttribute";
import { evalF } from "../Functions"; import { evalF } from "../Functions";
import AttributeListeners from "./AttributeListeners";
import AttributeAbstract from "./AttributeAbstract";
import AttributeIdentity from "./Interfaces/AttributeIdentity";
/** /**
* elements * elements
@ -21,10 +24,10 @@ import { evalF } from "../Functions";
* @implements {FMAClearInterface} * @implements {FMAClearInterface}
* @implements {FMAFormInitInterface} * @implements {FMAFormInitInterface}
*/ */
export default class FMAutosetAttribute export default class AutosetAttribute
extends FMAttribute { extends AttributeAbstract {
public trigger(ev: FMAttributeListeners, datas?: any): void { public trigger(event: AttributeListeners, data?: any): boolean | void | object {
console.log("pouet")
let str = this.input.element.getAttribute("data-autoset") || "" let str = this.input.element.getAttribute("data-autoset") || ""
if (evalF(str, (ster) => {this.input.setValue(ster)})) return if (evalF(str, (ster) => {this.input.setValue(ster)})) return
this.normal(str) this.normal(str)
@ -47,13 +50,13 @@ extends FMAttribute {
} }
} }
public static listeners: FMAttributeListeners[] = [ public static listeners: AttributeListeners[] = [
FMAttributeListeners.CHANGE, AttributeListeners.CHANGE,
FMAttributeListeners.FORM_FILL AttributeListeners.FORM_FILL
] ]
}
export const FMAutosetAttributeAssignment: FMAttributeAssignment = { public static identity: AttributeIdentity = {
attribute: FMAutosetAttribute, attribute: AutosetAttribute,
dataElement: "data-autoset" dataElement: "data-autoset"
} }
}

View File

@ -1,5 +1,7 @@
import FMAttribute, { FMAttributeListeners, FMAttributeAssignment } from "../FMAttribute";
import { evalF } from "../Functions"; import { evalF } from "../Functions";
import AttributeAbstract from "./AttributeAbstract";
import AttributeListeners from "./AttributeListeners";
import AttributeIdentity from "./Interfaces/AttributeIdentity";
/** /**
* elements * elements
@ -21,9 +23,9 @@ import { evalF } from "../Functions";
* @implements {FMAClearInterface} * @implements {FMAClearInterface}
* @implements {FMAFormInitInterface} * @implements {FMAFormInitInterface}
*/ */
export default class FMDefaultAttribute export default class DefaultAttribute
extends FMAttribute { extends AttributeAbstract {
public trigger(ev: FMAttributeListeners): boolean | void { public trigger(event: AttributeListeners, data?: any): boolean | void | object {
this.run() this.run()
return true return true
} }
@ -69,13 +71,13 @@ extends FMAttribute {
this.input.setValue(attrVal) this.input.setValue(attrVal)
} }
public static listeners: FMAttributeListeners[] = [ public static listeners: AttributeListeners[] = [
FMAttributeListeners.POST_CLEAR, AttributeListeners.POST_CLEAR,
FMAttributeListeners.FORM_INIT AttributeListeners.FORM_INIT
] ]
}
export const FMDefaultAttributeAssignment: FMAttributeAssignment = { public static identity: AttributeIdentity = {
attribute: FMDefaultAttribute, attribute: DefaultAttribute,
dataElement: "data-default" dataElement: "data-default"
} }
}

View File

@ -1,43 +0,0 @@
import FMAttribute, { FMAttributeListeners, FMAttributeAssignment, TriggerCallback } from "../FMAttribute";
/**
* elements
* if input has type and type == type time week
* then it will set the value to a new date of the value
*
*
* ex:
* "child:value:queryselector"
* or
* "child:text:queryselector"
* or
* "child:attributeName:queryselector"
*
*
* @export
* @class FMDefaultAttribute
* @extends {FMAttribute}
* @implements {FMAClearInterface}
* @implements {FMAFormInitInterface}
*/
export default class FMIgnoreAttribute
extends FMAttribute {
public trigger(ev: FMAttributeListeners, datas?: any): TriggerCallback {
console.log("pouetemon")
datas[this.input.getName()] = undefined
console.log(datas)
return {
datas,
result: true
}
}
public static listeners: FMAttributeListeners[] = [
FMAttributeListeners.FORM_SUBMIT
]
}
export const FMIgnoreAttributeAssignment: FMAttributeAssignment = {
attribute: FMIgnoreAttribute,
dataElement: "data-ignore"
}

View File

@ -1,22 +0,0 @@
import FMAttribute, { FMAttributeListeners, FMAttributeAssignment } from "../FMAttribute";
export default class FMRegexAttribute
extends FMAttribute {
public trigger(): boolean {
const regStr = this.input.element.dataset.regex
if (!regStr) return true
const regex = new RegExp(regStr, "g")
const test = this.input.getValue() + ""
console.log(test)
return regex.test(test)
}
public static listeners: FMAttributeListeners[] = [
FMAttributeListeners.VERIFY
]
}
export const FMRegexAttributeAssignment: FMAttributeAssignment = {
attribute: FMRegexAttribute,
dataElement: "data-regex"
}

View File

@ -0,0 +1,44 @@
import FMAttribute, { FMAttributeListeners, FMAttributeAssignment, TriggerCallback } from "../FMAttribute";
import AttributeAbstract from "./AttributeAbstract";
import AttributeListeners from "./AttributeListeners";
import AttributeIdentity from "./Interfaces/AttributeIdentity";
/**
* elements
* if input has type and type == type time week
* then it will set the value to a new date of the value
*
*
* ex:
* "child:value:queryselector"
* or
* "child:text:queryselector"
* or
* "child:attributeName:queryselector"
*
*
* @export
* @class FMDefaultAttribute
* @extends {FMAttribute}
* @implements {FMAClearInterface}
* @implements {FMAFormInitInterface}
*/
export default class IgnoreAttribute
extends AttributeAbstract {
public trigger(event: AttributeListeners, data?: any): boolean | void | object {
console.log("pouetemon")
data[this.input.getName()] = undefined
console.log(data)
return data
}
public static listeners: AttributeListeners[] = [
AttributeListeners.FORM_SUBMIT
]
public static identity: AttributeIdentity = {
attribute: IgnoreAttribute,
dataElement: "data-ignore"
}
}

View File

@ -0,0 +1,6 @@
import AttributeInterface from "./AttributeInterface"
export default interface AttributeIdentity {
attribute: AttributeInterface,
dataElement: string
}

View File

@ -0,0 +1,13 @@
import InputAbstract from "../../modules/InputAbstract";
import AttributeAbstract from "../AttributeAbstract";
import AttributeListeners from "../AttributeListeners";
import AttributeIdentity from "./AttributeIdentity";
/**
* Define static elements of `AttributeAbstract`
*/
export default interface AttributeInterface {
new(input: InputAbstract): AttributeAbstract
listeners: AttributeListeners[]
identity: AttributeIdentity
}

View File

@ -0,0 +1,24 @@
import AttributeIdentity from './Interfaces/AttributeIdentity';
import AttributeAbstract from './AttributeAbstract';
import AttributeListeners from "./AttributeListeners";
export default class RegexAttribute
extends AttributeAbstract {
public trigger(): boolean {
const regStr = this.input.element.dataset.regex
if (!regStr) return true
const regex = new RegExp(regStr, "g")
const test = this.input.getValue() + ""
console.log(test)
return regex.test(test)
}
public static listeners: AttributeListeners[] = [
AttributeListeners.VERIFY
]
public static identity: AttributeIdentity = {
attribute: RegexAttribute,
dataElement: "data-regex"
}
}

View File

@ -1,18 +1,18 @@
import { InputAssignment } from '../Interfaces';
import FormManager from "../FormManager" import FormManager from "../FormManager"
import FMInput from "../FMInput" import InputIdentity from './Interfaces/InputIdentity';
import DefaultInput from './DefaultInput';
/** /**
* the upgraded datalist element * the upgraded datalist element
* @class FMDatalistInput * @class FMDatalistInput
* @extends {FMInput} * @extends {FMInput}
*/ */
export default class FMDatalistInput extends FMInput { export default class DatalistInput extends DefaultInput {
datalist: HTMLDataListElement datalist: HTMLDataListElement
isStrict: boolean isStrict: boolean
constructor(element: HTMLInputElement, form: FormManager) { constructor(element: HTMLElement, form: FormManager) {
super(element, form) super(element, form)
// check if input is strict on inputs // check if input is strict on inputs
@ -62,10 +62,11 @@ export default class FMDatalistInput extends FMInput {
// if strict return undefined else return element value // if strict return undefined else return element value
return this.isStrict ? undefined : this.formatValue(this.element.value) return this.isStrict ? undefined : this.formatValue(this.element.value)
} }
}
export const FMDatalistAssignement: InputAssignment = { public static identity: InputIdentity = {
input: FMDatalistInput, input: DatalistInput,
attributes: "list", attributes: "list",
tagName: "input" tagName: "input"
} }
}

View File

@ -1,44 +1,44 @@
import { InputAssignment } from '../Interfaces'; import InputIdentity from './Interfaces/InputIdentity'
import FMInput from "../FMInput" import DefaultInput from './DefaultInput'
/** /**
* *
* @class FMDateInput * @class FMDateInput
* @extends {FMInput} * @extends {FMInput}
*/ */
export default class FMDateInput extends FMInput { export default class DateInput extends DefaultInput {
setValue(value: any) { public setValue(value: any) {
// handle GO null value // handle GO null value
const format = this.formatValue(value) const format = this.formatValue(value)
if (format) { if (format) {
this.element.valueAsDate = format this.element.valueAsDate = format
} }
this.element.value = format this.element.value = ""
} }
getValue(): Date|undefined { public getValue(): Date|undefined {
// if get date and if null return undefined else return value // if get date and if null return undefined else return value
let date = this.element.valueAsDate let date = this.element.valueAsDate
return date == null ? undefined : date return date == null ? undefined : date
} }
public formatValue(val: any): Date|undefined { public formatValue(val: any): Date|undefined {
if (typeof val === "object" && typeof val.getDate === "function") {
return (val as Date)
}
if (val === "0001-01-01T00:00:00Z") { if (val === "0001-01-01T00:00:00Z") {
return undefined return undefined
} }
if (typeof val === "string" || typeof val === "number") { if (typeof val === "string" || typeof val === "number") {
return new Date(val) return new Date(val)
} }
if (typeof val === "object" && typeof val.getDate === "function") {
return (val as Date)
}
return undefined return undefined
} }
}
export const FMDateAssignement: InputAssignment = { public static identity: InputIdentity = {
input: FMDateInput, input: DateInput,
type: "date", type: "date",
tagName: "input" tagName: "input"
} }
}

View File

@ -0,0 +1,39 @@
import { realType } from "../Functions"
import InputAbstract from "./InputAbstract"
import InputIdentity from "./Interfaces/InputIdentity"
export default class DefaultInput extends InputAbstract {
public setValue(value: any) {
this.element.value = this.formatValue(value)
}
public getValue(): any {
return this.formatValue(this.element.value)
}
public formatValue(value: any): any {
// if the value is a number return it as a number obj
return realType(value)
}
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;
if (attr) return attr
throw Error("Error: could not get input name!")
}
public verify(): boolean {
let val: any = this.getValue()
// if element is required and value is undefined retur false
if (this.element.hasAttribute("required") && (val === undefined || val === null || val === "")) return false
return true
}
public static identity: InputIdentity = {
input: DefaultInput
}
}

View File

@ -1,13 +1,13 @@
import { InputAssignment } from '../Interfaces';
import FMInput from "../FMInput"
import FormManager from '../FormManager'; import FormManager from '../FormManager';
import DefaultInput from './DefaultInput';
import InputIdentity from './Interfaces/InputIdentity';
/** /**
* *
* @class FMFileInput * @class FMFileInput
* @extends {FMInput} * @extends {FMInput}
*/ */
export default class FMFileInput extends FMInput { export default class FileInput extends DefaultInput {
isUploaded = false isUploaded = false
@ -15,16 +15,16 @@ export default class FMFileInput extends FMInput {
button: HTMLButtonElement button: HTMLButtonElement|undefined
constructor(element: HTMLInputElement, form: FormManager) { constructor(element: HTMLElement, form: FormManager) {
super(element, form) super(element, form)
this.type = this.element.dataset.uploadType ? parseInt(this.element.dataset.uploadType): 1 this.type = this.element.dataset.uploadType ? parseInt(this.element.dataset.uploadType): 1
element.addEventListener("change", () => { element.addEventListener("change", () => {
console.log("pouet") console.log("pouet")
let files = element.files let files = this.element.files
if (files && element.parentElement && files.length > 0) { if (files && element.parentElement && files.length > 0) {
const name = element.parentElement.querySelector(".file-name") const name = element.parentElement.querySelector(".file-name")
if (name) name.textContent = files[0].name if (name) name.textContent = files[0].name
@ -109,10 +109,10 @@ export default class FMFileInput extends FMInput {
return true return true
} }
} public static identity: InputIdentity = {
input: FileInput,
export const FMFileAssignement: InputAssignment = {
input: FMFileInput,
type: "file", type: "file",
tagName: "input" tagName: "input"
} }
}

View File

@ -0,0 +1,64 @@
import FormManager from "../FormManager";
import InputIdentity from "./Interfaces/InputIdentity";
export default abstract class InputAbstract {
public element: HTMLInputElement
public form: FormManager
public constructor(element: HTMLElement, form: FormManager) {
this.element = element as HTMLInputElement
this.form = form
}
/**
* Set the element Value
*
* _hint: pass it through this.formatValue_
*
* @param {*} value the input value
* @memberof FMInput
*/
public abstract setValue(value: any): void
/**
* Get the element value
*
* @returns {*} the value
* @memberof FMInput
*/
public abstract getValue(): any
/**
* 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`
*
* @param {*} value
* @returns {*}
* @memberof FMInput
*/
public abstract formatValue(value: any): any
/**
* Retrieve the input name
*
* name can be located at multiple locations like `name` attribute or `data-name` attribute
*
* @returns {string}
* @memberof FMInput
*/
public abstract getName(): string
/**
* Verify if the element is correct
*
* @returns {boolean}
* @memberof FMInput
*/
public abstract verify(): boolean
public static identity: InputIdentity
}

View File

@ -0,0 +1,10 @@
import InputAbstract from "../InputAbstract";
/**
* this interface is used for fetching and setting `name` to `FMInput` link
*
* @interface InputArray
*/
export default interface InputArray {
[key: string]: InputAbstract
}

View File

@ -0,0 +1,43 @@
import InputAbstract from "../InputAbstract";
import FMDatalistInput from "../FMDatalistInput";
import FMDateInput from "../FMDateInput";
import DefaultInput from "../DefaultInput";
import FormManager from "../../FormManager";
interface InputConstructor {
new(element: HTMLElement, form: FormManager): InputAbstract
}
/**
* Make an Input class different with the othes ones
*/
export default interface InputIdentity {
/**
* The input
*/
input: InputConstructor
/**
* the classes filters
*/
classes?: string[] | string
/**
* The Attribute filters
*/
attributes?: string[] | string
/**
* If it's an Input the type have to cerrespond
* to this
*/
type?: string
/**
* the TagName used
*
* ex: `<div></div>` will be `DIV`
*/
tagName ?: string
}

View File

@ -1,21 +1,22 @@
import { InputAssignment } from './../Interfaces';
import FormManager from "../FormManager" import FormManager from "../FormManager"
import FMInput from "../FMInput" import DefaultInput from './DefaultInput';
import InputAbstract from './InputAbstract';
import InputIdentity from './Interfaces/InputIdentity';
/** /**
* *
* @class FMRepeatInput * @class FMRepeatInput
* @extends {FMInput} * @extends {FMInput}
*/ */
export default class FMRepeatInput extends FMInput { export default class RepeatInput extends DefaultInput {
elements: FMInput[][] = [] elements: InputAbstract[][] = []
private template: HTMLElement private template: HTMLElement
private addBtn: HTMLElement private addBtn: HTMLElement
constructor(element: HTMLDivElement, form: FormManager) { constructor(element: HTMLElement, form: FormManager) {
super(element, form) super(element, form)
//fetch Template //fetch Template
@ -65,8 +66,8 @@ export default class FMRepeatInput extends FMInput {
node.style.display = "" node.style.display = ""
// loop through inputs ot init them // loop through inputs ot init them
let sub: FMInput[] = [] let sub: InputAbstract[] = [];
node.querySelectorAll("[data-input]").forEach((el: Element) => { (node.querySelectorAll("[data-input]") as NodeListOf<HTMLElement>).forEach((el: HTMLElement) => {
let input = this.form.getInit(el) let input = this.form.getInit(el)
if (!input) { if (!input) {
return return
@ -143,10 +144,10 @@ export default class FMRepeatInput extends FMInput {
} }
return values return values
} }
}
export const FMRepeatAssignment: InputAssignment = { public static identity: InputIdentity = {
input: FMRepeatInput, input: RepeatInput,
classes: "fm-repeat", classes: "fm-repeat",
tagName: "div" tagName: "div"
} }
}

View File

@ -1,5 +1,5 @@
import { InputAssignment } from '../Interfaces'; import InputIdentity from './Interfaces/InputIdentity';
import FMInput from "../FMInput" import DefaultInput from './DefaultInput';
import { realType } from '../Functions'; import { realType } from '../Functions';
/** /**
@ -7,7 +7,7 @@ import { realType } from '../Functions';
* @class FMDateInput * @class FMDateInput
* @extends {FMInput} * @extends {FMInput}
*/ */
export default class FMSelectInput extends FMInput { export default class SelectInput extends DefaultInput {
public formatValue(val: any): any { public formatValue(val: any): any {
const opt = this.element.querySelector(`option[value="${val}"]`) || this.element.querySelector("option[selected]") const opt = this.element.querySelector(`option[value="${val}"]`) || this.element.querySelector("option[selected]")
@ -16,9 +16,9 @@ export default class FMSelectInput extends FMInput {
} }
return undefined return undefined
} }
}
export const FMSelectAssignement: InputAssignment = { public static identity: InputIdentity = {
input: FMSelectInput, input: SelectInput,
tagName: "select" tagName: "select"
} }
}