/* Surligneur de mot (glossaire) 0) tout d'abord la liste des mots est récupée (getMotsADefinitions) et stockée dans motsAyantDefinition 1) chaque mot de la liste subie une transformation progressive en pattern: * les mots de moins de 3 caractères sont inchangés (exemple: "nu") * les mots finissant en "eux/euse" sont généricisés * les autres mots se voit ajoutée la possibilité de matcher sur \\w{0,2} 2) puis plusieurs RegExp sont baties à partir de la liste de pattern préliminaires * regexp_complete permet d'assurer que le mot: ** commence en début de ligne ** suit un espace ** ne suit pas un caractère [ mais ne s'assure pas que le mot ne suit PAS un caractère accentué, cf notes à propos de \\b et l'UTF-8 ] * regexp_thin permet de s'assurer que le mot: ** ne se trouve pas déjà encapsulé dans un X ** ne se trouve pas comme attribut "rel" d'un ** n'est pas directement précédé d'un accent (parmis ceux utilisés dans la BDD, cf exclureSpan) ** n'est pas directement précédé d'un caractère alphabétique Et tente d'extraire une partie de contexte significative (jusqu'à 24 caractère car initialement le test d'inclusion dans .definition_term était faire plus tardivement. 3) remplacerDefinitions() prend la liste des nodes susceptibles de nécessiter un traitement et ignore ceux ayant déjà été traités [max_passages] fois (4 par défaut) 4) pour chaque node: * le compteur de passage est incrémenté * necessiteSubstitution() est appellé == necessiteSubstitution() ==: ** Utilise regexp_thin pour extraire les mots restant à définir ainsi qu'une partie de leur contexte. ** Utilise regexp_complete pour extraire les mots au plus proche de leur bodures avec un moindre risque d'erreur ** exlue les faux positifs possibles de regexp_thin ** renvoi les matches de regexp_thin (qui présente plus de contexte) ============================= * pour chaque correspondance retournée par necessiteSubstitution(), le mot d'origine (tel que dans motsAyantDefinition) est déterminé en utilisant le levenstein (un cache est mis en place, cf texte_to_mot() dans helpers.js). * rechercherEtRemplacerMotParDefinition() est appelée pour effectuer la substitution dans le node Contraintes rencontrées: 1) exclure les mots déjà défini via la regexp général plutôt qu'au coup par coup. 2) vérifier les bordures 3) vérifier bordure d'accents: \\b(é) dans une regexp ne peut matcher une chaîne JS UTF-8 http://stackoverflow.com/questions/2881445/utf-8-word-boundary-regex-in-javascript */ var dictionnaire = new Array(); var motsAyantDefinition = null; var mouseX = null; var mouseY = null; var active = false; var set = '#zone-droite p, #zone-droite span:not(.definition_term), #zone-droite td, #zone-droite pre, #zone-droite div, #zone-droite li, .layout-content, .layout-content p, .layout-content span:not(.definition_term), .layout-content td, .layout-content pre, .layout-content div, .layout-content li'; var urlPage = window.location.href; // Note: utiliser \\b plutôt que \\W pour matcher les bordures de mots // en incluant début et fin de ligne var regexp_complete = null; var regexp_thin = null; // nombre maximum de passages de la détection sur un node donné var max_passages = 4; // echo $(mysql<<<"SELECT cle FROM definitions"|tr "[a-z,-]" o|sed -e 's/o//g' -e "s/\(.\)/\1\n/g"|sort -u) // ç é è ê î ï ô (2013/07/03) // TODO: http://xregexp.com/plugins/ var exclureSpan = '([^' + '(?:class="definition_term">)' + // mot contextualisé déjà dictionnarisé '(?:rel=")' + // la valeur du rel="" d'un mot déjà dictionnarisé 'çéèêîïô' + // les accents, non-traités dans la regexp générale et qui ne doivent pas // être pris pour des bordures de mots '\\w' + ']|^){1,24}'; // sert à filtrer plus rapidement les nodes inutiles pour l'application // du dictionnaire var exclureBlancs = new RegExp('^\\s*$'); function afficherLienDefinitions() { html = '
'; $('#conteneur_activation_definition').on('click', function(event) { event.preventDefault(); //supprimerToutesDefinitions(); if(motsAyantDefinition == null) { getMotsADefinitions(); ajouterListenerDefinitions(); } else { $(set).remplacerDefinitions(motsAyantDefinition); } }); $('body').append(html); } $.fn.remplacerDefinitions = function(mots) { this.each(function() { $(this).contents().filter(function() { return (this.nodeType == 3 && ! (($(this).data("count") || 0) > max_passages)); }).each(function() { // évite les nodes dont le texte est undefined (dumb example