Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
Florian Bouillon 2019-12-06 15:32:35 +01:00
parent 925b9c2d7f
commit dbe53cb3f9
No known key found for this signature in database
GPG Key ID: B143FF27EF555D16
19 changed files with 131 additions and 65 deletions

View File

@ -1,6 +1,6 @@
import FormManager from "./FormManager";
import InputAbstract from "./modules/InputAbstract";
import AttributeAbstract from "./attributes/AttributeAbstract";
import InputAbstract from "./modules/AbstractInput";
import AbstractAttribute from "./attributes/AbstractAttribute";
import AttributeIdentity from "./attributes/Interfaces/AttributeIdentity";
import AttributeListeners from "./attributes/AttributeListeners";
@ -16,17 +16,16 @@ export default class AttributesManager {
this.form = form
}
public register(...attribute: typeof AttributeAbstract[]) {
public register(...attribute: typeof AbstractAttribute[]) {
for (const attr of attribute) {
this.attributesArray.push(attr.identity)
}
}
public trigger(event: AttributeListeners, data?: any): boolean|object {
public trigger(event: AttributeListeners, data?: any): boolean {
if (!this.eventsListenersItems[event]) return true
for (const el of this.eventsListenersItems[event]) {
const res = el.trigger(event, data)
if (typeof res !== "undefined") return res
el.trigger(event, data)
}
return true
}
@ -83,5 +82,5 @@ export default class AttributesManager {
}
interface listenerItems {
[key:string]: AttributeAbstract[]
[key:string]: AbstractAttribute[]
}

View File

@ -7,7 +7,8 @@ import RegexAttribute from './attributes/RegexAttribute'
import IgnoreAttribute from './attributes/IgnoreAttribute'
import DefaultAttribute from './attributes/DefaultAttribute'
import AutosetAttribute from './attributes/AutosetAttribute'
import checkboxInput from './modules/CheckboxInput'
import CheckboxInput from './modules/CheckboxInput'
import NumberInput from './modules/NumberInput'
/**
* This class is Mainly used for (non-npm) browser usage as it contains every buitins extensions
@ -24,7 +25,8 @@ export default class fm extends FormManager {
DateInput,
RepeatInput,
SelectInput,
checkboxInput,
CheckboxInput,
NumberInput,
)
this.setupInputs()
this.attributeManager.register(

View File

@ -1,7 +1,7 @@
import AttributesManager from './AttributesManager';
import InputIdentity from './modules/Interfaces/InputIdentity';
import DefaultInput from './modules/DefaultInput';
import InputAbstract from './modules/InputAbstract';
import AbstractInput from './modules/AbstractInput';
import InputArray from "./modules/Interfaces/InputArray";
import AttributeListeners from './attributes/AttributeListeners';
@ -84,10 +84,11 @@ export default class FormManager {
/**
* Add to the Manager an Input
*
* @param {InputIdentity[]} inter the interface used
* @param {...(typeof AbstractInput[])} inter the interface used
* @memberof FormManager
*/
public assign(...inter: (typeof InputAbstract[])) {
public assign(...inter: (typeof AbstractInput[])) {
for (const input of inter) {
this.FMInputs.unshift(input.identity)
}
@ -120,7 +121,7 @@ export default class FormManager {
* @returns {FMInput}
* @memberof FormManager
*/
public getInit(element: HTMLElement): InputAbstract|void {
public getInit(element: HTMLElement): AbstractInput|void {
inputsLoop: for (const input of this.FMInputs) {
if (input.classes != undefined) {
let tmpList: string[] = []
@ -152,11 +153,11 @@ export default class FormManager {
* Verify the inputs for errors
*
* @param {boolean} [quick=false] define if the loop should stop after the first error
* @returns {InputAbstract[]} return an array containing the errored elements (Empty if not error)
* @returns {AbstractInput[]} return an array containing the errored elements (Empty if not error)
* @memberof FormManager
*/
public validate(quick = false): InputAbstract[] {
const errored: InputAbstract[] = []
public validate(quick = false): AbstractInput[] {
const errored: AbstractInput[] = []
for (const name in this.inputs) {
if (!this.inputs.hasOwnProperty(name)) continue
const input = this.inputs[name];
@ -208,6 +209,20 @@ export default class FormManager {
return true
}
/**
* Manually set the value of an element
*
* @param {string} name
* @param {*} value
* @memberof FormManager
*/
public setValue(name: string, value: any) {
if (!this.inputs.hasOwnProperty(name)) {
return
}
const input = this.inputs[name]
input.setValue(value)
}
/**
* Return the JSON `{key: value}` sequence
*

View File

@ -21,11 +21,11 @@ export function evalF(str: string, callback?: (str: string) => void): boolean {
*
* @param str the string to transform
*/
export function toNumber(str: any): number|undefined {
export function toNumber(str: any): number | undefined {
if (typeof str === "number") return str
if ((str === "" || str === undefined || typeof(str) === "boolean")) return undefined
// return undefined if it must be shown as string
// console.log("toNumber", str)
if (str === "" || typeof str !== "string") return undefined
// str is a string
if ((str.startsWith("0") || str.startsWith("+")) && str.length > 1) return undefined
const n = Number(str)
if (!isNaN(n)) {
@ -35,30 +35,33 @@ export function toNumber(str: any): number|undefined {
}
export function isNumber(el: any): boolean {
// console.log(el)
return typeof el === "number"
return typeof toNumber(el) === "number"
}
export function toBoolean(str: any): boolean|undefined {
export function toBoolean(str: any): boolean | undefined {
if (typeof str === "boolean") return str
if (str === "true") return true
if (str === "false") return false
return undefined
}
export function strToNum(str: string): number|string {
export function isBoolean(el: any): boolean {
return typeof toBoolean(el) === "boolean"
}
export function strToNum(str: string): number | string {
const n = toNumber(str)
if (n) return n
return str
}
export function realType(el: any): string|number|boolean {
export function realType(el: any): string|number|boolean|undefined {
// If el is `null` or `undefined`
if ((typeof el === "object" && el === null) || typeof el === "undefined") return undefined
if (typeof el === "object" && el.hasOwnProperty("id")) {
el = el.id
}
if (isNumber(el)) return el
const isBool = toBoolean(el)
const isNum = toNumber(el)
return typeof isBool === "boolean" ? isBool : typeof isNum === "number" ? isNum : el
if (isNumber(el)) return toNumber(el)
if (isBoolean(el)) return toBoolean(el)
return el
}

View File

@ -1,8 +1,8 @@
import AttributeIdentity from './Interfaces/AttributeIdentity';
import InputAbstract from "../modules/InputAbstract";
import InputAbstract from "../modules/AbstractInput";
import AttributeListeners from "./AttributeListeners";
export default abstract class AttributeAbstract {
export default abstract class AbstractAttribute {
public input: InputAbstract

View File

@ -1,6 +1,6 @@
import { evalF } from "../Functions";
import AttributeListeners from "./AttributeListeners";
import AttributeAbstract from "./AttributeAbstract";
import AbstractAttribute from "./AbstractAttribute";
import AttributeIdentity from "./Interfaces/AttributeIdentity";
/**
@ -24,7 +24,7 @@ import AttributeIdentity from "./Interfaces/AttributeIdentity";
* @implements {FMAFormInitInterface}
*/
export default class AutosetAttribute
extends AttributeAbstract {
extends AbstractAttribute {
public trigger(): boolean | void | object {
let str = this.input.element.getAttribute("data-autoset") || ""

View File

@ -1,5 +1,5 @@
import { evalF } from "../Functions";
import AttributeAbstract from "./AttributeAbstract";
import AbstractAttribute from "./AbstractAttribute";
import AttributeListeners from "./AttributeListeners";
import AttributeIdentity from "./Interfaces/AttributeIdentity";
@ -24,13 +24,18 @@ import AttributeIdentity from "./Interfaces/AttributeIdentity";
* @implements {FMAFormInitInterface}
*/
export default class DefaultAttribute
extends AttributeAbstract {
extends AbstractAttribute {
public trigger(): boolean | void | object {
this.run()
return true
}
private run() {
// Dont override existing value
if (this.input.getValue() !== undefined) {
return
}
let attrVal = this.input.element.getAttribute("data-default")
// if element has a date,time,week type
@ -66,7 +71,8 @@ extends AttributeAbstract {
// if default is an attribute value
if (!el.hasAttribute(splitted[1])) throw Error(`Error: "${this.input.getName()}" element don't have the attribute "${splitted[1]}"`)
return this.input.setValue(el.getAttribute(splitted[1]))
this.input.setValue(el.getAttribute(splitted[1]))
return
}
this.input.setValue(attrVal)
}

View File

@ -1,4 +1,4 @@
import AttributeAbstract from "./AttributeAbstract";
import AbstractAttribute from "./AbstractAttribute";
import AttributeListeners from "./AttributeListeners";
import AttributeIdentity from "./Interfaces/AttributeIdentity";
@ -23,7 +23,7 @@ import AttributeIdentity from "./Interfaces/AttributeIdentity";
* @implements {FMAFormInitInterface}
*/
export default class IgnoreAttribute
extends AttributeAbstract {
extends AbstractAttribute {
public trigger(_: AttributeListeners, data?: any): boolean | void | object {
data[this.input.getName()] = undefined
return data

View File

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

View File

@ -1,9 +1,9 @@
import AttributeIdentity from './Interfaces/AttributeIdentity';
import AttributeAbstract from './AttributeAbstract';
import AbstractAttribute from './AbstractAttribute';
import AttributeListeners from "./AttributeListeners";
export default class RegexAttribute
extends AttributeAbstract {
extends AbstractAttribute {
public trigger(): boolean {
const regStr = this.input.element.dataset.regex
if (!regStr) return true

View File

@ -12,9 +12,11 @@ export default class CheckboxInput extends DefaultInput {
public setValue(value: any) {
this.element.checked = this.formatValue(value)
}
public getValue(): boolean {
return this.element.checked
}
public formatValue(value: any): boolean {
value = toBoolean(value)
if (typeof value === "undefined") {

View File

@ -9,7 +9,6 @@ import DefaultInput from './DefaultInput'
export default class DateInput extends DefaultInput {
public setValue(value: any) {
// handle GO null value
const format = this.formatValue(value)
if (typeof format === "object") {
this.element.valueAsDate = format
@ -28,6 +27,7 @@ export default class DateInput extends DefaultInput {
if (typeof val === "object" && typeof val.getDate === "function") {
return (val as Date)
}
// handle GO null value
if (val === "0001-01-01T00:00:00Z") {
return undefined
}

View File

@ -1,11 +1,11 @@
import { realType } from "../Functions"
import InputAbstract from "./InputAbstract"
import AbstractInput from "./AbstractInput"
import InputIdentity from "./Interfaces/InputIdentity"
export default class DefaultInput extends InputAbstract {
export default class DefaultInput extends AbstractInput {
public setValue(value: any) {
this.element.value = this.formatValue(value)
this.element.value = this.formatValue(value) || ""
}
public getValue(): any {
@ -13,7 +13,6 @@ export default class DefaultInput extends InputAbstract {
}
public formatValue(value: any): any {
if (typeof value === "undefined") return ""
// if the value is a number return it as a number obj
return realType(value)
}

View File

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

View File

@ -1,8 +1,8 @@
import InputAbstract from "../InputAbstract";
import AbstractInput from "../AbstractInput";
import FormManager from "../../FormManager";
interface InputConstructor {
new(element: HTMLElement, form: FormManager): InputAbstract
new(element: HTMLElement, form: FormManager): AbstractInput
}
/**

View File

@ -0,0 +1,25 @@
import InputIdentity from './Interfaces/InputIdentity';
import DefaultInput from './DefaultInput';
import { toNumber, isNumber } from '../Functions';
/**
*
* @class FMDateInput
* @extends {FMInput}
*/
export default class NumberInput extends DefaultInput {
public formatValue(value: any): number|undefined {
const n = toNumber(value)
return n
}
public verify(): boolean {
return typeof this.getValue() === "undefined" || isNumber(this.getValue())
}
public static identity: InputIdentity = {
input: NumberInput,
type: "number"
}
}

View File

@ -1,6 +1,6 @@
import FormManager from "../FormManager"
import DefaultInput from './DefaultInput';
import InputAbstract from './InputAbstract';
import InputAbstract from './AbstractInput';
import InputIdentity from './Interfaces/InputIdentity';
/**
@ -89,14 +89,15 @@ export default class RepeatInput extends DefaultInput {
input.element.disabled = true
}
sub.push(input)
// if values is a named array
if (values != undefined && values[input.getName()] != undefined) {
input.setValue(values[input.getName()])
return
}
// if value is a single string/number/etc
if (typeof(values) != "object" && values != undefined) {
input.setValue(values)
}
// Set default value
input.setValue(values)
})
this.elements.push(sub)

View File

@ -9,14 +9,28 @@ import { realType } from '../Functions';
*/
export default class SelectInput extends DefaultInput {
public formatValue(value: any): any {
if (typeof value === "undefined") {
const opt: HTMLOptionElement|null = this.element.querySelector("option[selected]")
if (opt) {
return opt.value
}
public setValue(value: any) {
value = realType(value)
let opt:HTMLOptionElement|undefined = this.element.querySelector(`option[value="${value}"]`) || undefined
if (opt) {
this.element.value = value
return
}
return realType(value)
opt = this.element.querySelector("option[selected]") || undefined
if (opt) {
this.element.value = opt.value
}
}
public formatValue(value: any): any {
if (typeof value !== "undefined" && value !== "") {
return realType(value)
}
const opt: HTMLOptionElement|undefined = this.element.querySelector("option[selected]") || undefined
if (opt) {
return opt.value
}
throw Error(":O it should never come here")
}
public static identity: InputIdentity = {