Ajout possibilité ou non de rendre le moteur de recherche sensible à la casse, aux accents ou encore à ignorer ou pas certains caractères spéciaux.
This commit is contained in:
parent
ce1356f10a
commit
a7ca9c2e1a
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "freedatas2html",
|
"name": "freedatas2html",
|
||||||
"version": "1.3.2",
|
"version": "1.4.0",
|
||||||
"description": "Conversion and display of data in different formats (CSV, JSON, HTML) with the possibility of filtering, classifying and paginating the results.",
|
"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",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const errors=require("./errors.js");
|
const errors=require("./errors.js");
|
||||||
import { DOMElement, Filters } from "./interfaces";
|
import { DOMElement, Filters, SearchModeSettings } from "./interfaces";
|
||||||
import { FreeDatas2HTML } from "./FreeDatas2HTML";
|
import { FreeDatas2HTML } from "./FreeDatas2HTML";
|
||||||
|
|
||||||
export class SearchEngine implements Filters
|
export class SearchEngine implements Filters
|
||||||
@ -13,6 +13,13 @@ export class SearchEngine implements Filters
|
|||||||
public placeholder: string="";
|
public placeholder: string="";
|
||||||
public automaticSearch: boolean=false;
|
public automaticSearch: boolean=false;
|
||||||
private _inputValue: string="";
|
private _inputValue: string="";
|
||||||
|
public searchMode:SearchModeSettings= // par défaut, recherche lâche, mais peut devenir stricte en passant tout à false
|
||||||
|
{
|
||||||
|
accentOff: true,
|
||||||
|
caseOff: true,
|
||||||
|
specialCharsOff: true,
|
||||||
|
specialCharsWhiteList: "",
|
||||||
|
}
|
||||||
|
|
||||||
// Injection de la classe principale, mais uniquement si des données ont été importées
|
// Injection de la classe principale, mais uniquement si des données ont été importées
|
||||||
constructor(converter: FreeDatas2HTML, elt: DOMElement, fields?: number[])
|
constructor(converter: FreeDatas2HTML, elt: DOMElement, fields?: number[])
|
||||||
@ -110,10 +117,34 @@ export class SearchEngine implements Filters
|
|||||||
mySearch._converter.refreshView();
|
mySearch._converter.refreshView();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pré-traitement des chaînes de caractères à comparer, suivant le mode de recherche
|
||||||
|
private searchPreProcessing(searchElement: string) : string
|
||||||
|
{
|
||||||
|
let finalString=searchElement;
|
||||||
|
if(this.searchMode.accentOff) // caractères accentués remplacés (exemple : "é" -> "e")
|
||||||
|
finalString=finalString.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); // cf. https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
|
||||||
|
if(this.searchMode.caseOff)
|
||||||
|
finalString=finalString.toLowerCase();
|
||||||
|
if(this.searchMode.specialCharsOff)
|
||||||
|
{
|
||||||
|
// Suppression de tous les caractères "spéciaux", c'est-à-dire n'étant ni une lettre, ni un chiffre
|
||||||
|
// ! Doit être exécuté après "accentOff", sans quoi les caractères accentués seront supprimés avant d'être remplacés
|
||||||
|
const validChars="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"+this.searchMode.specialCharsWhiteList;
|
||||||
|
let validString="";
|
||||||
|
for(const letter of finalString)
|
||||||
|
{
|
||||||
|
if(validChars.indexOf(letter) !== -1)
|
||||||
|
validString+=letter;
|
||||||
|
}
|
||||||
|
finalString=validString;
|
||||||
|
}
|
||||||
|
return finalString;
|
||||||
|
}
|
||||||
|
|
||||||
public dataIsOk(data: {[index: string]:string}) : boolean
|
public dataIsOk(data: {[index: string]:string}) : boolean
|
||||||
{
|
{
|
||||||
const realSearch=this._inputValue.trim().toLowerCase();
|
const realSearch=this.searchPreProcessing(this._inputValue.trim());
|
||||||
// Pas de valeur sélectionnée = pas de filtre sur ce champ
|
// Pas de valeur sélectionnée = pas de filtre sur ce champ
|
||||||
if(realSearch.length === 0)
|
if(realSearch.length === 0)
|
||||||
return true;
|
return true;
|
||||||
@ -122,8 +153,7 @@ export class SearchEngine implements Filters
|
|||||||
{
|
{
|
||||||
if(this._fields2Search.indexOf(field) !== -1)
|
if(this._fields2Search.indexOf(field) !== -1)
|
||||||
{
|
{
|
||||||
// Attention, recherche insensible à la casse, mais aux accents, etc.
|
if(this.searchPreProcessing(data[field]).indexOf(realSearch) !== -1)
|
||||||
if(data[field].toLowerCase().indexOf(realSearch) !== -1)
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,13 @@ export interface RemoteSources extends RemoteSourceSettings
|
|||||||
{
|
{
|
||||||
getFetchSettings() : {};
|
getFetchSettings() : {};
|
||||||
}
|
}
|
||||||
|
export interface SearchModeSettings
|
||||||
|
{
|
||||||
|
accentOff: boolean;
|
||||||
|
caseOff: boolean;
|
||||||
|
specialCharsOff: boolean;
|
||||||
|
specialCharsWhiteList: string;
|
||||||
|
}
|
||||||
export interface Selectors extends Filters
|
export interface Selectors extends Filters
|
||||||
{
|
{
|
||||||
datasFieldNb: number;
|
datasFieldNb: number;
|
||||||
|
@ -239,9 +239,9 @@ describe("Test du moteur de recherche.", () =>
|
|||||||
|
|
||||||
it("Doit retourner false, si une donnée testée ne correspond pas à la valeur cherchée.", async () =>
|
it("Doit retourner false, si une donnée testée ne correspond pas à la valeur cherchée.", async () =>
|
||||||
{
|
{
|
||||||
searchInput.value="Halogène";
|
searchInput.value="Hallogène";
|
||||||
searchInput.dispatchEvent(new Event("input"));
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
expect(mySearch.dataIsOk({ "Famille": "Halogene" })).toBeFalse();// sensible aux accents
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Doit retourner true, si la valeur recherchée est trouvée dans la donnée recherchée, sans prendre en compte la casse, ni les espaces entourant la saisie.", () =>
|
it("Doit retourner true, si la valeur recherchée est trouvée dans la donnée recherchée, sans prendre en compte la casse, ni les espaces entourant la saisie.", () =>
|
||||||
@ -254,15 +254,57 @@ describe("Test du moteur de recherche.", () =>
|
|||||||
searchInput.value="gène";
|
searchInput.value="gène";
|
||||||
searchInput.dispatchEvent(new Event("input"));
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
||||||
// Insensible à casse :
|
|
||||||
searchInput.value="halo";
|
|
||||||
searchInput.dispatchEvent(new Event("input"));
|
|
||||||
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
|
||||||
// Espace entourant la saisie ignorés :
|
// Espace entourant la saisie ignorés :
|
||||||
searchInput.value=" halo ";
|
searchInput.value=" halo ";
|
||||||
searchInput.dispatchEvent(new Event("input"));
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
||||||
|
// Par défaut, la recherche doit être tolérante à la casse, à la présence ou non d'accent et ignorer les caractères n'étant ni des lettres, ni des chiffres
|
||||||
|
searchInput.value="Halogene";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
||||||
|
searchInput.value="halogène";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
||||||
|
searchInput.value="#Halogène";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Si demandé doit traiter les données avant de les comparer de manière à prendre en compte les accents, majuscules ou caractères spéciaux.", () =>
|
||||||
|
{
|
||||||
|
// Sensible à casse :
|
||||||
|
mySearch.searchMode.caseOff=false;
|
||||||
|
searchInput.value="halogène";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
||||||
|
searchInput.value="Halogène";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "halogène" })).toBeFalse();
|
||||||
|
// Sensible aux accents :
|
||||||
|
mySearch.searchMode.accentOff=false;
|
||||||
|
searchInput.value="Halogene";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
||||||
|
searchInput.value="Halogène";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Halogene" })).toBeFalse();
|
||||||
|
// Prise en compte des caractères spéciaux :
|
||||||
|
mySearch.searchMode.specialCharsOff=false;
|
||||||
|
searchInput.value="Halogène^";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
||||||
|
searchInput.value="Halogène";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Ha+logène" })).toBeFalse();
|
||||||
|
// Ignore les caractères spéciaux, sauf ceux en liste blanche :
|
||||||
|
mySearch.searchMode.specialCharsOff=true;
|
||||||
|
mySearch.searchMode.specialCharsWhiteList="^+";
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Ha+logène" })).toBeFalse();
|
||||||
|
searchInput.value="Halogène^";
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user