204 lines
7.8 KiB
TypeScript
204 lines
7.8 KiB
TypeScript
const Papa = require("papaparse");
|
|
|
|
import { papaParseDatas, papaParseErrors, papaParseMeta } from "./papaParseInterfaces";
|
|
const errors=require("./errors.js");
|
|
|
|
interface domElement
|
|
{
|
|
id: string;
|
|
eltDOM?: HTMLElement;
|
|
}
|
|
interface selectors extends domElement
|
|
{
|
|
colCSV: number;
|
|
name?: string;
|
|
values? : string[];
|
|
}
|
|
|
|
export class freeCSV2HTML
|
|
{
|
|
// Configuration :
|
|
private _datasViewElt: domElement = { id:"", eltDOM:undefined };
|
|
private _datasSourceUrl: string = "";
|
|
private _datasSelectors: selectors[] = [];
|
|
|
|
public parseMeta: papaParseMeta|undefined = undefined;
|
|
public parseDatas: papaParseDatas[] = [];
|
|
public parseErrors: papaParseErrors[] = [];
|
|
private datasHTML: string = "";
|
|
|
|
set datasViewElt(elt: domElement)
|
|
{
|
|
let checkContainerExist=document.getElementById(elt.id);
|
|
if(checkContainerExist === null)
|
|
throw new Error(errors.elementNotFound+elt.id);
|
|
else
|
|
{
|
|
this._datasViewElt.id=elt.id;
|
|
this._datasViewElt.eltDOM=checkContainerExist;
|
|
}
|
|
}
|
|
|
|
// Pas plus de tests + poussés, car nombreux protocoles possibles pour l'url du fichier. À revoir.
|
|
set datasSourceUrl(url: string)
|
|
{
|
|
if(url.trim().length === 0)
|
|
throw new Error(errors.needUrl);
|
|
else
|
|
this._datasSourceUrl=url.trim();
|
|
}
|
|
|
|
set datasSelectors(selectionElts: selectors[])
|
|
{
|
|
let checkContainerExist: HTMLElement|null;
|
|
for(let i = 0; i < selectionElts.length; i++)
|
|
{
|
|
checkContainerExist=document.getElementById(selectionElts[i].id);
|
|
if(checkContainerExist === null)
|
|
throw new Error(errors.elementNotFound+selectionElts[i].id);
|
|
else if(Number.isInteger( selectionElts[i].colCSV) === false || selectionElts[i].colCSV < 0)
|
|
throw new Error(errors.needNaturalNumber); // La validité réelle du numéro de colonne ne peut être vérifée qu'après le parsage.
|
|
else
|
|
selectionElts[i].eltDOM=checkContainerExist;
|
|
}
|
|
this._datasSelectors= selectionElts;
|
|
}
|
|
|
|
public async parse(): Promise<any>
|
|
{
|
|
const converter=this;
|
|
return new Promise((resolve,reject) =>
|
|
{
|
|
if(converter._datasSourceUrl !== "" )
|
|
{
|
|
Papa.parse(converter._datasSourceUrl,
|
|
{
|
|
quoteChar: '"',
|
|
header: true,
|
|
complete: function(results :any)
|
|
{
|
|
converter.parseMeta=results.meta;
|
|
converter.parseErrors=results.errors; // prévoir option bloquant la suite à la moindre erreur trouvée ?
|
|
converter.parseDatas=results.data;
|
|
resolve(true);
|
|
},
|
|
error:function(error :any)
|
|
{
|
|
reject(new Error(errors.parserFail));
|
|
},
|
|
download: true,
|
|
skipEmptyLines: true,
|
|
});
|
|
}
|
|
else
|
|
reject(new Error(errors.needUrl));
|
|
});
|
|
}
|
|
|
|
public async run(): Promise<any>
|
|
{
|
|
if (this._datasViewElt.eltDOM === undefined)
|
|
throw new Error(errors.needDatasElt);
|
|
else if(this._datasSourceUrl === "" )
|
|
throw new Error(errors.needUrl);
|
|
|
|
await this.parse();
|
|
|
|
if(this.parseDatas.length === 0 || this.parseMeta === undefined || this.parseMeta.fields === undefined)
|
|
{
|
|
this._datasViewElt.eltDOM.innerHTML=errors.datasNotFound;
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// Affichage initial des données du fichier
|
|
this.datasHTML="<table><thead>";
|
|
for (let i in this.parseMeta.fields)
|
|
this.datasHTML+="<th>"+this.parseMeta.fields[i]+"</th>";
|
|
this.datasHTML+="</thead><tbody>";
|
|
for (let row in this.parseDatas)
|
|
{
|
|
this.datasHTML+="<tr>";
|
|
for(let field in this.parseDatas[row])
|
|
{
|
|
if( this.parseMeta.fields.indexOf(field) !== -1) // si les erreurs papaParse sont acceptées, il peut y avoir des données en trop : "__parsed_extra"
|
|
this.datasHTML+="<td>"+this.parseDatas[row][field]+"</td>";
|
|
}
|
|
this.datasHTML+="</tr>";
|
|
}
|
|
this.datasHTML+="</tbody></table>";
|
|
this._datasViewElt.eltDOM.innerHTML=this.datasHTML;
|
|
|
|
// Si demandé, création des listes permettant de filter les données
|
|
if(this._datasSelectors.length > 0)
|
|
{
|
|
// Les colonnes devant servir de filtre existent-elles dans le fichier ?
|
|
let selectorsHTML : string [] = [];
|
|
for(let i in this._datasSelectors)
|
|
{
|
|
if(this._datasSelectors[i].colCSV > (this.parseMeta.fields.length-1))
|
|
throw new Error(errors.selectorFieldNotFound);
|
|
else
|
|
{
|
|
let values=[], colName=this.parseMeta.fields[this._datasSelectors[i].colCSV];
|
|
for (let row in this.parseDatas)
|
|
{
|
|
if(values.indexOf(this.parseDatas[row][colName]) === -1)
|
|
values.push(this.parseDatas[row][colName]);
|
|
}
|
|
if(values.length > 0)
|
|
{
|
|
values.sort(); // revoir le problème des chiffres, dates, etc. https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
|
|
this._datasSelectors[i].name = colName;
|
|
this._datasSelectors[i].values=values;
|
|
selectorsHTML[i]="<label for='CSVDatasSelector"+i+"'>"+colName+" : </label><select name='CSVDatasSelector"+i+"' id='CSVDatasSelector"+i+"'><option value='0'>----</option>";
|
|
for(let j in values)
|
|
selectorsHTML[i]+="<option value='"+(Number(j)+1)+"'>"+values[j]+"</option>";
|
|
selectorsHTML[i]+="</select>";
|
|
this._datasSelectors[i].eltDOM!.innerHTML=selectorsHTML[i];// je force avec "!", car l'existence de eltDOM a été testée par le setter.
|
|
}
|
|
|
|
// suite : https://stackoverflow.com/questions/19329978/change-selects-option-and-trigger-events-with-javascript
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|
|
/* Exemple d'appelle complet à papaparse :
|
|
Papa.parse(url, {
|
|
delimiter :"",
|
|
newline: "",
|
|
quoteChar:'"',// à proposer en option
|
|
escapeChar:"",// idem
|
|
header:true,
|
|
transformHeader:"",
|
|
dynamicTyping:false,
|
|
preview:0,
|
|
encoding:"",
|
|
worker:true,
|
|
comments:"",
|
|
step:"",// prévoir en option pour très gros fichiers ?
|
|
complete: function(results :any)
|
|
{
|
|
console.log(results.meta);
|
|
console.log(results.data[35]);
|
|
console.log(results.errors);
|
|
},
|
|
error:function(error :any)
|
|
{
|
|
console.log(error);
|
|
},
|
|
download: true,// nécessaire pour un accès via "http..."
|
|
downloadRequestBody:false,
|
|
skipEmptyLines: true,
|
|
chunk:"",
|
|
fastMode:"",
|
|
beforeFirstChunk:"",
|
|
withCredentials:false,
|
|
transform: "", // à revoir
|
|
delimitersToGuess:""
|
|
});
|
|
* // https://www.papaparse.com/docs#config*/ |