165 lines
6.2 KiB
TypeScript
165 lines
6.2 KiB
TypeScript
const { compare }=require('natural-orderby');
|
|
const errors=require("./errors.js");
|
|
import { DOMElement, Selectors } from "./interfaces";
|
|
import { FreeDatas2HTML } from "./FreeDatas2HTML";
|
|
|
|
export class Selector implements Selectors
|
|
{
|
|
private _converter: FreeDatas2HTML;
|
|
private _datasFieldNb: number;
|
|
private _datasViewElt: DOMElement={ id: "", eltDOM: undefined };
|
|
private _selectedValue: number|undefined=undefined;
|
|
private _separator: string|undefined;
|
|
private _values: string[]=[];
|
|
private _name: string="";
|
|
|
|
// Injection de la classe principale, mais uniquement si des données ont été importées
|
|
// Le champ duquel le sélecteur tire ses données doit exister ?
|
|
constructor(converter: FreeDatas2HTML, datasFieldNb: number, elt: DOMElement, separator?: string)
|
|
{
|
|
if(converter.fields.length === 0 || converter.datas.length === 0)
|
|
throw new Error(errors.filterNeedDatas);
|
|
else if(! converter.checkFieldExist(Number(datasFieldNb)))
|
|
throw new Error(errors.selectorFieldNotFound);
|
|
else
|
|
{
|
|
this._datasViewElt=FreeDatas2HTML.checkInDOMById(elt);
|
|
this._converter=converter;
|
|
this._datasFieldNb=datasFieldNb;
|
|
// Pas de trim(), car l'espace peut être le séparateur :
|
|
if(separator !== undefined && separator !== "")
|
|
this._separator=separator;
|
|
}
|
|
}
|
|
|
|
get converter() : FreeDatas2HTML
|
|
{
|
|
return this._converter;
|
|
}
|
|
|
|
get datasViewElt() : DOMElement
|
|
{
|
|
return this._datasViewElt;
|
|
}
|
|
|
|
get datasFieldNb() : number
|
|
{
|
|
return this._datasFieldNb;
|
|
}
|
|
|
|
get name() : string
|
|
{
|
|
return this._name;
|
|
}
|
|
|
|
get selectedValue() : number|undefined
|
|
{
|
|
return this._selectedValue;
|
|
}
|
|
|
|
get separator() : string|undefined
|
|
{
|
|
return this._separator;
|
|
}
|
|
|
|
get values(): string[]
|
|
{
|
|
return this._values;
|
|
}
|
|
|
|
// Création du <select> dans le DOM correspondant au filtre
|
|
public filter2HTML(label:string="") : void
|
|
{
|
|
this._name=this._converter.fields![this._datasFieldNb]; // "!" car l'existence du champ est testé par le constructeur
|
|
for (let row of this._converter.datas)
|
|
{
|
|
let checkedValue;
|
|
if(this._separator === undefined)
|
|
{
|
|
checkedValue=row[this._name].trim(); // trim() évite des problèmes de classement des éléments du SELECT
|
|
if(checkedValue !== "" && this._values.indexOf(checkedValue) === -1)
|
|
this._values.push(checkedValue);
|
|
}
|
|
else
|
|
{
|
|
let checkedValues=row[this._name].split(this._separator);
|
|
for(let value of checkedValues)
|
|
{
|
|
checkedValue=value.trim();
|
|
if(checkedValue !== "" && this._values.indexOf(checkedValue) === -1)
|
|
this._values.push(checkedValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(this._values.length === 0) // possible si uniquement des valeurs vides pour ce champ
|
|
throw new Error(errors.selectorFieldIsEmpty);
|
|
else
|
|
{
|
|
// Classement des données à l'aide (ou non) d'une fonction spécifique :
|
|
if(this._converter.getSortingFunctionForField(this._datasFieldNb) !== undefined)
|
|
this._values.sort(this._converter.getSortingFunctionForField(this._datasFieldNb)!.sort); // sans le "!" : TS2532: Object is possibly 'undefined' ???
|
|
else
|
|
this._values.sort(compare());
|
|
|
|
// Création et injection du SELECT dans le DOM
|
|
label=(label === "") ? this._name : label;
|
|
let selectorsHTML="<label for='freeDatas2HTML_"+this._datasViewElt.id+"'>"+label+" :</label><select name='freeDatas2HTML_"+this._datasViewElt.id+"' id='freeDatas2HTML_"+this._datasViewElt.id+"'><option value='0'>----</option>"; // l'option zéro permet d'actualiser l'affichage en ignorant ce filtre
|
|
for(let i=0; i< this._values.length; i++)
|
|
selectorsHTML+="<option value='"+(i+1)+"'>"+this._values[i]+"</option>";
|
|
selectorsHTML+="</select>";
|
|
this. _datasViewElt.eltDOM!.innerHTML=selectorsHTML;// "!" car l'existence de "eltDOM" est testé par le constructeur
|
|
|
|
const selectElement=document.getElementById("freeDatas2HTML_"+this._datasViewElt.id) as HTMLInputElement, mySelector=this;
|
|
selectElement.addEventListener("change", function(e)
|
|
{
|
|
if(selectElement.value === "0")
|
|
mySelector._selectedValue=undefined;
|
|
else
|
|
mySelector._selectedValue=parseInt(selectElement.value,10)-1;
|
|
mySelector._converter.refreshView();
|
|
});
|
|
}
|
|
}
|
|
|
|
public dataIsOk(data: {[index: string]:string}) : boolean
|
|
{
|
|
// Permet de vérifier que filter2HTML() a été préalablement appelée :
|
|
if(this._name === "")
|
|
throw new Error(errors.filterCheckIsOkFail);
|
|
|
|
// Pas de valeur sélectionnée = pas de filtre sur ce champ
|
|
if(this._selectedValue === undefined)
|
|
return true;
|
|
|
|
if(this._values[this._selectedValue] === undefined) // théoriquement impossible, mais cela vient du client...
|
|
throw new Error(errors.selectorSelectedIndexNotFound);
|
|
|
|
// Si le champ est absent pour un enregistrement, il est refusé
|
|
if(data[this._name] === undefined)
|
|
return false;
|
|
|
|
const selectedValueTxt=this._values[this._selectedValue];
|
|
if(this._separator === undefined)
|
|
{
|
|
if(data[this._name].trim() !== selectedValueTxt)
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
let find=false;
|
|
let checkedValues=data[this._name].split(this._separator);
|
|
for(let value of checkedValues)
|
|
{
|
|
if(value.trim() === selectedValueTxt)
|
|
{
|
|
find=true;
|
|
break;
|
|
}
|
|
}
|
|
return find;
|
|
}
|
|
}
|
|
} |