Ajout fonctionnalité permettant de classer les données via les colonnes + adaptation exemple et nouvelle compilation du code en JS

This commit is contained in:
Fabrice PENHOËT 2021-09-02 18:15:15 +02:00
parent 14608b8488
commit 4939153d89
11 changed files with 1015 additions and 43 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "freedatas2html", "name": "freedatas2html",
"version": "0.3.4", "version": "0.3.5",
"description": "Visualization of data from various sources (CSV, API, HTML...) with filters, classification, pagination, etc.", "description": "Visualization of data from various sources (CSV, API, HTML...) with filters, classification, pagination, etc.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

File diff suppressed because one or more lines are too long

View File

@ -19,6 +19,7 @@
</article> </article>
<aside><p>Les données affichées viennent d'<a href="datas/elements-chimiques.csv">un fichier CSV</a> reprenant une partie des informations trouvées <a href="https://fr.wikipedia.org/wiki/%C3%89l%C3%A9ment_chimique#Caract%C3%A9ristiques_des_diff%C3%A9rents_%C3%A9l%C3%A9ments" target="_blank">sur Wikipédia</a>.</p> <aside><p>Les données affichées viennent d'<a href="datas/elements-chimiques.csv">un fichier CSV</a> reprenant une partie des informations trouvées <a href="https://fr.wikipedia.org/wiki/%C3%89l%C3%A9ment_chimique#Caract%C3%A9ristiques_des_diff%C3%A9rents_%C3%A9l%C3%A9ments" target="_blank">sur Wikipédia</a>.</p>
<p>La dernière colonne permet de montrer la possibilité d'<b>extraire des données d'une colonne ayant plusieurs valeurs par ligne</b>, ici séparées par une virgule.<br>Ce choix de la virgule comme séparateur ne pose pas de problème, tant le fichier CSV est correctement conçu.<br>Elle ne doit par contre pas être présente dans les expressions à extraire de la colonne, sachant que l'on peut désigner n'importe quel autre caractère séparateur.</p> <p>La dernière colonne permet de montrer la possibilité d'<b>extraire des données d'une colonne ayant plusieurs valeurs par ligne</b>, ici séparées par une virgule.<br>Ce choix de la virgule comme séparateur ne pose pas de problème, tant le fichier CSV est correctement conçu.<br>Elle ne doit par contre pas être présente dans les expressions à extraire de la colonne, sachant que l'on peut désigner n'importe quel autre caractère séparateur.</p>
<p>Toujours en option, certaines peuvent être désignées comme permettant de classer les données: un 1ᵉʳ clic lance un classement par ordre croissant, le 2ᵉ pour ordre décroissant et ainsi de suite.</p>
<p>Design basé sur <a href="https://www.getpapercss.com" target="_blank">PaperCSS</a></p></aside> <p>Design basé sur <a href="https://www.getpapercss.com" target="_blank">PaperCSS</a></p></aside>
</body> </body>
</html> </html>

View File

@ -43,7 +43,8 @@ var initialise = function () { return __awaiter(void 0, void 0, void 0, function
_a.trys.push([0, 2, , 3]); _a.trys.push([0, 2, , 3]);
converter = new freeDatas2HTML(); converter = new freeDatas2HTML();
converter.datasViewElt = { id: "datas" }; converter.datasViewElt = { id: "datas" };
converter.datasSelectors = [{ datasFielNb: 3, id: "filtre1" }, { datasFielNb: 4, id: "filtre2" }]; converter.datasSelectors = [{ datasFieldNb: 3, id: "filtre1" }, { datasFieldNb: 4, id: "filtre2" }, { datasFieldNb: 5, id: "filtre3", separator: "," }];
converter.datasSortingColumns = [{ datasFieldNb: 0 }, { datasFieldNb: 1 }, { datasFieldNb: 2 }];
converter.datasSourceUrl = "http://localhost:8080/datas/elements-chimiques.csv"; converter.datasSourceUrl = "http://localhost:8080/datas/elements-chimiques.csv";
return [4, converter.run()]; return [4, converter.run()];
case 1: case 1:

View File

@ -36,11 +36,13 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
}; };
var Papa = require("papaparse"); var Papa = require("papaparse");
var errors = require("./errors.js"); var errors = require("./errors.js");
var compare = require('natural-orderby').compare;
var freeDatas2HTML = (function () { var freeDatas2HTML = (function () {
function freeDatas2HTML() { function freeDatas2HTML() {
this._datasViewElt = { id: "", eltDOM: undefined }; this._datasViewElt = { id: "", eltDOM: undefined };
this._datasSourceUrl = ""; this._datasSourceUrl = "";
this._datasSelectors = []; this._datasSelectors = [];
this._datasSortingColumns = [];
this.parseMeta = undefined; this.parseMeta = undefined;
this.parseDatas = []; this.parseDatas = [];
this.parseErrors = []; this.parseErrors = [];
@ -81,10 +83,12 @@ var freeDatas2HTML = (function () {
checkContainerExist = document.getElementById(selectionElts[i].id); checkContainerExist = document.getElementById(selectionElts[i].id);
if (checkContainerExist === null) if (checkContainerExist === null)
console.error(errors.elementNotFound + selectionElts[i].id); console.error(errors.elementNotFound + selectionElts[i].id);
else if (Number.isInteger(selectionElts[i].datasFielNb) === false || selectionElts[i].datasFielNb < 0) else if (Number.isInteger(selectionElts[i].datasFieldNb) === false || selectionElts[i].datasFieldNb < 0)
console.error(errors.needNaturalNumber); console.error(errors.needNaturalNumber);
else { else {
selectionElts[i].eltDOM = checkContainerExist; selectionElts[i].eltDOM = checkContainerExist;
if (selectionElts[i].separator !== undefined && selectionElts[i].separator === "")
selectionElts[i].separator = undefined;
this._datasSelectors.push(selectionElts[i]); this._datasSelectors.push(selectionElts[i]);
} }
} }
@ -92,6 +96,24 @@ var freeDatas2HTML = (function () {
enumerable: true, enumerable: true,
configurable: true configurable: true
}); });
Object.defineProperty(freeDatas2HTML.prototype, "datasSortingColumns", {
get: function () {
return this._datasSortingColumns;
},
set: function (sortingColumns) {
this._datasSortingColumns = [];
for (var i = 0; i < sortingColumns.length; i++) {
if (Number.isInteger(sortingColumns[i].datasFieldNb) === false || sortingColumns[i].datasFieldNb < 0)
console.error(errors.needNaturalNumber);
else {
sortingColumns[i].order = undefined;
this._datasSortingColumns.push(sortingColumns[i]);
}
}
},
enumerable: true,
configurable: true
});
freeDatas2HTML.prototype.parse = function () { freeDatas2HTML.prototype.parse = function () {
return __awaiter(this, void 0, void 0, function () { return __awaiter(this, void 0, void 0, function () {
var converter; var converter;
@ -129,7 +151,7 @@ var freeDatas2HTML = (function () {
}; };
freeDatas2HTML.prototype.run = function () { freeDatas2HTML.prototype.run = function () {
return __awaiter(this, void 0, void 0, function () { return __awaiter(this, void 0, void 0, function () {
var converter_1, selectorsHTML, i, values, colName, row, j, selectElement; var converter_1, selectorsHTML, i, values, colName, row, checkedValue, checkedValues, i_1, checkedValue, j, selectElement, i;
return __generator(this, function (_a) { return __generator(this, function (_a) {
switch (_a.label) { switch (_a.label) {
case 0: case 0:
@ -146,21 +168,30 @@ var freeDatas2HTML = (function () {
console.error(this.parseErrors); console.error(this.parseErrors);
else { else {
converter_1 = this; converter_1 = this;
this.datasHTML = this.createDatasHTML(this.parseMeta.fields, this.parseDatas);
this._datasViewElt.eltDOM.innerHTML = this.datasHTML;
if (this._datasSelectors.length > 0) { if (this._datasSelectors.length > 0) {
selectorsHTML = []; selectorsHTML = [];
for (i in this._datasSelectors) { for (i in this._datasSelectors) {
if (this._datasSelectors[i].datasFielNb > (this.parseMeta.fields.length - 1)) if (this._datasSelectors[i].datasFieldNb > (this.parseMeta.fields.length - 1))
throw new Error(errors.selectorFieldNotFound); throw new Error(errors.selectorFieldNotFound);
else { else {
values = [], colName = this.parseMeta.fields[this._datasSelectors[i].datasFielNb]; values = [], colName = this.parseMeta.fields[this._datasSelectors[i].datasFieldNb];
for (row in this.parseDatas) { for (row in this.parseDatas) {
if (values.indexOf(this.parseDatas[row][colName].trim()) === -1) if (this._datasSelectors[i].separator === undefined) {
values.push(this.parseDatas[row][colName].trim()); checkedValue = this.parseDatas[row][colName].trim();
if (checkedValue !== "" && values.indexOf(checkedValue) === -1)
values.push(checkedValue);
}
else {
checkedValues = this.parseDatas[row][colName].split(this._datasSelectors[i].separator);
for (i_1 in checkedValues) {
checkedValue = checkedValues[i_1].trim();
if (checkedValue !== "" && values.indexOf(checkedValue) === -1)
values.push(checkedValue);
}
}
} }
if (values.length > 0) { if (values.length > 0) {
values.sort(); values.sort(compare());
this._datasSelectors[i].name = colName; this._datasSelectors[i].name = colName;
this._datasSelectors[i].values = values; this._datasSelectors[i].values = values;
selectorsHTML[i] = "<label for='freeDatas2HTMLSelector" + i + "'>" + colName + " : </label><select name='freeDatas2HTMLSelector" + i + "' id='freeDatas2HTMLSelector" + i + "'><option value='0'>----</option>"; selectorsHTML[i] = "<label for='freeDatas2HTMLSelector" + i + "'>" + colName + " : </label><select name='freeDatas2HTMLSelector" + i + "' id='freeDatas2HTMLSelector" + i + "'><option value='0'>----</option>";
@ -171,12 +202,18 @@ var freeDatas2HTML = (function () {
selectElement = document.getElementById("freeDatas2HTMLSelector" + i); selectElement = document.getElementById("freeDatas2HTMLSelector" + i);
selectElement.addEventListener('change', function (e) { selectElement.addEventListener('change', function (e) {
converter_1.datasHTML = converter_1.createDatasHTML(converter_1.parseMeta.fields, converter_1.parseDatas); converter_1.datasHTML = converter_1.createDatasHTML(converter_1.parseMeta.fields, converter_1.parseDatas);
converter_1._datasViewElt.eltDOM.innerHTML = converter_1.datasHTML; converter_1.refreshView();
}); });
} }
} }
} }
} }
for (i in this._datasSortingColumns) {
if (this._datasSortingColumns[i].datasFieldNb > (this.parseMeta.fields.length - 1))
throw new Error(errors.sortingColumnsFieldNotFound);
}
this.datasHTML = this.createDatasHTML(this.parseMeta.fields, this.parseDatas);
this.refreshView();
return [2, true]; return [2, true];
} }
return [2]; return [2];
@ -184,12 +221,50 @@ var freeDatas2HTML = (function () {
}); });
}); });
}; };
freeDatas2HTML.prototype.refreshView = function () {
if (this._datasViewElt.eltDOM !== undefined) {
var converter_2 = this;
this._datasViewElt.eltDOM.innerHTML = this.datasHTML;
if (this._datasSortingColumns.length > 0) {
var getTableTh = document.querySelectorAll("table th");
if (getTableTh !== null) {
var _loop_1 = function (i) {
var datasFieldNb = this_1._datasSortingColumns[i].datasFieldNb;
var htmlContent = getTableTh[datasFieldNb].innerHTML;
htmlContent = "<a href='#freeDatas2HTMLSorting" + datasFieldNb + "' id='freeDatas2HTMLSorting" + datasFieldNb + "'>" + htmlContent + "</a>";
getTableTh[datasFieldNb].innerHTML = htmlContent;
var sortingElement = document.getElementById("freeDatas2HTMLSorting" + datasFieldNb);
sortingElement.addEventListener('click', function (e) {
e.preventDefault();
var order = converter_2.datasSortingColumns[i].order;
if (order === undefined || order === "desc")
converter_2.datasSortingColumns[i].order = "asc";
else
converter_2.datasSortingColumns[i].order = "desc";
converter_2._datasSortedColumn = converter_2.datasSortingColumns[i];
converter_2.datasHTML = converter_2.createDatasHTML(converter_2.parseMeta.fields, converter_2.parseDatas);
converter_2.refreshView();
});
};
var this_1 = this;
for (var i in this._datasSortingColumns) {
_loop_1(i);
}
}
}
}
};
freeDatas2HTML.prototype.createDatasHTML = function (fields, datas) { freeDatas2HTML.prototype.createDatasHTML = function (fields, datas) {
var checkSelectorExist, filters = []; var checkSelectorExist, filters = [];
for (var i in this._datasSelectors) { for (var i in this._datasSelectors) {
checkSelectorExist = document.querySelector("#" + this._datasSelectors[i].id + " select"); checkSelectorExist = document.querySelector("#" + this._datasSelectors[i].id + " select");
if (checkSelectorExist != null && checkSelectorExist.value != "0") if (checkSelectorExist != null && checkSelectorExist.selectedIndex != 0)
filters.push({ field: this._datasSelectors[i].name, value: this._datasSelectors[i].values[checkSelectorExist.selectedIndex - 1] }); filters.push({ field: this._datasSelectors[i].name, value: this._datasSelectors[i].values[checkSelectorExist.selectedIndex - 1], separator: this._datasSelectors[i].separator });
}
if (this._datasSortedColumn !== undefined) {
var col_1 = fields[this._datasSortedColumn.datasFieldNb];
var colOrder_1 = this._datasSortedColumn.order;
datas.sort(function (a, b) { return compare({ order: colOrder_1 })(a[col_1], b[col_1]); });
} }
var datasHTML = "<table><thead>"; var datasHTML = "<table><thead>";
for (var i in fields) for (var i in fields)
@ -199,9 +274,22 @@ var freeDatas2HTML = (function () {
var visible = true; var visible = true;
if (filters.length !== 0) { if (filters.length !== 0) {
for (var i in filters) { for (var i in filters) {
if (filters[i].separator === undefined) {
if (datas[row][filters[i].field].trim() != filters[i].value) if (datas[row][filters[i].field].trim() != filters[i].value)
visible = false; visible = false;
} }
else {
var checkedValues = datas[row][filters[i].field].split(filters[i].separator), finded = false;
for (var j in checkedValues) {
if (checkedValues[j].trim() === filters[i].value) {
finded = true;
break;
}
}
if (!finded)
visible = false;
}
}
} }
if (visible) { if (visible) {
datasHTML += "<tr>"; datasHTML += "<tr>";

View File

@ -7,4 +7,5 @@ module.exports =
needUrl: "Merci de fournir une url valide pour le fichier CSV à parser.", needUrl: "Merci de fournir une url valide pour le fichier CSV à parser.",
parserFail: "La lecture des données du fichier a échoué.", parserFail: "La lecture des données du fichier a échoué.",
selectorFieldNotFound: "Au moins une des colonnes devant servir à filtrer les données n'existe pas dans le fichier.", selectorFieldNotFound: "Au moins une des colonnes devant servir à filtrer les données n'existe pas dans le fichier.",
sortingColumnsFieldNotFound: "Au moins une des colonnes devant servir à classer les données n'existe pas dans le fichier.",
}; };

View File

@ -7,6 +7,7 @@ const initialise = async () =>
let converter=new freeDatas2HTML(); let converter=new freeDatas2HTML();
converter.datasViewElt={ id:"datas" }; converter.datasViewElt={ id:"datas" };
converter.datasSelectors=[{ datasFieldNb:3, id:"filtre1"}, { datasFieldNb:4, id:"filtre2"},{ datasFieldNb:5, id:"filtre3", separator:"," }]; converter.datasSelectors=[{ datasFieldNb:3, id:"filtre1"}, { datasFieldNb:4, id:"filtre2"},{ datasFieldNb:5, id:"filtre3", separator:"," }];
converter.datasSortingColumns=[{ datasFieldNb:0 }, { datasFieldNb:1 },{ datasFieldNb:2 }];
converter.datasSourceUrl="http://localhost:8080/datas/elements-chimiques.csv"; converter.datasSourceUrl="http://localhost:8080/datas/elements-chimiques.csv";
await converter.run(); await converter.run();
} }

View File

@ -3,13 +3,15 @@ const errors = require("./errors.js");
const { compare }= require('natural-orderby'); const { compare }= require('natural-orderby');
import { papaParseDatas, papaParseErrors, papaParseMeta } from "./papaParseInterfaces"; import { papaParseDatas, papaParseErrors, papaParseMeta } from "./papaParseInterfaces";
import { domElement, selectors } from "./freeDatas2HTMLInterfaces"; import { domElement, selectors, sortingColumns } from "./freeDatas2HTMLInterfaces";
export class freeDatas2HTML export class freeDatas2HTML
{ {
private _datasViewElt: domElement = { id:"", eltDOM:undefined }; private _datasViewElt: domElement = { id:"", eltDOM:undefined };
private _datasSourceUrl: string = ""; private _datasSourceUrl: string = "";
private _datasSelectors: selectors[] = []; private _datasSelectors: selectors[] = [];
private _datasSortingColumns: sortingColumns[] = [];
private _datasSortedColumn : sortingColumns|undefined;
public parseMeta: papaParseMeta|undefined = undefined; public parseMeta: papaParseMeta|undefined = undefined;
public parseDatas: papaParseDatas[] = []; public parseDatas: papaParseDatas[] = [];
@ -63,6 +65,26 @@ export class freeDatas2HTML
return this._datasSelectors; return this._datasSelectors;
} }
set datasSortingColumns(sortingColumns: sortingColumns[])
{
this._datasSortingColumns=[];
for(let i = 0; i < sortingColumns.length; i++)
{
if(Number.isInteger(sortingColumns[i].datasFieldNb) === false || sortingColumns[i].datasFieldNb < 0)
console.error(errors.needNaturalNumber);
else
{
sortingColumns[i].order=undefined;
this._datasSortingColumns.push(sortingColumns[i]);
}
}
}
get datasSortingColumns() : sortingColumns[]
{
return this._datasSortingColumns;
}
public async parse(): Promise<any> public async parse(): Promise<any>
{ {
const converter=this; const converter=this;
@ -118,9 +140,7 @@ export class freeDatas2HTML
else else
{ {
let converter=this; let converter=this;
// Affichage initial de toutes les données du fichier
this.datasHTML=this.createDatasHTML(this.parseMeta!.fields, this.parseDatas);
this._datasViewElt.eltDOM.innerHTML=this.datasHTML;
// Si demandé, création des listes permettant de filter les données // Si demandé, création des listes permettant de filter les données
if(this._datasSelectors.length > 0) if(this._datasSelectors.length > 0)
{ {
@ -168,19 +188,67 @@ export class freeDatas2HTML
selectElement.addEventListener('change', function(e) selectElement.addEventListener('change', function(e)
{ {
converter.datasHTML=converter.createDatasHTML(converter.parseMeta!.fields as string[], converter.parseDatas); converter.datasHTML=converter.createDatasHTML(converter.parseMeta!.fields as string[], converter.parseDatas);
converter._datasViewElt.eltDOM!.innerHTML=converter.datasHTML; converter.refreshView();
}); });
} }
} }
} }
} }
// Je teste aussi les colonnes devant servir à classer les données.
for(let i in this._datasSortingColumns)
{
if(this._datasSortingColumns[i].datasFieldNb > (this.parseMeta!.fields.length-1))
throw new Error(errors.sortingColumnsFieldNotFound);
}
// Si tout est ok, affichage initial de toutes les données du fichier
this.datasHTML=this.createDatasHTML(this.parseMeta!.fields, this.parseDatas);
this.refreshView();
return true; return true;
} }
} }
private refreshView() : void
{
if(this._datasViewElt.eltDOM !== undefined)
{
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
if(this._datasSortingColumns.length > 0)
{
let getTableTh=document.querySelectorAll("table th");
if(getTableTh !== null)
{
for(let i in this._datasSortingColumns)
{
let datasFieldNb=this._datasSortingColumns[i].datasFieldNb;
let htmlContent=getTableTh[datasFieldNb].innerHTML;
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)
{
e.preventDefault();
let order=converter.datasSortingColumns[i].order ;
if(order === undefined || order === "desc")
converter.datasSortingColumns[i].order="asc";
else
converter.datasSortingColumns[i].order="desc";
converter._datasSortedColumn = converter.datasSortingColumns[i];
converter.datasHTML=converter.createDatasHTML(converter.parseMeta!.fields as string[], converter.parseDatas);
converter.refreshView();
});
}
}
}
}
}
private createDatasHTML(fields: string[], datas: any[]) : string private createDatasHTML(fields: string[], datas: any[]) : string
{ {
// Je vérifie si des valeurs ont été sélectionnées pour filter les données. // Dois-je filtrer les données ?
let checkSelectorExist: HTMLSelectElement|null, filters: any[] = []; let checkSelectorExist: HTMLSelectElement|null, filters: any[] = [];
for(let i in this._datasSelectors) for(let i in this._datasSelectors)
{ {
@ -189,6 +257,15 @@ export class freeDatas2HTML
if(checkSelectorExist != null && checkSelectorExist.selectedIndex != 0) if(checkSelectorExist != null && checkSelectorExist.selectedIndex != 0)
filters.push({ field: this._datasSelectors[i].name, value: this._datasSelectors[i].values![checkSelectorExist.selectedIndex-1], separator:this._datasSelectors[i].separator }); filters.push({ field: this._datasSelectors[i].name, value: this._datasSelectors[i].values![checkSelectorExist.selectedIndex-1], separator:this._datasSelectors[i].separator });
} }
// Dois-je classer les données par rapport à une colonne ?
if(this._datasSortedColumn !== undefined)
{
const col=fields[this._datasSortedColumn.datasFieldNb];
const colOrder=this._datasSortedColumn.order;
datas.sort( (a, b) => compare( {order: colOrder} )(a[col], b[col]));
}
// Création du tableau de données : // Création du tableau de données :
let datasHTML="<table><thead>"; let datasHTML="<table><thead>";
for (let i in fields) for (let i in fields)

View File

@ -10,3 +10,8 @@ export interface selectors extends domElement
name?: string; name?: string;
values? : string[]; values? : string[];
} }
export interface sortingColumns
{
datasFieldNb: number;
order?: "asc"|"desc"|undefined;
}

View File

@ -9,4 +9,8 @@ module.exports =
datasHTMLFor2Select:'<table><thead><tr><th>Z (numéro atomique)</th><th>Élément</th><th>Symbole</th><th>Famille</th><th>Abondance des éléments dans la croûte terrestre (μg/k)</th></tr></thead><tbody><tr><td>2</td><td>Hélium</td><td>He</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr><tr><td>10</td><td>Néon</td><td>Ne</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr><tr><td>18</td><td>Argon</td><td>Ar</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr></tbody></table>', datasHTMLFor2Select:'<table><thead><tr><th>Z (numéro atomique)</th><th>Élément</th><th>Symbole</th><th>Famille</th><th>Abondance des éléments dans la croûte terrestre (μg/k)</th></tr></thead><tbody><tr><td>2</td><td>Hélium</td><td>He</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr><tr><td>10</td><td>Néon</td><td>Ne</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr><tr><td>18</td><td>Argon</td><td>Ar</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr></tbody></table>',
datasHTMLFor2SelectNone:'<table><thead><tr><th>Z (numéro atomique)</th><th>Élément</th><th>Symbole</th><th>Famille</th><th>Abondance des éléments dans la croûte terrestre (μg/k)</th></tr></thead><tbody></tbody></table>', datasHTMLFor2SelectNone:'<table><thead><tr><th>Z (numéro atomique)</th><th>Élément</th><th>Symbole</th><th>Famille</th><th>Abondance des éléments dans la croûte terrestre (μg/k)</th></tr></thead><tbody></tbody></table>',
datasHTMLForSelectTagsField:'<table><thead><tr><th>Z (numéro atomique)</th><th>Élément</th><th>Symbole</th><th>Famille</th><th>Abondance des éléments dans la croûte terrestre (μg/k)</th><th>Étiquettes</th></tr></thead><tbody><tr><td>118</td><td>Oganesson</td><td>Og</td><td>Indéfinie</td><td>Inexistant</td><td>Exemple10</td></tr></tbody></table>', datasHTMLForSelectTagsField:'<table><thead><tr><th>Z (numéro atomique)</th><th>Élément</th><th>Symbole</th><th>Famille</th><th>Abondance des éléments dans la croûte terrestre (μg/k)</th><th>Étiquettes</th></tr></thead><tbody><tr><td>118</td><td>Oganesson</td><td>Og</td><td>Indéfinie</td><td>Inexistant</td><td>Exemple10</td></tr></tbody></table>',
sortingColumn1HTML: '<a href="#freeDatas2HTMLSorting0" id="freeDatas2HTMLSorting0">Z (numéro atomique)</a>',
sortingColumn2HTML: '<a href="#freeDatas2HTMLSorting2" id="freeDatas2HTMLSorting2">Symbole</a>',
datasHTMLFor2Select1Clic: '<table><thead><tr><th>Z (numéro atomique)</th><th>Élément</th><th><a href="#freeDatas2HTMLSorting2" id="freeDatas2HTMLSorting2">Symbole</a></th><th>Famille</th><th>Abondance des éléments dans la croûte terrestre (μg/k)</th></tr></thead><tbody><tr><td>18</td><td>Argon</td><td>Ar</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr><tr><td>2</td><td>Hélium</td><td>He</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr><tr><td>10</td><td>Néon</td><td>Ne</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr></tbody></table>',
datasHTMLFor2Select2Clic: '<table><thead><tr><th>Z (numéro atomique)</th><th>Élément</th><th><a href="#freeDatas2HTMLSorting2" id="freeDatas2HTMLSorting2">Symbole</a></th><th>Famille</th><th>Abondance des éléments dans la croûte terrestre (μg/k)</th></tr></thead><tbody><tr><td>10</td><td>Néon</td><td>Ne</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr><tr><td>2</td><td>Hélium</td><td>He</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr><tr><td>18</td><td>Argon</td><td>Ar</td><td>Gaz noble</td><td>&gt; 1 et &lt; 100 000</td></tr></tbody></table>',
} }

View File

@ -51,6 +51,16 @@ describe("freeDatas2HTML", () =>
expect(converter.datasSelectors[0].id).toEqual("selector1"); expect(converter.datasSelectors[0].id).toEqual("selector1");
}); });
it("Ne doit accepter que les colonnes de classement pour lesquelles les numéros fournis sont des nombres naturels.", () =>
{
converter.datasSortingColumns=[{ datasFieldNb:2.3 },{ datasFieldNb:3 }];
expect(converter.datasSortingColumns.length).toEqual(1);
converter.datasSortingColumns=[{ datasFieldNb:2 },{ datasFieldNb:-1 }];
expect(converter.datasSortingColumns.length).toEqual(1);
converter.datasSortingColumns=[{ datasFieldNb:2 },{ datasFieldNb:3 }];
expect(converter.datasSortingColumns.length).toEqual(2);
});
it("Si un séparateur vide est fourni pour un sélecteur, il doit être ignoré.", () => it("Si un séparateur vide est fourni pour un sélecteur, il doit être ignoré.", () =>
{ {
converter.datasSelectors=[{ datasFieldNb:2, id:"selector2", separator:"" }]; converter.datasSelectors=[{ datasFieldNb:2, id:"selector2", separator:"" }];
@ -244,4 +254,55 @@ describe("freeDatas2HTML", () =>
}); });
}); });
describe("Création et action des colonnes permettant de classer les données affichées.", () =>
{
beforeEach( () =>
{
converter.datasViewElt={ id:"datas" };
converter.datasSourceUrl="http://localhost:9876/datas/datas1.csv";
});
it("Doit générer une erreur si au moins un des numéros de colonne de classement fournis pour ne correspond pas à une des colonne du fichier.", async () =>
{
converter.datasSortingColumns=[{ datasFieldNb:0 },{ datasFieldNb:5 }];
await expectAsync(converter.run()).toBeRejectedWith(new Error(errors.sortingColumnsFieldNotFound));
});
it("Ne doit pas pas générer d'erreur si tous les numéros de colonne de classement fournis correspondent à des colonnes du fichier.", async () =>
{
converter.datasSortingColumns=[{ datasFieldNb:3 },{ datasFieldNb:4 }];
await expectAsync(converter.run()).not.toBeRejected();
});
it("Pour chaque colonne de classement demandée, doit générer un lien hypertexte dans l'entête de la colonne.", async () =>
{
converter.datasSortingColumns=[{ datasFieldNb:0 },{ datasFieldNb:2 }];
await converter.run();
let getTableTh=document.querySelectorAll("table th");
expect(getTableTh[0].innerHTML).toEqual(fixtures.sortingColumn1HTML);
expect(getTableTh[2].innerHTML).toEqual(fixtures.sortingColumn2HTML);
});
it("Le 1er click sur l'entête d'une des colonnes doit classer les données dans le sens ascendant, puis descendant et ainsi de suite, en prenant en compte les éventuels filtres.", async () =>
{
converter.datasSelectors=[{ datasFieldNb:3, id:"selector1"},{ datasFieldNb:4, id:"selector2"}];
converter.datasSortingColumns=[{ datasFieldNb:2 }];
await converter.run();
let selectElement = document.getElementById("freeDatas2HTMLSelector0") as HTMLInputElement;
selectElement.value="2";
selectElement = document.getElementById("freeDatas2HTMLSelector1") as HTMLInputElement;
selectElement.value="1";
selectElement.dispatchEvent(new Event('change'));
let getTableThLink=document.querySelector("table th a") as HTMLElement;
getTableThLink.click();// tri ascendant
let txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTMLFor2Select1Clic);
getTableThLink.click();// tri descendant
txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTMLFor2Select2Clic);
getTableThLink.click();// de nouveau ascendant
txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTMLFor2Select1Clic);
});
});
}); });