From 7d85e375c543d4372c8355c25be883674090bd11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20PENHO=C3=8BT?= Date: Mon, 21 Feb 2022 16:56:19 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20de=20la=20possibilit=C3=A9=20de=20cherc?= =?UTF-8?q?her=20s=C3=A9par=C3=A9ment=20(ou=20pas)=20chacun=20des=20mots?= =?UTF-8?q?=20saisis.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/SearchEngine.ts | 39 +++++++++++++++++++++++++++++---------- src/interfaces.ts | 1 + tests/searchEngineSpec.ts | 18 ++++++++++++++++++ 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 23fcc0e..84f8ea0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "freedatas2html", - "version": "1.4.0", + "version": "1.5.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": { diff --git a/src/SearchEngine.ts b/src/SearchEngine.ts index 4eabf66..c6d80cb 100644 --- a/src/SearchEngine.ts +++ b/src/SearchEngine.ts @@ -17,6 +17,7 @@ export class SearchEngine implements Filters { accentOff: true, caseOff: true, + separatedWords: true, // doit-on chercher l'expression en entier ou chacun des mots ? specialCharsOff: true, specialCharsWhiteList: "", } @@ -128,9 +129,9 @@ export class SearchEngine implements Filters 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 + // Suppression de tous les caractères "spéciaux", c'est-à-dire n'étant ni une lettre, ni un chiffre, ni un espace // ! 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; + const validChars="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "+this.searchMode.specialCharsWhiteList; let validString=""; for(const letter of finalString) { @@ -145,18 +146,36 @@ export class SearchEngine implements Filters public dataIsOk(data: {[index: string]:string}) : boolean { const realSearch=this.searchPreProcessing(this._inputValue.trim()); - // Pas de valeur sélectionnée = pas de filtre sur ce champ + // Pas de valeur saisie = pas de filtre sur ce champ if(realSearch.length === 0) return true; - // Sinon, on cherche la valeur saisie dans tous les champs définis : - for(let field in data) + + // L'expression saisie doit-elle être séparée en plusieurs "mots" ? + let searchedWords: string[]=[]; + if(this.searchMode.separatedWords) + searchedWords=realSearch.split(" "); + else + searchedWords[0]=realSearch; + + // Chacun des "mots" doit être trouvé au moins une fois : + let nbFound=0; + for(const word of searchedWords) { - if(this._fields2Search.indexOf(field) !== -1) - { - if(this.searchPreProcessing(data[field]).indexOf(realSearch) !== -1) - return true; + for(let field in data) + { + if(this._fields2Search.indexOf(field) !== -1) + { + if(this.searchPreProcessing(data[field]).indexOf(word.trim()) !== -1) + { + nbFound++; + break; // ! sinon, on peut trouver +sieurs fois le même "mot" dans les différents champs. + } + } } } - return false; + if(nbFound < searchedWords.length) // tous les mots doivent être trouvés + return false; + else + return true; } } \ No newline at end of file diff --git a/src/interfaces.ts b/src/interfaces.ts index eca7dfd..50a04f7 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -85,6 +85,7 @@ export interface SearchModeSettings { accentOff: boolean; caseOff: boolean; + separatedWords: boolean; specialCharsOff: boolean; specialCharsWhiteList: string; } diff --git a/tests/searchEngineSpec.ts b/tests/searchEngineSpec.ts index 0949f44..c085853 100644 --- a/tests/searchEngineSpec.ts +++ b/tests/searchEngineSpec.ts @@ -304,6 +304,24 @@ describe("Test du moteur de recherche.", () => searchInput.dispatchEvent(new Event("input")); expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse(); }); + + it("Si demandé doit cherché l'expression en entier et non chacun des mots séparément.", async () => + { + // Cas normal, ok si tous les mots sont trouvés séparément : + searchInput.value="gaz noble"; + searchInput.dispatchEvent(new Event("input")); + expect(mySearch.dataIsOk({ "Famille": "le gaz est noble" })).toBeTrue(); + expect(mySearch.dataIsOk({ "Famille": "noble est le gaz" })).toBeTrue(); + expect(mySearch.dataIsOk({ "Famille": "gaz", "Symbole":"noble" })).toBeTrue(); + + // Il faut trouvé au moins une fois l'expression entière dans un des champs : + mySearch.searchMode.separatedWords=false; + searchInput.dispatchEvent(new Event("input")); + expect(mySearch.dataIsOk({ "Famille": "gaz noble" })).toBeTrue(); + expect(mySearch.dataIsOk({ "Famille": "gaz noble", "Symbole":"He" })).toBeTrue(); + expect(mySearch.dataIsOk({ "Famille": "le gaz est noble" })).toBeFalse(); + expect(mySearch.dataIsOk({ "Famille": "gaz", "Symbole":"noble" })).toBeFalse(); + }); }); });