Compare commits
9 Commits
aa65cef241
...
38637443e2
Author | SHA1 | Date | |
---|---|---|---|
38637443e2 | |||
d7ae990e07 | |||
efa0c77213 | |||
ad7575bf8b | |||
dc86d1be44 | |||
48cf6f0dcc | |||
af7c915826 | |||
751fb44142 | |||
477571467a |
@ -14,18 +14,18 @@ module.exports = function(config) {
|
||||
frameworks: ["jasmine", "karma-typescript"],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [ "src/*.ts", "tests/*.ts" , { pattern: 'tests/datas/*', watched: true, included: false, served: true } ],
|
||||
files: [ "src/**/*.ts", "tests/**/*Spec.ts" , { pattern: 'tests/datas/*', watched: true, included: false, served: true } ],
|
||||
|
||||
proxies: { "/datas/": "http://localhost:9876/base/tests/datas/" },
|
||||
|
||||
// list of files / patterns to exclude
|
||||
exclude: [ "src/example*" ],
|
||||
exclude: [ "src/demo/*.ts" ],
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://www.npmjs.com/search?q=keywords:karma-preprocessor
|
||||
preprocessors: {
|
||||
'src/*.ts': [ 'karma-typescript' ],
|
||||
'tests/*.ts': [ 'karma-typescript' ]
|
||||
'src/**/*.ts': [ 'karma-typescript' ],
|
||||
'tests/**/*Spec.ts': [ 'karma-typescript' ]
|
||||
},
|
||||
|
||||
// test results reporter to use
|
||||
|
6917
package-lock.json
generated
6917
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "freedatas2html",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "Conversion and display of data in different formats (CSV, JSON, HTML) with the possibility of filtering, classifying and paginating the results.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@ -12,7 +12,17 @@
|
||||
"type": "git",
|
||||
"url": "https://forge.chapril.org/Fab_Blab/freeDatas2HTML"
|
||||
},
|
||||
"keywords": ["CSV", "datas", "grid", "HTML", "JSON", "list", "parser", "TABLE", "view" ],
|
||||
"keywords": [
|
||||
"CSV",
|
||||
"datas",
|
||||
"grid",
|
||||
"HTML",
|
||||
"JSON",
|
||||
"list",
|
||||
"parser",
|
||||
"TABLE",
|
||||
"view"
|
||||
],
|
||||
"author": {
|
||||
"name": "Fabrice PENHOËT",
|
||||
"email": "fabrice@le-fab-lab.com",
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
238
public/JS/exampleWithUL.app.js
Normal file
238
public/JS/exampleWithUL.app.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -31,6 +31,7 @@
|
||||
<li><a href="/withCSV.html">Parser et afficher un fichier CSV prédéfini</a>, avec ajout de filtres multi-critères, moteur de recherche, pagination, compteur de résultats.. Il s'agit de l'exemple le plus complet.</li>
|
||||
<li><a href="/withJSON.html">Parser et afficher des données JSON</a>, avec ajout d'un filtre, d'un moteur de recherche, pagination et compteur de résultats.</li>
|
||||
<li><a href="/withHTML.html">Parser et réafficher les données situées dans le code HTML</a> de la page, avec filtre, pagination et adaptation à la taille de l'écran.</li>
|
||||
<li><a href="/withUL.html">Utilisation d'une extension créant des liens de classement</a>, dans le cas où les données ne sont pas listées dans un tableau.</li>
|
||||
</ul>
|
||||
<p>Un lien vers le code source TypeScript est fourni pour chaque exemple, de manière à ce que vous puissiez lire le code, tout en observant le résultat.</p>
|
||||
</article>
|
||||
|
53
public/withUL.html
Normal file
53
public/withUL.html
Normal file
@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Exemple d’utilisation de FreeDatas2HTML pour classer des données, non listées sous forme de tableau.">
|
||||
<meta name="robots" content="index, follow">
|
||||
<link rel="stylesheet" href="CSS/paper.min.css">
|
||||
<link rel="stylesheet" href="CSS/fd2html.css">
|
||||
<script src="JS/exampleWithUL.app.js" defer></script>
|
||||
<script src="JS/matomo.js" defer></script>
|
||||
<title>Classer des données non listées sous forme de tableau HTML - FreeDatas2HTML</title>
|
||||
</head>
|
||||
|
||||
<body class="paper container">
|
||||
|
||||
<header id="header" class="text-center">
|
||||
<h1><a href="/">FreeDatas2HTML</a></h1>
|
||||
<nav id="menu-principal">
|
||||
<ul class="inline row flex-center">
|
||||
<li><a href="./#intro" class="badge warning sm-12 col">Introduction</a></li>
|
||||
<li><a href="./examples.html#content" class="badge success sm-12 col">Exemples</a></li>
|
||||
<li><a href="https://forge.chapril.org/Fab_Blab/FreeDatas2HTML" target="_blank" title="accéder au dépôt GIT" rel="noopener" class="badge success sm-12 col">Git</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<h2>Classer des données non listées sous forme de tableau</h2>
|
||||
|
||||
<article id="content">
|
||||
<p>Dans l’exemple ci-dessous FreeDatas2HTML liste les données autrement que sous forme de tableau.<br>Dans ce cas, l’absence d’entêtes de colonne ne permet pas d’utiliser le module rendant cliquables ces entêtes pour lancer le classement les données.</p>
|
||||
<p>Aussi, <a href="https://forge.chapril.org/Fab_Blab/freeDatas2HTML/src/branch/master/src/extensions/exampleWithUL.ts" title="Script de l’extension" target="_blank">une extension</a> est utilisée. Elle gère de manière autonome la création et le fonctionnement des liens de classements. Vous pouvez écrire votre propre extension, par exemple si vous préférez proposer une liste SELECT pour choisir le champ de classement. L’important est que la demande de classement par l’utilisateur appelle la fonction d’actualisation de FreeDatas2HTML, en lui ayant transmis préalablement le champ sur lequel classer les données et l’ordre dans lequel les classer.</p>
|
||||
</article>
|
||||
|
||||
|
||||
<div id="classement">
|
||||
</div>
|
||||
|
||||
<div id="datas">
|
||||
<p>Si tout se passe bien, ce texte sera remplacé par un tableau de données extraites du fichier CSV.</p>
|
||||
</div>
|
||||
|
||||
<aside>
|
||||
<p>Les données listé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" rel="noopener" title="Wikipédia">sur Wikipédia</a>.</p>
|
||||
</aside>
|
||||
|
||||
<aside>
|
||||
<p><a href="https://forge.chapril.org/Fab_Blab/freeDatas2HTML/src/branch/master/src/demo/exampleWithUL.ts" target="_blank" title="accéder au code" rel="noopener" class="paper-btn btn-secondary">Code source utilisé par cette page.</a></p>
|
||||
</aside>
|
||||
|
||||
<footer><p>Design : <a href="https://www.getpapercss.com" target="_blank">PaperCSS</a> | <a href="/mentions-legales.html">Contact et mentions légales</a>.</p></footer>
|
||||
</body>
|
||||
</html>
|
@ -239,10 +239,10 @@ export class FreeDatas2HTML
|
||||
// car l'élément HTML du compteur peut être dans le template du Render.
|
||||
this.datasCounter2HTML();
|
||||
|
||||
// (ré)activation des éventuels champs de classement :
|
||||
for(let field of this.datasSortingFields)
|
||||
// (ré)activation des éventuels liens de classement, si ils sont affichés en même temps que le reste des données :
|
||||
for(let field of this.datasSortingFields)
|
||||
field.field2HTML();
|
||||
|
||||
|
||||
// Tout réaffichage peut entraîner une modification du nombre de pages (évolution filtres, etc.)
|
||||
if(this.pagination !== undefined)
|
||||
this.pagination.pages2HTML();
|
||||
|
@ -1,4 +1,3 @@
|
||||
const { compare }=require('natural-orderby');
|
||||
const errors=require("./errors.js");
|
||||
import { SortingFields } from "./interfaces";
|
||||
import { FreeDatas2HTML } from "./FreeDatas2HTML";
|
||||
@ -41,6 +40,11 @@ export class SortingField implements SortingFields
|
||||
return this._fieldsDOMSelector;
|
||||
}
|
||||
|
||||
set order(setting :"asc"|"desc"|undefined )
|
||||
{
|
||||
this._order=setting;
|
||||
}
|
||||
|
||||
get order() : "asc"|"desc"|undefined
|
||||
{
|
||||
return this._order;
|
||||
|
@ -1,4 +1,3 @@
|
||||
var compare = require('natural-orderby').compare;
|
||||
var errors = require("./errors.js");
|
||||
var SortingField = (function () {
|
||||
function SortingField(converter, datasFieldNb, fieldsDOMSelector) {
|
||||
@ -39,6 +38,9 @@ var SortingField = (function () {
|
||||
get: function () {
|
||||
return this._order;
|
||||
},
|
||||
set: function (setting) {
|
||||
this._order = setting;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
83
src/build/demo/exampleWithUL.js
Normal file
83
src/build/demo/exampleWithUL.js
Normal file
@ -0,0 +1,83 @@
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
import { FreeDatas2HTML, Render, SortingField } from "../FreeDatas2HTML";
|
||||
import { SortingFieldsStandAlone } from "../extensions/SortingFieldsStandAlone";
|
||||
var initialise = function () { return __awaiter(void 0, void 0, void 0, function () {
|
||||
var converter, myRender, sortingField1, sortingField2, sortingField3, allFields, e_1;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
_a.trys.push([0, 2, , 3]);
|
||||
converter = new FreeDatas2HTML("CSV");
|
||||
converter.parser.setRemoteSource({ url: "http://localhost:8080/datas/elements-chimiques.csv" });
|
||||
return [4, converter.run()];
|
||||
case 1:
|
||||
_a.sent();
|
||||
converter.fields2Rend = [0, 1, 2, 3];
|
||||
myRender = new Render();
|
||||
myRender.settings =
|
||||
{
|
||||
allBegining: "<h4>Liste des éléments chimiques :</h4>",
|
||||
allEnding: "",
|
||||
linesBegining: "<ul>",
|
||||
linesEnding: "</ul>",
|
||||
lineBegining: "<li><ul>",
|
||||
lineEnding: "</ul></li>",
|
||||
dataDisplaying: "<li><b>#FIELDNAME :</b> #VALUE</li>",
|
||||
};
|
||||
converter.datasRender = myRender;
|
||||
sortingField1 = new SortingField(converter, 0);
|
||||
sortingField2 = new SortingField(converter, 1);
|
||||
sortingField3 = new SortingField(converter, 2);
|
||||
allFields = new SortingFieldsStandAlone(converter, { id: "classement" });
|
||||
allFields.datasSortingFields = [sortingField1, sortingField2, sortingField3];
|
||||
allFields.rendSettings.allBeginning = "<h4>#LABEL</h4><ul>";
|
||||
allFields.rend2HTML("Champ sur lequel classer les données :");
|
||||
converter.datasViewElt = { id: "datas" };
|
||||
converter.refreshView();
|
||||
return [3, 3];
|
||||
case 2:
|
||||
e_1 = _a.sent();
|
||||
console.error(e_1);
|
||||
document.getElementById("datas").innerHTML = "<div class=\"alert alert-warning\">D\u00E9sol\u00E9, mais un probl\u00E8me technique emp\u00EAche l'affichage des donn\u00E9es.</div>";
|
||||
return [3, 3];
|
||||
case 3: return [2];
|
||||
}
|
||||
});
|
||||
}); };
|
||||
console.log("Hello, ami développeur :-)\nLe code source TypeScript utilisé pour faire fonctionner cette page est lisible ici : :\nhttps://forge.chapril.org/Fab_Blab/freeDatas2HTML/src/branch/master/src/demo/exampleWithJSON.ts\nUn bug ? Une suggestion ? => fabrice@le-fab-lab.com");
|
||||
initialise();
|
67
src/build/extensions/SortingFieldsStandAlone.js
Normal file
67
src/build/extensions/SortingFieldsStandAlone.js
Normal file
@ -0,0 +1,67 @@
|
||||
import { FreeDatas2HTML } from "../FreeDatas2HTML";
|
||||
var errors = require("../errors.js");
|
||||
errors.needSortingFields = "Vous devez fournir au moins un champ de classement valide.";
|
||||
var SortingFieldsStandAlone = (function () {
|
||||
function SortingFieldsStandAlone(converter, elt, settings) {
|
||||
if (settings === void 0) { settings = SortingFieldsStandAlone.defaultSettings; }
|
||||
this._datasViewElt = { id: "", eltDOM: undefined };
|
||||
this.datasSortingFields = [];
|
||||
if (converter.fields.length === 0)
|
||||
throw new Error(errors.sortingFieldNeedDatas);
|
||||
this._datasViewElt = FreeDatas2HTML.checkInDOMById(elt);
|
||||
this._converter = converter;
|
||||
this.rendSettings = settings;
|
||||
}
|
||||
Object.defineProperty(SortingFieldsStandAlone.prototype, "converter", {
|
||||
get: function () {
|
||||
return this._converter;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(SortingFieldsStandAlone.prototype, "datasViewElt", {
|
||||
get: function () {
|
||||
return this._datasViewElt;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
SortingFieldsStandAlone.prototype.rend2HTML = function (label) {
|
||||
if (label === void 0) { label = ""; }
|
||||
if (this.datasSortingFields.length === 0)
|
||||
throw new Error(errors.needSortingFields);
|
||||
var htmlContent = this.rendSettings.allBeginning.replace("#LABEL", label);
|
||||
for (var _i = 0, _a = this.datasSortingFields; _i < _a.length; _i++) {
|
||||
var field = _a[_i];
|
||||
htmlContent += this.rendSettings.fieldBeginning + "<a href='#freeDatas2HTMLSorting" + field.datasFieldNb + "' id='freeDatas2HTMLSorting" + field.datasFieldNb + "'>" + this._converter.fields[field.datasFieldNb] + "</a>" + this.rendSettings.fieldEnding;
|
||||
}
|
||||
htmlContent += this.rendSettings.allEnding;
|
||||
this._datasViewElt.eltDOM.innerHTML = htmlContent;
|
||||
var _loop_1 = function (field) {
|
||||
var sortingLink = document.getElementById("freeDatas2HTMLSorting" + field.datasFieldNb);
|
||||
sortingLink.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
if (field.order === undefined || field.order === "desc")
|
||||
field.order = "asc";
|
||||
else
|
||||
field.order = "desc";
|
||||
field.converter.datasSortedField = field;
|
||||
field.converter.refreshView();
|
||||
});
|
||||
};
|
||||
for (var _b = 0, _c = this.datasSortingFields; _b < _c.length; _b++) {
|
||||
var field = _c[_b];
|
||||
_loop_1(field);
|
||||
}
|
||||
};
|
||||
SortingFieldsStandAlone.defaultSettings = {
|
||||
allBeginning: "<span>#LABEL</span><ul>",
|
||||
allEnding: "</ul>",
|
||||
fieldBeginning: "<li>",
|
||||
fieldEnding: "</li>",
|
||||
};
|
||||
return SortingFieldsStandAlone;
|
||||
}());
|
||||
export { SortingFieldsStandAlone };
|
||||
export { FreeDatas2HTML, SortingField } from "../FreeDatas2HTML";
|
||||
export { errors };
|
51
src/demo/exampleWithUL.ts
Normal file
51
src/demo/exampleWithUL.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { FreeDatas2HTML, Pagination, Render, SearchEngine, Selector, SortingField } from "../FreeDatas2HTML";
|
||||
import { SortingFieldsStandAlone } from "../extensions/SortingFieldsStandAlone";
|
||||
|
||||
const initialise=async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Création d'un convertisseur parsant les données d'un fichier CSV "distant"
|
||||
const converter=new FreeDatas2HTML("CSV");
|
||||
converter.parser.setRemoteSource({ url:"http://localhost:8080/datas/elements-chimiques.csv" });
|
||||
// Parsage des données, qui ne sont pas encore affichées :
|
||||
await converter.run();
|
||||
// On affiche que certains champs :
|
||||
converter.fields2Rend=[0,1,2,3];
|
||||
|
||||
// Les données sont listées en dehors d'un tableau :
|
||||
const myRender=new Render();
|
||||
myRender.settings=
|
||||
{
|
||||
allBegining:"<h4>Liste des éléments chimiques :</h4>",
|
||||
allEnding:"",
|
||||
linesBegining:"<ul>",
|
||||
linesEnding:"</ul>",
|
||||
lineBegining:"<li><ul>",
|
||||
lineEnding:"</ul></li>",
|
||||
dataDisplaying:"<li><b>#FIELDNAME :</b> #VALUE</li>",
|
||||
};
|
||||
converter.datasRender=myRender;
|
||||
|
||||
// Désignation des champs permettant de classer les données en dehors de l'affichage des données
|
||||
let sortingField1=new SortingField(converter, 0);
|
||||
let sortingField2=new SortingField(converter, 1);
|
||||
let sortingField3=new SortingField(converter, 2);
|
||||
const allFields=new SortingFieldsStandAlone(converter,{ id:"classement" });
|
||||
allFields.datasSortingFields=[sortingField1,sortingField2, sortingField3];
|
||||
allFields.rendSettings.allBeginning="<h4>#LABEL</h4><ul>";
|
||||
allFields.rend2HTML("Champ sur lequel classer les données :") ;
|
||||
|
||||
// Affichage initial :
|
||||
converter.datasViewElt={ id:"datas" };
|
||||
converter.refreshView();
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.error(e);
|
||||
document.getElementById("datas")!.innerHTML=`<div class="alert alert-warning">Désolé, mais un problème technique empêche l'affichage des données.</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Hello, ami développeur :-)\nLe code source TypeScript utilisé pour faire fonctionner cette page est lisible ici : :\nhttps://forge.chapril.org/Fab_Blab/freeDatas2HTML/src/branch/master/src/demo/exampleWithJSON.ts\nUn bug ? Une suggestion ? => fabrice@le-fab-lab.com");
|
||||
initialise();
|
87
src/extensions/SortingFieldsStandAlone.ts
Normal file
87
src/extensions/SortingFieldsStandAlone.ts
Normal file
@ -0,0 +1,87 @@
|
||||
// Cette classe est une alternative à l'utilisation directe de SortingField.
|
||||
// Ici, les liens de classement sont créés dans un élément du DOM externe à celui affichant les données
|
||||
|
||||
import { DOMElement } from "../interfaces";
|
||||
import { FreeDatas2HTML, SortingField } from "../FreeDatas2HTML";
|
||||
const errors=require("../errors.js");
|
||||
errors.needSortingFields="Vous devez fournir au moins un champ de classement valide.";
|
||||
|
||||
interface SortingFieldsSettings
|
||||
{
|
||||
allBeginning: string;
|
||||
allEnding: string;
|
||||
fieldBeginning: string;
|
||||
fieldEnding: string;
|
||||
}
|
||||
|
||||
export class SortingFieldsStandAlone
|
||||
{
|
||||
private _converter: FreeDatas2HTML;
|
||||
private _datasViewElt: DOMElement={ id: "", eltDOM: undefined };
|
||||
public datasSortingFields: SortingField[]=[]; // SortingField refusera les champs non valides
|
||||
public rendSettings: SortingFieldsSettings;
|
||||
static readonly defaultSettings=
|
||||
{
|
||||
allBeginning: "<span>#LABEL</span><ul>",
|
||||
allEnding: "</ul>",
|
||||
fieldBeginning: "<li>",
|
||||
fieldEnding: "</li>",
|
||||
};
|
||||
|
||||
constructor(converter: FreeDatas2HTML, elt: DOMElement, settings: SortingFieldsSettings=SortingFieldsStandAlone.defaultSettings)
|
||||
{
|
||||
// Ne peut être appelé avant d'avoir récupéré la liste des champs :
|
||||
if(converter.fields.length === 0)
|
||||
throw new Error(errors.sortingFieldNeedDatas);
|
||||
// Test l'existence dans le DOM de l'élément devant afficher les options de classement :
|
||||
this._datasViewElt=FreeDatas2HTML.checkInDOMById(elt);
|
||||
this._converter=converter;
|
||||
this.rendSettings=settings;
|
||||
}
|
||||
|
||||
get converter() : FreeDatas2HTML
|
||||
{
|
||||
return this._converter;
|
||||
}
|
||||
|
||||
get datasViewElt() : DOMElement
|
||||
{
|
||||
return this._datasViewElt;
|
||||
}
|
||||
|
||||
public rend2HTML(label:string="") : void
|
||||
{
|
||||
// Au moins un champ de classement valide doit avoir été fourni :
|
||||
if(this.datasSortingFields.length === 0)
|
||||
throw new Error(errors.needSortingFields);
|
||||
|
||||
// Arrivé ici, il y a au moins un lien de classement à injecter :
|
||||
let htmlContent=this.rendSettings.allBeginning.replace("#LABEL", label);
|
||||
for(let field of this.datasSortingFields)
|
||||
{
|
||||
htmlContent+=this.rendSettings.fieldBeginning+"<a href='#freeDatas2HTMLSorting"+field.datasFieldNb+"' id='freeDatas2HTMLSorting"+field.datasFieldNb+"'>"+this._converter.fields[field.datasFieldNb]+"</a>"+this.rendSettings.fieldEnding;
|
||||
}
|
||||
htmlContent+=this.rendSettings.allEnding;
|
||||
this._datasViewElt.eltDOM!.innerHTML=htmlContent;// "!" car existence de l'élement dans le DOM a été testé dans le constructeur.
|
||||
|
||||
// Les liens venant d'êtres injectés dans le DOM, il reste à les rendre actifs :
|
||||
for(let field of this.datasSortingFields)
|
||||
{
|
||||
let sortingLink=document.getElementById("freeDatas2HTMLSorting"+field.datasFieldNb);
|
||||
sortingLink!.addEventListener("click", function(e) // "!" car je sais que sortingLink existe, venant de le créer.
|
||||
{
|
||||
e.preventDefault();
|
||||
if(field.order === undefined || field.order === "desc")
|
||||
field.order="asc";
|
||||
else
|
||||
field.order="desc";
|
||||
field.converter.datasSortedField=field;
|
||||
field.converter.refreshView();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Utile au script de tests :
|
||||
export { FreeDatas2HTML, SortingField } from "../FreeDatas2HTML";
|
||||
export { errors };
|
108
tests/extensions/sortingFieldsStandAloneSpec.ts
Normal file
108
tests/extensions/sortingFieldsStandAloneSpec.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import { errors, FreeDatas2HTML, SortingField, SortingFieldsStandAlone } from "../../src/extensions/SortingFieldsStandAlone";
|
||||
const fixtures=require("../fixtures.js");
|
||||
|
||||
describe("Test des liens de classement (hors données).", () =>
|
||||
{
|
||||
let converter: FreeDatas2HTML;
|
||||
let sortingFields: SortingFieldsStandAlone;
|
||||
|
||||
beforeEach( async () =>
|
||||
{
|
||||
document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML);
|
||||
converter=new FreeDatas2HTML("CSV");
|
||||
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
|
||||
converter.datasViewElt={ id:"datas" };
|
||||
await converter.run(); // parsage + 1er affichage des données
|
||||
});
|
||||
|
||||
afterEach( () =>
|
||||
{
|
||||
document.body.removeChild(document.getElementById("fixture"));
|
||||
});
|
||||
|
||||
describe("Test des données reçues pour configurer les liens de classement.", () =>
|
||||
{
|
||||
it("Doit générer une erreur, si initialisé avant que les champs de données ne soient connus.", () =>
|
||||
{
|
||||
converter=new FreeDatas2HTML("CSV");
|
||||
// Pas lancé converter.run(), donc les données n'ont pas été parsées :
|
||||
expect(() => { return new SortingFieldsStandAlone(converter, { id:"selector1" }); }).toThrowError(errors.sortingFieldNeedDatas);
|
||||
});
|
||||
|
||||
it("Doit générer une erreur, si initialisé avec l'id d'un élément n'existant pas dans le DOM", () =>
|
||||
{
|
||||
expect(() => { return new SortingFieldsStandAlone(converter, { id:"dontExist" }); }).toThrowError(errors.converterElementNotFound+"dontExist");
|
||||
});
|
||||
|
||||
it("Si tous les paramètres sont ok, ils doivent être acceptés.", () =>
|
||||
{
|
||||
expect(() => { sortingFields=new SortingFieldsStandAlone(converter, { id:"selector1" }); }).not.toThrowError();
|
||||
expect(sortingFields.converter).toEqual(converter);
|
||||
expect(sortingFields.datasViewElt.id).toEqual("selector1");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Création et action des liens de classement", () =>
|
||||
{
|
||||
let sortingField1: SortingField, sortingField2: SortingField;
|
||||
|
||||
beforeEach(() =>
|
||||
{
|
||||
sortingFields=new SortingFieldsStandAlone(converter, { id:"selector1" });
|
||||
sortingField1=new SortingField(converter, 0);
|
||||
sortingField2=new SortingField(converter, 2);
|
||||
sortingFields.datasSortingFields=[sortingField1,sortingField2];
|
||||
});
|
||||
|
||||
it("Doit générer une erreur, si lancé avant d'avoir fourni au moins un champ de classement.", () =>
|
||||
{
|
||||
sortingFields=new SortingFieldsStandAlone(converter, { id:"selector1" });
|
||||
expect(() => { return sortingFields.rend2HTML() }).toThrowError(errors.needSortingFields);
|
||||
});
|
||||
|
||||
it("Doit générer une liste de liens correspondant aux champs fournis .", () =>
|
||||
{
|
||||
sortingFields.rend2HTML();
|
||||
let expectedHTML="<span></span><ul><li>"+fixtures.sortingColumn1HTML+"</li><li>"+fixtures.sortingColumn2HTML+"</li></ul>";
|
||||
expect(document.getElementById("selector1").innerHTML).toEqual(expectedHTML);
|
||||
// Idem avec des paramètres d'affichage :
|
||||
sortingFields.rendSettings=
|
||||
{
|
||||
allBeginning: "<h4>#LABEL</h4><p>",
|
||||
allEnding: "</p>",
|
||||
fieldBeginning: "",
|
||||
fieldEnding: " | ",
|
||||
};
|
||||
expectedHTML="<h4>Classer les données :</h4><p>"+fixtures.sortingColumn1HTML+" | "+fixtures.sortingColumn2HTML+" | </p>";
|
||||
sortingFields.rend2HTML("Classer les données :");
|
||||
expect(document.getElementById("selector1").innerHTML).toEqual(expectedHTML);
|
||||
});
|
||||
|
||||
it("Lorsqu'ils sont cliqués, les liens de classement doivent transmettre l'information au convertisseur + lui demander d'actualiser l'affichage.", () =>
|
||||
{
|
||||
sortingFields.rend2HTML();
|
||||
let getLinks=document.querySelectorAll("ul li a") as NodeListOf<HTMLElement>;
|
||||
|
||||
spyOn(converter, "refreshView");
|
||||
getLinks[0].click();// tri ascendant 1er champ
|
||||
expect(sortingField1.converter.datasSortedField).toEqual(sortingField1);
|
||||
expect(sortingField1.converter.datasSortedField.order).toEqual("asc");
|
||||
expect(converter.refreshView).toHaveBeenCalledTimes(1);
|
||||
|
||||
getLinks[1].click();// tri ascendant mais sur le second champ
|
||||
expect(sortingField2.converter.datasSortedField).toEqual(sortingField2);
|
||||
expect(sortingField2.converter.datasSortedField.order).toEqual("asc");
|
||||
expect(converter.refreshView).toHaveBeenCalledTimes(2);
|
||||
|
||||
getLinks[0].click();// tri descendant sur le 1er champ
|
||||
expect(sortingField1.converter.datasSortedField).toEqual(sortingField1);
|
||||
expect(sortingField1.converter.datasSortedField.order).toEqual("desc");
|
||||
expect(converter.refreshView).toHaveBeenCalledTimes(3);
|
||||
|
||||
getLinks[0].click();// de nouveau ascendant
|
||||
expect(sortingField1.converter.datasSortedField).toEqual(sortingField1);
|
||||
expect(sortingField1.converter.datasSortedField.order).toEqual("asc");
|
||||
expect(converter.refreshView).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
});
|
||||
});
|
@ -8,6 +8,7 @@ module.exports =
|
||||
exampleWithCSV: "./src/demo/exampleWithCSV.ts",
|
||||
exampleWithHTML: "./src/demo/exampleWithHTML.ts",
|
||||
exampleWithJSON: "./src/demo/exampleWithJSON.ts",
|
||||
exampleWithUL: "./src/demo/exampleWithUL.ts",
|
||||
exampleWithUserFile: "./src/demo/exampleWithUserFile.ts"
|
||||
},
|
||||
output:
|
||||
|
Loading…
Reference in New Issue
Block a user