Ajout possibilité de fournir des fonctions spécifiques pour classer les données de certaines colonnes.
This commit is contained in:
parent
75c9efc3b1
commit
66ea27b0fb
@ -18,9 +18,9 @@ De même l'idée est de rester libre du rendu des données en n'imposant pas de
|
||||
|
||||
La première version se contente de récupérer et parser des données présentes dans un fichier CSV via un appel Ajax.
|
||||
Les données trouvées sont affichées dans un tableau. En option, des colonnes peuvent être indiquées par filtrer les données et/ou les classer.
|
||||
Il est possible de fournir des fonctions spécifiques pour classer les données de certaines colonnes.
|
||||
|
||||
Il reste à ajouter :
|
||||
- la possibilité de fournir des fonctions spécifiques pour classer les données de certaines colonnes.
|
||||
- la possibilité de paginer les données.
|
||||
- la possibilité d'utiliser des sources/formats différents qu'un fichier CSV pour extraire les données.
|
||||
- la possibilité de spécifier un code HTML autre qu'un tableau pour lister les données.
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "freedatas2html",
|
||||
"version": "0.3.5",
|
||||
"version": "0.3.6",
|
||||
"description": "Visualization of data from various sources (CSV, API, HTML...) with filters, classification, pagination, etc.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
@ -7,7 +7,20 @@ const initialise = async () =>
|
||||
let converter=new freeDatas2HTML();
|
||||
converter.datasViewElt={ id:"datas" };
|
||||
converter.datasSelectors=[{ datasFieldNb:3, id:"filtre1"}, { datasFieldNb:4, id:"filtre2"},{ datasFieldNb:5, id:"filtre3", separator:"," }];
|
||||
converter.datasSortingColumns=[{ datasFieldNb:0 }, { datasFieldNb:1 },{ datasFieldNb:2 }];
|
||||
const mySort = (a: any, b: any, order: "asc"|"desc" = "asc") =>
|
||||
{
|
||||
const values = [ "> 100000", "> 1 et < 100 000", "≤ 1", "Traces", "Inexistant"];
|
||||
if(order === "desc")
|
||||
values.reverse();
|
||||
if(values.indexOf(a) > values.indexOf(b))
|
||||
return -1;
|
||||
else if(values.indexOf(a) < values.indexOf(b))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
};
|
||||
converter.datasSortingColumns=[{ datasFieldNb:0 }, { datasFieldNb:1 },{ datasFieldNb:2 }, { datasFieldNb:4 }];
|
||||
converter.datasSortingFunctions= [{ datasFieldNb:4, sort:mySort}];
|
||||
converter.datasSourceUrl="http://localhost:8080/datas/elements-chimiques.csv";
|
||||
await converter.run();
|
||||
}
|
||||
|
@ -8,18 +8,20 @@ import { domElement, selectors, sortingColumns, sortingFunctions } from "./free
|
||||
export class freeDatas2HTML
|
||||
{
|
||||
private _datasViewElt: domElement = { id:"", eltDOM:undefined };
|
||||
private _datasSourceUrl: string = "";
|
||||
public datasHTML: string = "";
|
||||
// Revoir car tous les attributs suivants sont liés aux colonnes/fields des données (créer une classe ?)
|
||||
private _datasSelectors: selectors[] = [];
|
||||
private _datasSortingColumns: sortingColumns[] = [];
|
||||
private _datasSortedColumn: sortingColumns|undefined;
|
||||
|
||||
private _datasSortingFunctions: sortingFunctions[] = [];
|
||||
// Parseur fichier :
|
||||
private _datasSourceUrl: string = "";
|
||||
public parseMeta: papaParseMeta|undefined = undefined;
|
||||
public parseDatas: papaParseDatas[] = [];
|
||||
public parseErrors: papaParseErrors[] = [];
|
||||
public datasHTML: string = "";
|
||||
public stopIfParseErrors: boolean = false;
|
||||
|
||||
public static isNaturalNumber(nb)
|
||||
public static isNaturalNumber(nb: number)
|
||||
{
|
||||
return (Number.isInteger(nb) === false || nb < 0) ? false : true;
|
||||
}
|
||||
@ -84,12 +86,36 @@ export class freeDatas2HTML
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get datasSortingColumns() : sortingColumns[]
|
||||
|
||||
get datasSortingColumns() : sortingColumns[]
|
||||
{
|
||||
return this._datasSortingColumns;
|
||||
}
|
||||
|
||||
|
||||
// Attention : une fonction de classement peut aussi bien servir à une colonne triable, qu'à une colonne servant à filtrer les données
|
||||
set datasSortingFunctions(sortingFunctions: sortingFunctions[])
|
||||
{
|
||||
this._datasSortingFunctions=[];
|
||||
for(let i = 0; i < sortingFunctions.length; i++)
|
||||
{
|
||||
if(freeDatas2HTML.isNaturalNumber(sortingFunctions[i].datasFieldNb) === false)
|
||||
console.error(errors.needNaturalNumber);
|
||||
else
|
||||
this._datasSortingFunctions.push(sortingFunctions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Retourne la fonction spécifique de classement associée à une colonne
|
||||
public getSortingFunctionForField(datasFieldNb: number) : sortingFunctions|undefined
|
||||
{
|
||||
for(let i in this._datasSortingFunctions)
|
||||
{
|
||||
if(this._datasSortingFunctions[i].datasFieldNb === datasFieldNb)
|
||||
return this._datasSortingFunctions[i];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public async parse(): Promise<any>
|
||||
{
|
||||
const converter=this;
|
||||
@ -172,7 +198,6 @@ export class freeDatas2HTML
|
||||
let checkedValues=this.parseDatas[row][colName].split(this._datasSelectors[i].separator as string);
|
||||
for(let i in checkedValues)
|
||||
{
|
||||
|
||||
let checkedValue=checkedValues[i].trim();
|
||||
if(checkedValue !== "" && values.indexOf(checkedValue) === -1)
|
||||
values.push(checkedValue);
|
||||
@ -181,7 +206,10 @@ export class freeDatas2HTML
|
||||
}
|
||||
if(values.length > 0)
|
||||
{
|
||||
values.sort(compare());
|
||||
if(this.getSortingFunctionForField(this._datasSelectors[i].datasFieldNb) !== undefined)
|
||||
values.sort(this.getSortingFunctionForField(this._datasSelectors[i].datasFieldNb)!.sort);
|
||||
else
|
||||
values.sort(compare());
|
||||
this._datasSelectors[i].name=colName;
|
||||
this._datasSelectors[i].values=values;
|
||||
selectorsHTML[i]="<label for='freeDatas2HTMLSelector"+i+"'>"+colName+" : </label><select name='freeDatas2HTMLSelector"+i+"' id='freeDatas2HTMLSelector"+i+"'><option value='0'>----</option>";
|
||||
@ -220,7 +248,7 @@ export class freeDatas2HTML
|
||||
{
|
||||
const converter=this;
|
||||
this._datasViewElt.eltDOM.innerHTML=this.datasHTML;
|
||||
// Ici car il faut que la tableau soit déjà dans le DOM pour écouter les clics
|
||||
// Ici, car il faut que le tableau soit déjà dans le DOM pour "mettre sous écoute" les clics
|
||||
if(this._datasSortingColumns.length > 0)
|
||||
{
|
||||
let getTableTh=document.querySelectorAll("table th");
|
||||
@ -233,7 +261,7 @@ export class freeDatas2HTML
|
||||
htmlContent="<a href='#freeDatas2HTMLSorting"+datasFieldNb+"' id='freeDatas2HTMLSorting"+datasFieldNb+"'>"+htmlContent+"</a>";
|
||||
getTableTh[datasFieldNb].innerHTML=htmlContent;
|
||||
let sortingElement=document.getElementById("freeDatas2HTMLSorting"+datasFieldNb);
|
||||
sortingElement!.addEventListener('click', function(e)
|
||||
sortingElement!.addEventListener("click", function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
let order=converter.datasSortingColumns[i].order ;
|
||||
@ -268,7 +296,14 @@ export class freeDatas2HTML
|
||||
{
|
||||
const col=fields[this._datasSortedColumn.datasFieldNb];
|
||||
const colOrder=this._datasSortedColumn.order;
|
||||
datas.sort( (a, b) => compare( {order: colOrder} )(a[col], b[col]));
|
||||
// Une fonction spécifique de classement a-t-elle été définie ?
|
||||
if(this.getSortingFunctionForField(this._datasSortedColumn.datasFieldNb) !== undefined)
|
||||
{
|
||||
let myFunction=this.getSortingFunctionForField(this._datasSortedColumn.datasFieldNb);
|
||||
datas.sort( (a, b) => { return myFunction!.sort(a[col], b[col], colOrder); });
|
||||
}
|
||||
else
|
||||
datas.sort( (a, b) => compare( {order: colOrder} )(a[col], b[col]));
|
||||
}
|
||||
|
||||
// Création du tableau de données :
|
||||
|
@ -14,4 +14,9 @@ export interface sortingColumns
|
||||
{
|
||||
datasFieldNb: number;
|
||||
order?: "asc"|"desc"|undefined;
|
||||
}
|
||||
export interface sortingFunctions
|
||||
{
|
||||
datasFieldNb: number;
|
||||
sort(a: any,b: any, order?: "asc"|"desc"): number; // cf. https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
|
||||
}
|
@ -41,7 +41,6 @@ describe("freeDatas2HTML", () =>
|
||||
expect(converter.datasSelectors[0].id).toEqual("selector2");
|
||||
});
|
||||
|
||||
// Utile pour tester les valeurs fournies pour les numéros de colonne
|
||||
it("Doit retourner un booléen indiquant si un nombre est naturel ou non.", () =>
|
||||
{
|
||||
expect(freeDatas2HTML.isNaturalNumber(-1)).toBeFalse();
|
||||
@ -66,6 +65,23 @@ describe("freeDatas2HTML", () =>
|
||||
{
|
||||
expect(() => { return converter.datasSourceUrl=" "; }).toThrowError(errors.needUrl);
|
||||
});
|
||||
|
||||
it("Doit me retourner la fonction associée à une colonne, de manière à ce qu'elle soit utilisable pour comparer deux valeurs.", () =>
|
||||
{
|
||||
// Fonction volontairement basique, car ce n'est pas la fonction que l'on teste ici, mais le fait que l'on puisse l'utiliser !
|
||||
const simpleSort = (a: any, b: any) =>
|
||||
{
|
||||
if(a < b)
|
||||
return 1;
|
||||
else if(a > b)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
};
|
||||
converter.datasSortingFunctions=[{ datasFieldNb:0, sort:simpleSort }];
|
||||
expect(converter.getSortingFunctionForField(0)).toBeDefined();
|
||||
expect([7,9,3,5].sort(converter.getSortingFunctionForField(0).sort)).toEqual([9,7,5,3]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Parsage du fichier et création du tableau de données", () =>
|
||||
|
Loading…
Reference in New Issue
Block a user