Librairie Handsontable : site commercial
Retour d’expérience sur l’utilisation et la manipulation de la librairie Handsontable dans deux projets :
- PASSY pour l’exploration et l’analyse des segments
- SIGraphLab pour l’exploitation et la sélection des colonnes représentant les variables à traiter.
Cette page va décrire l’utilisation et la configuration des objets pour permettre de répondre aux besoins fonctionnels des applications.
PASSY – DPFV :
Objectif de la mise en place de cette librairie : permettre de visualiser sous forme de feuille Excel un ensemble d’informations liées aux segments sélectionnées par l’utilisateur. Dans cette visualisation plusieurs fonctionnalités recherchées sont : possibilité de trier les colonnes dans l’ordre croissante ou décroissant, possibilité de rechercher et de mettre des filtres sur une colonne quelconque, possibilité de déclencher des actions à partir d’une cellule contenant des attributs HTML (comme bouton ou autre éléments).
Illustration :

Insertion des librairies Javascript spécifiques : indication dans les attributs de création de l’objet
<script src="/handsontable/handsontable.full.min.js"></script>
<link rel="stylesheet" href="/handsontable/handsontable.min.css">
<link rel="stylesheet" href="/handsontable/ht-theme-main.min.css">
Création des fonctions de constructions de l’objet graphique : Handsontable
const construction_tableau=function(zone_, liste_noms,contenu ) {
const container = document.querySelector('#'+zone_);
container.innerHTML="";
// theme name with obligatory ht-theme-* prefix // 'ht-theme-main' ,
hot = new Handsontable(container, {
themeName: 'ht-theme-main-dark',
height: 400,
data: contenu,
colHeaders:liste_noms,
columns: [
{data: "action", renderer: buttonRenderer, readOnly:true},
{data: "exp1", type: 'text',className:'stylecellule'},
{data: "exp2", type: 'text'},
{data: "mot", type: 'text'},
{data: "exp3", type: 'text'},
{data: "exp4", type: 'text'},
{data: "info", type: 'text'},
{data: "locuteur", type: 'text'},
{data: "sexe", type: 'text'},
{data: "tranche", type: 'text'},
],
rowHeaders: true,
columnSorting: true,
hiddenColumns: {
columns: [6],
indicators: true
},
//outsideClickDeselects: false,
contextMenu: true,
manualColumnResize:true,
dropdownMenu: true,
autoWrapRow: true,
//autoWrapCol: true,
//readOnly : true,
stretchH: 'all',
filters: true,
licenseKey: 'non-commercial-and-evaluation' // for non-commercial use only
});
}
// ----------------------------------------------------------------------------------------------------------
// Gestion et interprétation des données déposées dans la zone de texte sous format csv
// ----------------------------------------------------------------------------------------------------------
function processData(zone_table, tab_elem) {
let lines = [];
tab_elem.forEach( element=>{
lines.push(element);
});
construction_tableau(zone_table, ["Action","exp1","exp2","mot","exp3","exp4","info","locuteur","sexe","tranche"],lines);
}
// ------------------------------------------------
// Renderer personnalisé pour le bouton
// ------------------------------------------------
function buttonRenderer(instance, td, row, col, prop, value, cellProperties) {
td.innerHTML = '';
const button = document.createElement('button');
button.innerHTML="Analyser";
button.style.cssText = `
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 8px 15px;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
font-size: 12px;
transition: all 0.3s;
`;
// partie événementielle
button.onmouseover = function() {
this.style.transform = 'scale(1.1)';
this.style.boxShadow = '0 4px 12px rgba(102, 126, 234, 0.4)';
};
button.onmouseout = function() {
this.style.transform = 'scale(1)';
this.style.boxShadow = 'none';
};
button.onclick = function(e) {
e.stopPropagation();
const cellProperties = instance.getCellMeta(row, col);
const rowData = instance.getSourceDataAtRow(cellProperties.row);
document.getElementById("mydivSonore").style.display="block";
chargement_segment_pour_ecoute([rowData["info"]], liste_entrees_current);
};
td.appendChild(button);
return td;
}
Principe du renderer : redirige vers une fonction type avec les paramètres définis instance, td, row, col, prop, value, cellProperties permettant de passer les différents paramètres associés à la cellule. Le paramètre td va permettre d’avoir le descripteur de la cellule du tableau. Il suffit de recréer un nouvel objet au sens HTML (button, select, input ….) de lui affecter les propriétés visuels spécifiques et une gestion événementielle. Ensuite à l’aide de la méthode appendChild de le greffer dans la cellule correspondante.
Commentaires : sur les différents attributs attention à la manipulation de l’attribut columns qui doit définir tous les attributs des colonnes, de plus la licenseKey est important pour définir le fait que le site n’a pas une vocation commerciale si c’est le cas il faut souscrire à une licence. Dans la constitution du tableau il faut penser à insérer les entêtes également afin que handsontable puisse répartir les données au bon endroit.
Exemple du tableau transmis à la fonction processData

SIGraphLab :
L’objectif dans cette application est de permettre lors du chargement du fichier csv de permettre à l’utilisateur de sélectionner les variables qu’il souhaite charger dans son contexte d’analyse. Les fonctionnalités d’Handsontable permettent à l’utilisateur de visualiser et de sélectionner les colonnes de façon continue ou discontinue pour ensuite les charger dans son contexte.

Partie implémentation de la librarie dans cette application :
var hot=null;
// Fonction de génération du tableau
const construction_tableau=function(zone_, name_tab,liste_noms,contenu ) {
const container = document.querySelector('#'+zone_);
// theme name with obligatory ht-theme-* prefix // 'ht-theme-main' ,
hot = new Handsontable(container, {
themeName: 'ht-theme-main-dark-auto',
height: 400,
width: "95%",
// other options
data: contenu,
colHeaders:liste_noms,
rowHeaders: true,
hiddenColumns: {
indicators: true
},
outsideClickDeselects: false,
contextMenu: true,
dropdownMenu: true,
autoWrapRow: true,
autoWrapCol: true,
filters: true,
licenseKey: 'non-commercial-and-evaluation' // for non-commercial use only
});
}
// ----------------------------------------------------------------------------------------------------------
// Gestion et interprétation des données déposées dans la zone de texte sous format csv avec le séparateur #
// ----------------------------------------------------------------------------------------------------------
function processData(allText) {
let allTextLines = allText.split(/\r\n|\n/);
let headers = allTextLines[0].split(separateur);
let lines = [];
for (var i=1; i<allTextLines.length; i++) {
if (allTextLines[i]!="") {
// il faut nettoyer les lignes surtout avec les nombres réels à mettre 2 digits derriere la virgule
let tab=allTextLines[i].split(separateur);
let new_tab=[];
for (let elem of tab) {
if (elem.indexOf(",")!=-1) {
new_tab.push(parseFloat(elem.replace(",",".")).toFixed(2));
} else {
new_tab.push(elem);
}
}
lines.push(new_tab);
}
}
table=construction_tableau("zone_table","tab_mots",headers , lines);
}
D’autres librairies ont été étudiées au préalable de type Datatable, spreadsheet et création manuelle , mais avec une implémentation plus difficile et des fonctionnalités moins intéressantes que handsontable dans sa version non commerciale. Ce qui nous a conduit à opter pour cette librairie.