Nouvelle fonctionnalité permettant d'adapter le rendu HTML.
This commit is contained in:
parent
1b84eb8192
commit
f55f897bea
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "freedatas2html",
|
"name": "freedatas2html",
|
||||||
"version": "0.4.6",
|
"version": "0.5.0",
|
||||||
"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": {
|
||||||
|
@ -25,10 +25,11 @@
|
|||||||
</article>
|
</article>
|
||||||
<p id="pages"></p>
|
<p id="pages"></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>
|
<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>Le dernier filtre (Mots-clés) permet de montrer la possibilité d'<b>extraire des données d'un champ ayant plusieurs valeurs par ligne</b>, ici séparées par une virgule, 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 <b>classer les données</b> : un 1ᵉʳ clic lance un classement par ordre croissant, le 2ᵉ pour ordre décroissant et ainsi de suite.</p>
|
<p>Certains champs (=colonnes) peuvent être désignées comme devant permettre de <b>classer les données</b> : un 1ᵉʳ clic lance un classement par ordre croissant, le 2ᵉ pour ordre décroissant et ainsi de suite.</p>
|
||||||
<p>Il est également possible d'afficher le nombre total de résultats, avec prise en compte des éventuels filtres.</p>
|
<p>Il est également possible d'afficher le nombre total de résultats, avec prise en compte des éventuels filtres.</p>
|
||||||
<p>Enfin, une dernière option permet de <b>paginer les résultats</b>.</p>
|
<p>Une autre option permet de <b>paginer les résultats</b>.</p>
|
||||||
|
<p>Enfin il est possible d'<b>afficher les données autrement que sous forme de tableau HTML</b>. Si vous affichez cette page sur un écran large de moins de 800 px, les données seront simplement listées.<br>Si vous avez un grand écran, visualiser le résultat en faisant "Alt+"Maj"+"M", puis "F5". Appuyez de nouveau sur "F5", une fois de retour sur grand écran.</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>
|
@ -12,6 +12,7 @@ module.exports =
|
|||||||
parserDatasNotFound : "Aucune donnée n'a été trouvée.",
|
parserDatasNotFound : "Aucune donnée n'a été trouvée.",
|
||||||
parserFail: "La lecture des données du fichier a échoué.",
|
parserFail: "La lecture des données du fichier a échoué.",
|
||||||
parserNeedUrl: "Merci de fournir une url valide pour le fichier à parser.",
|
parserNeedUrl: "Merci de fournir une url valide pour le fichier à parser.",
|
||||||
|
renderNeedDatas: "Il ne peut y avoir de pagination, si les données n'ont pas été récupérées.",
|
||||||
selector2HTMLFail: "Le création d'un filtre dans le DOM nécessite l'initialisation de l'élément HTML et du numéro du champs à filter.",
|
selector2HTMLFail: "Le création d'un filtre dans le DOM nécessite l'initialisation de l'élément HTML et du numéro du champs à filter.",
|
||||||
selectorCheckIsOkFail: "Le test est lancé sur un filtre incorrectement initialisé ou sur un attribut absent de la donnée à tester.",
|
selectorCheckIsOkFail: "Le test est lancé sur un filtre incorrectement initialisé ou sur un attribut absent de la donnée à tester.",
|
||||||
selectorFieldNotFound: "Au moins un des champs devant servir à filtrer les données n'existe pas dans le fichier.",
|
selectorFieldNotFound: "Au moins un des champs devant servir à filtrer les données n'existe pas dans le fichier.",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { FreeDatas2HTML, Pagination, Selector, SortingField } from "./freeDatas2HTML";
|
import { FreeDatas2HTML, Pagination, Render, Selector, SortingField } from "./freeDatas2HTML";
|
||||||
|
|
||||||
const initialise = async () =>
|
const initialise = async () =>
|
||||||
{
|
{
|
||||||
@ -24,6 +24,21 @@ const initialise = async () =>
|
|||||||
converter.datasSourceUrl="http://localhost:8080/datas/elements-chimiques.csv";
|
converter.datasSourceUrl="http://localhost:8080/datas/elements-chimiques.csv";
|
||||||
await converter.parse();
|
await converter.parse();
|
||||||
converter.datasSortingFunctions=[{ datasFieldNb:4, sort:mySort }];
|
converter.datasSortingFunctions=[{ datasFieldNb:4, sort:mySort }];
|
||||||
|
// Adaptation du rendu
|
||||||
|
if(window.innerWidth < 800)
|
||||||
|
{
|
||||||
|
converter.datasRender.settings={
|
||||||
|
allBegining:"<h3>Affichage petits écrans !</h3>",
|
||||||
|
allEnding:"",
|
||||||
|
linesBegining:"<ul>",
|
||||||
|
linesEnding:"</ul>",
|
||||||
|
lineBegining:"<li><ul>",
|
||||||
|
lineEnding:"</ul></li>",
|
||||||
|
dataDisplaying:"<li><b>#FIELDNAME :</b> #VALUE</li>",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
converter.datasRender.settings.allBegining="<table class='table-hover'>";
|
||||||
|
|
||||||
// Configuration de la pagination
|
// Configuration de la pagination
|
||||||
const pagination=new Pagination(converter, { id:"pages" }, "Page à afficher :");
|
const pagination=new Pagination(converter, { id:"pages" }, "Page à afficher :");
|
||||||
@ -48,20 +63,19 @@ const initialise = async () =>
|
|||||||
converter.datasSelectors=[filtre1,filtre2,filtre3];
|
converter.datasSelectors=[filtre1,filtre2,filtre3];
|
||||||
|
|
||||||
// Ajout de champs permettant de classer les données
|
// Ajout de champs permettant de classer les données
|
||||||
let sortingField1=new SortingField(converter, 0);
|
// Uniquement avec un rendu tableau (grand écran), car entêtes de colonne nécessaires
|
||||||
//sortingField1.datasFieldNb=0;
|
if(window.innerWidth >= 800)
|
||||||
sortingField1.field2HTML();
|
{
|
||||||
let sortingField2=new SortingField(converter, 1);
|
let sortingField1=new SortingField(converter, 0);
|
||||||
// sortingField2.datasFieldNb=1;
|
sortingField1.field2HTML();
|
||||||
sortingField2.field2HTML();
|
let sortingField2=new SortingField(converter, 1);
|
||||||
let sortingField3=new SortingField(converter, 2);
|
sortingField2.field2HTML();
|
||||||
//sortingField3.datasFieldNb=2;
|
let sortingField3=new SortingField(converter, 2);
|
||||||
sortingField3.field2HTML();
|
sortingField3.field2HTML();
|
||||||
let sortingField4=new SortingField(converter, 4);
|
let sortingField4=new SortingField(converter, 4);
|
||||||
//sortingField4.datasFieldNb=4;
|
sortingField4.field2HTML();
|
||||||
sortingField4.field2HTML();
|
converter.datasSortingFields=[sortingField1,sortingField2,sortingField3,sortingField4];
|
||||||
// Injection dans le convertisseur
|
}
|
||||||
converter.datasSortingFields=[sortingField1,sortingField2,sortingField3,sortingField4];
|
|
||||||
}
|
}
|
||||||
catch(e)
|
catch(e)
|
||||||
{
|
{
|
||||||
|
@ -2,8 +2,9 @@ const Papa = require("papaparse");
|
|||||||
const errors = require("./errors.js");
|
const errors = require("./errors.js");
|
||||||
const { compare }= require('natural-orderby');
|
const { compare }= require('natural-orderby');
|
||||||
|
|
||||||
import { Counter, DOMElement, Paginations, Selectors, SortingFields, SortingFunctions } from "./freeDatas2HTMLInterfaces";
|
import { Counter, DatasRenders, DOMElement, Paginations, Selectors, SortingFields, SortingFunctions } from "./freeDatas2HTMLInterfaces";
|
||||||
import { Pagination} from "./freeDatas2HTMLPagination";
|
import { Pagination} from "./freeDatas2HTMLPagination";
|
||||||
|
import { Render} from "./freeDatas2HTMLRender";
|
||||||
import { Selector } from "./freeDatas2HTMLSelector";
|
import { Selector } from "./freeDatas2HTMLSelector";
|
||||||
import { SortingField } from "./freeDatas2HTMLSortingField";
|
import { SortingField } from "./freeDatas2HTMLSortingField";
|
||||||
|
|
||||||
@ -11,9 +12,11 @@ import { PapaParseDatas, PapaParseErrors, PapaParseMeta } from "./papaParseInter
|
|||||||
|
|
||||||
export class FreeDatas2HTML
|
export class FreeDatas2HTML
|
||||||
{
|
{
|
||||||
// L'élément HTML où doivent être affichées les données :
|
// L'élément HTML où afficher les données. Laisser à undefined si non affichées :
|
||||||
private _datasViewElt: DOMElement = { id:"", eltDOM:undefined };
|
private _datasViewElt: DOMElement|undefined = undefined;
|
||||||
// Le code HTML résultant (utile ?) :
|
// Le moteur de rendu pour préparer l'affichage des données
|
||||||
|
public datasRender: DatasRenders;
|
||||||
|
// Le code HTML résultant :
|
||||||
public datasHTML: string = "";
|
public datasHTML: string = "";
|
||||||
|
|
||||||
// L'url où accéder aux données :
|
// L'url où accéder aux données :
|
||||||
@ -40,6 +43,12 @@ export class FreeDatas2HTML
|
|||||||
// Affichage du nombre total de lignes de données (optionnel) :
|
// Affichage du nombre total de lignes de données (optionnel) :
|
||||||
private _datasCounter: Counter = {};
|
private _datasCounter: Counter = {};
|
||||||
|
|
||||||
|
// J'initialiser avec des valeurs par défaut pouvant être surchargées par les setters
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
this.datasRender=new Render(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Vérifie s'il y a bien un élément dans le DOM pour l'id fourni
|
// Vérifie s'il y a bien un élément dans le DOM pour l'id fourni
|
||||||
public static checkInDOMById(checkedElt: DOMElement) : DOMElement
|
public static checkInDOMById(checkedElt: DOMElement) : DOMElement
|
||||||
{
|
{
|
||||||
@ -160,8 +169,6 @@ export class FreeDatas2HTML
|
|||||||
// Lance FreeDatas2HTML suivant les données reçues :
|
// Lance FreeDatas2HTML suivant les données reçues :
|
||||||
public async run(): Promise<any>
|
public async run(): Promise<any>
|
||||||
{
|
{
|
||||||
if (this._datasViewElt.eltDOM === undefined)
|
|
||||||
throw new Error(errors.converterNeedDatasElt);
|
|
||||||
if(this._datasSourceUrl === "" )
|
if(this._datasSourceUrl === "" )
|
||||||
throw new Error(errors.parserNeedUrl);
|
throw new Error(errors.parserNeedUrl);
|
||||||
|
|
||||||
@ -181,10 +188,14 @@ export class FreeDatas2HTML
|
|||||||
|
|
||||||
refreshView() : void
|
refreshView() : void
|
||||||
{
|
{
|
||||||
if(this.parseMetas === undefined || this.parseMetas.fields === undefined || this._datasViewElt.eltDOM === undefined)
|
if(this.parseMetas === undefined || this.parseMetas.fields === undefined)
|
||||||
throw new Error(errors.converterRefreshFail);
|
throw new Error(errors.converterRefreshFail);
|
||||||
this.datasHTML=this.createDatasHTML(this.parseMetas.fields, this.parseDatas);
|
|
||||||
this._datasViewElt.eltDOM.innerHTML=this.datasHTML;
|
this.datasHTML=this.createDatas2Display(this.parseMetas.fields, this.parseDatas);
|
||||||
|
|
||||||
|
if(this._datasViewElt !== undefined && this._datasViewElt.eltDOM !== undefined)
|
||||||
|
this._datasViewElt.eltDOM.innerHTML=this.datasHTML;
|
||||||
|
|
||||||
// On réactive les éventuels champs de classement
|
// On réactive les éventuels champs de classement
|
||||||
for(let i in this.datasSortingFields)
|
for(let i in this.datasSortingFields)
|
||||||
{
|
{
|
||||||
@ -193,7 +204,7 @@ export class FreeDatas2HTML
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createDatasHTML(fields: string[], datas: any[]) : string
|
createDatas2Display(fields: string[], datas: any[]) : string
|
||||||
{
|
{
|
||||||
// Dois-je classer les données par rapport à un champ ?
|
// Dois-je classer les données par rapport à un champ ?
|
||||||
if(this.datasSortedField !== undefined && this.datasSortedField.datasFieldNb !==undefined)
|
if(this.datasSortedField !== undefined && this.datasSortedField.datasFieldNb !==undefined)
|
||||||
@ -216,11 +227,8 @@ export class FreeDatas2HTML
|
|||||||
firstData=this.pagination.selectedValue*(this.pagination.pages.selectedValue-1);
|
firstData=this.pagination.selectedValue*(this.pagination.pages.selectedValue-1);
|
||||||
let maxData = (this.pagination !== undefined && this.pagination.selectedValue !== undefined) ? this.pagination.selectedValue : datas.length+1;
|
let maxData = (this.pagination !== undefined && this.pagination.selectedValue !== undefined) ? this.pagination.selectedValue : datas.length+1;
|
||||||
|
|
||||||
// Création du tableau de données :
|
// Création du tableau des données à afficher :
|
||||||
let datasHTML="<table><thead>";
|
const datas2Display=[];
|
||||||
for (let i in fields)
|
|
||||||
datasHTML+="<th>"+fields[i]+"</th>";
|
|
||||||
datasHTML+="</thead><tbody>";
|
|
||||||
let nbVisible=0, nbTotal=0;
|
let nbVisible=0, nbTotal=0;
|
||||||
for (let row in datas)
|
for (let row in datas)
|
||||||
{
|
{
|
||||||
@ -236,21 +244,13 @@ export class FreeDatas2HTML
|
|||||||
}
|
}
|
||||||
if(visible && nbTotal >= firstData && nbVisible < maxData)
|
if(visible && nbTotal >= firstData && nbVisible < maxData)
|
||||||
{
|
{
|
||||||
datasHTML+="<tr>";
|
datas2Display.push(datas[row]);
|
||||||
for(let field in datas[row])
|
|
||||||
{
|
|
||||||
// Attention : si les erreurs papaParse ne sont pas bloquantes, il peut y avoir des données en trop, avec comme nom de colonne : "__parsed_extra"
|
|
||||||
if(fields.indexOf(field) !== -1)
|
|
||||||
datasHTML+="<td>"+datas[row][field]+"</td>";
|
|
||||||
}
|
|
||||||
datasHTML+="</tr>";
|
|
||||||
nbVisible++;
|
nbVisible++;
|
||||||
nbTotal++;
|
nbTotal++;
|
||||||
}
|
}
|
||||||
else if(visible)
|
else if(visible)
|
||||||
nbTotal++;
|
nbTotal++;
|
||||||
}
|
}
|
||||||
datasHTML+="</tbody></table>";
|
|
||||||
if(this._datasCounter !== undefined && this._datasCounter.displayElement !== undefined)
|
if(this._datasCounter !== undefined && this._datasCounter.displayElement !== undefined)
|
||||||
{
|
{
|
||||||
this._datasCounter.value=nbTotal;
|
this._datasCounter.value=nbTotal;
|
||||||
@ -259,11 +259,12 @@ export class FreeDatas2HTML
|
|||||||
// Tout réaffichage peut entraîner une modification du nombre de pages (évolution filtres, etc.)
|
// Tout réaffichage peut entraîner une modification du nombre de pages (évolution filtres, etc.)
|
||||||
if(this.pagination !== undefined)
|
if(this.pagination !== undefined)
|
||||||
this.pagination.creaPageSelector(nbTotal);
|
this.pagination.creaPageSelector(nbTotal);
|
||||||
return datasHTML;
|
return this.datasRender.rend2HTML(datas2Display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Permet l'appel des dépendances via un seul script
|
// Permet l'appel des dépendances via un seul script
|
||||||
export { Pagination } from "./freeDatas2HTMLPagination";
|
export { Pagination } from "./freeDatas2HTMLPagination";
|
||||||
|
export { Render} from "./freeDatas2HTMLRender";
|
||||||
export { Selector } from "./freeDatas2HTMLSelector";
|
export { Selector } from "./freeDatas2HTMLSelector";
|
||||||
export { SortingField } from "./freeDatas2HTMLSortingField";
|
export { SortingField } from "./freeDatas2HTMLSortingField";
|
@ -3,6 +3,24 @@ export interface Counter
|
|||||||
displayElement?: DOMElement; // peut être undefined si on ne souhaite pas d'affichage automatique dans la page
|
displayElement?: DOMElement; // peut être undefined si on ne souhaite pas d'affichage automatique dans la page
|
||||||
value?: number; // undefined jusqu'à recevoir sa première valeur
|
value?: number; // undefined jusqu'à recevoir sa première valeur
|
||||||
}
|
}
|
||||||
|
export interface DatasRenders
|
||||||
|
{
|
||||||
|
rend2HTML(datas: any[]): string;
|
||||||
|
settings: DatasRendersSettings;
|
||||||
|
}
|
||||||
|
export interface DatasRendersSettings
|
||||||
|
{
|
||||||
|
allBegining: string;
|
||||||
|
allEnding: string;
|
||||||
|
fieldsBegining?: string;
|
||||||
|
fieldsEnding?: string;
|
||||||
|
fieldDisplaying?: string;
|
||||||
|
linesBegining: string;
|
||||||
|
linesEnding: string;
|
||||||
|
lineBegining: string;
|
||||||
|
lineEnding: string;
|
||||||
|
dataDisplaying: string;
|
||||||
|
}
|
||||||
export interface DOMElement
|
export interface DOMElement
|
||||||
{
|
{
|
||||||
id: string;
|
id: string;
|
||||||
|
61
src/freeDatas2HTMLRender.ts
Normal file
61
src/freeDatas2HTMLRender.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
const errors = require("./errors.js");
|
||||||
|
import { DatasRenders, DatasRendersSettings } from "./freeDatas2HTMLInterfaces";
|
||||||
|
import { FreeDatas2HTML } from "./freeDatas2HTML";
|
||||||
|
|
||||||
|
export class Render implements DatasRenders
|
||||||
|
{
|
||||||
|
private _converter: FreeDatas2HTML;
|
||||||
|
public settings: DatasRendersSettings;
|
||||||
|
static readonly defaultSettings =
|
||||||
|
{
|
||||||
|
allBegining:"<table>",
|
||||||
|
allEnding:"</table>",
|
||||||
|
fieldsBegining:"<thead><tr>",
|
||||||
|
fieldsEnding:"</tr><thead>",
|
||||||
|
fieldDisplaying:"<th>#FIELDNAME</th>",
|
||||||
|
linesBegining:"<tbody>",
|
||||||
|
linesEnding:"</tbody>",
|
||||||
|
lineBegining:"<tr>",
|
||||||
|
lineEnding:"</tr>",
|
||||||
|
dataDisplaying:"<td>#VALUE</td>",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Injection de la classe principale
|
||||||
|
constructor(converter: FreeDatas2HTML, settings:DatasRendersSettings=Render.defaultSettings)
|
||||||
|
{
|
||||||
|
this._converter=converter;
|
||||||
|
this.settings=settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reçoit les données à afficher et créer le HTML correspondant
|
||||||
|
public rend2HTML(datas: any[]) : string
|
||||||
|
{
|
||||||
|
if(this._converter.parseMetas === undefined || this._converter.parseMetas.fields === undefined)
|
||||||
|
throw new Error(errors.renderNeedDatas);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let datasHTML=this.settings.allBegining;
|
||||||
|
// On ne souhaite pas nécessairement afficher les noms de colonne
|
||||||
|
if(this.settings.fieldsBegining !== undefined && this.settings.fieldDisplaying !== undefined)
|
||||||
|
{
|
||||||
|
datasHTML+=this.settings.fieldsBegining;
|
||||||
|
for (let i in this._converter.parseMetas!.fields)
|
||||||
|
datasHTML+=this.settings.fieldDisplaying.replace("#FIELDNAME", this._converter.parseMetas.fields[Number(i)]);
|
||||||
|
datasHTML+=this.settings.fieldsEnding;
|
||||||
|
}
|
||||||
|
datasHTML+=this.settings.linesBegining;
|
||||||
|
for (let row in datas)
|
||||||
|
{
|
||||||
|
datasHTML+=this.settings.lineBegining;
|
||||||
|
for(let field in datas[row])
|
||||||
|
{
|
||||||
|
if(this._converter.parseMetas.fields.indexOf(field) !== -1)
|
||||||
|
datasHTML+=this.settings.dataDisplaying.replace("#VALUE" , datas[row][field]).replace("#FIELDNAME" , field);
|
||||||
|
}
|
||||||
|
datasHTML+=this.settings.lineEnding;
|
||||||
|
}
|
||||||
|
datasHTML+=this.settings.linesEnding+this.settings.allEnding;
|
||||||
|
return datasHTML;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user