Subversion Repositories Applications.dictionnaire

Rev

Rev 7 | Rev 11 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 7 Rev 10
Line -... Line 1...
-
 
1
/*
-
 
2
  Surligneur de mot (glossaire)
-
 
3
 
-
 
4
  0) tout d'abord la liste des mots est récupée (getMotsADefinitions) et stockée dans motsAyantDefinition
-
 
5
 
-
 
6
  1) chaque mot de la liste subie une transformation progressive en pattern:
-
 
7
  * les mots de moins de 3 caractères sont inchangés (exemple: "nu")
-
 
8
  * les mots finissant en "eux/euse" sont généricisés
-
 
9
  * les autres mots se voit ajoutée la possibilité de matcher sur \\w{0,2}
-
 
10
 
-
 
11
  2) puis plusieurs RegExp sont baties à partir de la liste de pattern préliminaires
-
 
12
  * regexp_complete permet d'assurer que le mot:
-
 
13
  ** commence en début de ligne
-
 
14
  ** suit un espace
-
 
15
  ** ne suit pas un caractère
-
 
16
  [ mais ne s'assure pas que le mot ne suit PAS un caractère accentué, cf notes à propos de \\b et l'UTF-8 ]
-
 
17
 
-
 
18
  * regexp_thin permet de s'assurer que le mot:
-
 
19
  ** ne se trouve pas déjà encapsulé dans un <span rel="" class="definition_term">X</span>
-
 
20
  ** ne se trouve pas comme attribut "rel" d'un <span rel="X" class="definition_term"></span>
-
 
21
  ** n'est pas directement précédé d'un accent (parmis ceux utilisés dans la BDD, cf exclureSpan)
-
 
22
  ** n'est pas directement précédé d'un caractère alphabétique
-
 
23
  Et tente d'extraire une partie de contexte significative (jusqu'à 24 caractère car initialement le
-
 
24
  test d'inclusion dans .definition_term était faire plus tardivement.
-
 
25
 
-
 
26
  3) remplacerDefinitions() prend la liste des nodes susceptibles de nécessiter un traitement
-
 
27
  et ignore ceux ayant déjà été traités [max_passages] fois (4 par défaut)
-
 
28
 
-
 
29
  4) pour chaque node:
-
 
30
  * le compteur de passage est incrémenté
-
 
31
  * nesseciteSubstitution() est appellé
-
 
32
 
-
 
33
  == nesseciteSubstitution() ==:
-
 
34
  ** Utilise regexp_thin pour extraire les mots restant à définir ainsi qu'une partie de leur contexte.
-
 
35
  ** Utilise regexp_complete pour extraire les mots au plus proche de leur bodures avec un moindre risque d'erreur
-
 
36
  ** exlue les faux positifs possibles de regexp_thin
-
 
37
  ** renvoi les matches de regexp_thin (qui présente plus de contexte)
-
 
38
  =============================
-
 
39
 
-
 
40
  * pour chaque correspondance retournée par nesseciteSubstitution(),
-
 
41
  le mot d'origine (tel que dans motsAyantDefinition)
-
 
42
  est déterminé en utilisant le levenstein (un cache est mis en place, cf texte_to_mot() dans helpers.js).
-
 
43
 
-
 
44
  * rechercherEtRemplacerMotParDefinition() est appelée pour effectuer la substitution dans le node
-
 
45
 
-
 
46
 
-
 
47
  Contraintes rencontrées:
-
 
48
  1) exclure les mots déjà défini via la regexp général plutôt qu'au coup par coup.
-
 
49
  2) vérifier les bordures
-
 
50
  3) vérifier bordure d'accents:
-
 
51
  \\b(é) dans une regexp ne peut matcher une chaîne JS UTF-8
-
 
52
  http://stackoverflow.com/questions/2881445/utf-8-word-boundary-regex-in-javascript
-
 
53
*/
-
 
54
 
1
var dictionnaire = new Array();
55
var dictionnaire = new Array();
2
var motsAyantDefinition = null;
56
var motsAyantDefinition = null;
3
var mouseX = null;
57
var mouseX = null;
4
var mouseY = null;
58
var mouseY = null;
5
var active = false;
59
var active = false;
6
var set = 'p, span, td, pre, div';
60
var set = 'p, span:not(.definition_term), td, pre, div, li';
-
 
61
 
-
 
62
// Note: utiliser \\b plutôt que \\W pour matcher les bordures de mots
-
 
63
// en incluant début et fin de ligne
-
 
64
var regexp_complete = null;
-
 
65
 
-
 
66
var regexp_context = null;
-
 
67
var regexp_thin = null;
-
 
68
 
-
 
69
// nombre maximum de passages de la détection sur un node donné
-
 
70
var max_passages = 4;
-
 
71
 
-
 
72
// echo $(mysql<<<"SELECT cle FROM definitions"|tr "[a-z,-]" o|sed -e 's/o//g' -e "s/\(.\)/\1\n/g"|sort -u)
-
 
73
// ç é è ê î ï ô (2013/07/03)
-
 
74
// TODO: http://xregexp.com/plugins/
-
 
75
var	exclureSpan = '([^' +
-
 
76
	'(?:class="definition_term">)' + // mot contextualisé déjà dictionnarisé
-
 
77
	'(?:rel=")' + // la valeur du rel="" d'un mot déjà dictionnarisé
-
 
78
	'çéèêîïô' + // les accents, non-traités dans la regexp générale et qui ne doivent pas
-
 
79
	// être pris pour des bordures de mots
-
 
80
	'\\w' +
-
 
81
	']|^){1,24}';
Line 7... Line -...
7
 
-
 
8
function getUrlBaseService() {
-
 
9
	// provient de dictionnaire.config.js
-
 
10
	return URL_BASE_SERVICE;
-
 
Line 11... Line 82...
11
}
82
 
12
 
83
 
13
function supprimerAccents(str) { 
84
function supprimerAccents(str) { 
14
    var rExps=[ 
85
    var rExps=[ 
Line 47... Line 118...
47
 
118
 
48
function afficherLienDefinitions() {
119
function afficherLienDefinitions() {
49
	html = '<div id="conteneur_activation_definition"><a href="#">rechercher les définitions</a></div>';
120
	html = '<div id="conteneur_activation_definition"><a href="#">rechercher les définitions</a></div>';
50
	$('#conteneur_activation_definition').live('click', function(event) {
121
	$('#conteneur_activation_definition').live('click', function(event) {
51
		event.preventDefault();
122
		event.preventDefault();
52
		supprimerToutesDefinitions();
123
		//supprimerToutesDefinitions();
53
		if(motsAyantDefinition == null) {
124
		if(motsAyantDefinition == null) {
-
 
125
			getMotsADefinitions();
54
			getMotsADefinitions();
126
			ajouterListenerDefinitions();
55
		} else {
127
		} else {
56
			$(set).remplacerDefinitions(motsAyantDefinition);
128
			$(set).remplacerDefinitions(motsAyantDefinition);
57
		}
129
		}
58
	});
130
	});
Line 66... Line 138...
66
}
138
}
Line 67... Line 139...
67
 
139
 
68
$.fn.remplacerDefinitions = function(mots) {
140
$.fn.remplacerDefinitions = function(mots) {
69
    this.each(function() { 	
141
    this.each(function() {
70
          $(this).contents().filter(function() { 
142
        $(this).contents().filter(function() {
71
        	  return this.nodeType == 3;   
143
        	return (this.nodeType == 3 && ! (($(this).data("count") || 0) > max_passages));
72
          }).each(function() {
144
        }).each(function() {
73
        	  element = $(this);
145
			$(this).data("count", ($(this).data("count") || 0) + 1);
-
 
146
			ttexte = texte = $(this).text();
-
 
147
			matches_list = nesseciteSubstitution(texte)[0];
-
 
148
			if(!matches_list) return true; // TODO: data("count") = max_passages ?
74
        	  texte = element.text();
149
 
-
 
150
			for(i in matches_list) {
-
 
151
				couple = matches_list[i];
75
        	  if(texte != "") {
152
				mot_contextualise = couple[2];
-
 
153
				cle = texte_to_mot(mot_contextualise);
76
	        	  $.each(mots, function(index, valeur) {	
154
 
77
	        		  texte = rechercherEtRemplacerMotParDefinition(texte, valeur);
155
				if(! (ttexte = rechercherEtRemplacerMotParDefinition(texte, cle, couple))) break;
78
	        	  });	
-
 
79
	        	  element.replaceWith(texte);
156
				texte = ttexte;
-
 
157
			}
80
        	  }
158
			$(this).replaceWith(texte);
81
          });
159
		});
82
    });
160
	});
83
    return this;
161
	return this;
Line 84... Line 162...
84
}
162
}
85
 
163
 
86
function rechercherEtRemplacerMotParDefinition(texte, mot) {
-
 
87
	exclureSpan = '[^(?:class="definition_term">)]';
164
function rechercherEtRemplacerMotParDefinition(texte, mot, couple) {
88
    regExp = new RegExp(exclureSpan+"[ |,|-|;|.]+("+mot+")[a-zA-Z]{1}", 'ig');
165
	var full_contexte = couple[0],
-
 
166
	prefix_solo = couple[1],
89
  	termeDansTexte = regExp.exec(texte);  	
167
	mot_contextualise = couple[2];
-
 
168
 
-
 
169
	// cf exclureSpan
90
  	if(termeDansTexte != null && termeDansTexte.length > 1) {
170
	if(new RegExp('((?:class="definition_term">)|(?:rel=")|(?:[çéèêîïô]))(' + mot + "\\w{0,2}" + ')' + "\\b", "ig").test(full_contexte)) return;
91
	  	motOriginal = termeDansTexte[1];
171
 
-
 
172
	templateMotADefinition = formaterTemplateMotADefinition(mot_contextualise, mot);
92
		templateMotADefinition = formaterTemplateMotADefinition(motOriginal);
173
	bloc_replace = full_contexte.replace(mot_contextualise, templateMotADefinition);
Line -... Line 174...
-
 
174
	return texte.replace(full_contexte, bloc_replace);
-
 
175
}
-
 
176
 
-
 
177
 
-
 
178
function nesseciteSubstitution(texte) {
-
 
179
	var liste = [], liste_complete = [];
-
 
180
 
-
 
181
	// regexp d'extraction du contexte, sans limite aux bords de "mot",
-
 
182
	// peu amener des faux positifs, et notamment ne pas matcher au mieux.
93
		texte = texte.replace(motOriginal, templateMotADefinition);
183
	// Eg: subsessiles match "sessile" et non "subsessile".
-
 
184
	while( (matches_c = regexp_thin.exec(texte)) ) {
-
 
185
		//liste.push(getUnique(clean(matches_c)));
-
 
186
		liste.push(matches_c);
-
 
187
	}
-
 
188
 
-
 
189
	if(liste.length == 0) return [null];
-
 
190
 
-
 
191
	// regexp de validation des bordure de mots, ne conserve que des matches correct
94
  	}
192
	// vis-à-vis de la bordure gauche
Line -... Line 193...
-
 
193
	while( (matches_c = regexp_complete.exec(texte)) ) {
-
 
194
		liste_complete.push(matches_c[1]);
-
 
195
	}
-
 
196
 
-
 
197
	// si une match n'est pas dans le tableau des mots autorisés (indexOf)
-
 
198
	for(var i = 0; i < liste.length; i++) {
-
 
199
		if($.inArray(liste[i][2], liste_complete) == -1) liste.splice(i, 1);
-
 
200
	}
-
 
201
 
95
 
202
	return [liste, liste_complete]
96
  	return texte;
203
}
97
}
204
 
98
 
205
 
99
function getMotsADefinitions() {
206
function getMotsADefinitions() {
-
 
207
	$.ajax({
100
	$.ajax({
208
		url: URL_BASE_SERVICE+'mots/', // provient de dictionnaire.config.js
-
 
209
		success: function(data) {
101
		url: getUrlBaseService()+'mots/',
210
			motsAyantDefinition = data;
102
		success: function(data) {
211
			batirRegexp(motsAyantDefinition);
103
			motsAyantDefinition = data;
212
			$(set).remplacerDefinitions(motsAyantDefinition);
104
			$(set).remplacerDefinitions(motsAyantDefinition);
213
 
-
 
214
		},
-
 
215
		dataType: "JSON",
-
 
216
		global: false
-
 
217
	});
-
 
218
}
-
 
219
 
-
 
220
function batirRegexp(mots) {
-
 
221
	var restr = '';
-
 
222
	$.each(mots, function(index, mot) {
-
 
223
		if(restr != '') restr += '|';
-
 
224
 
-
 
225
		if(mot.length < 3) {
-
 
226
			restr += mot;
-
 
227
		}
-
 
228
		// gestion masculin/féminin en "eux/euse"
-
 
229
		else if(mot.substr(-1) == 'x') {
-
 
230
			restr += mot.slice(0, -1) + "(?:x|se|ses)";
-
 
231
		}
-
 
232
		else if(mot.substr(-4) == 'euse') { // TODO: fix DB
-
 
233
			restr += mot.slice(0, -2) + "(?:x|se|ses)";
Line -... Line 234...
-
 
234
		}
105
		},
235
		else
106
		dataType: "JSON",
236
			restr += mot + "\\w{0,2}";
Line 107... Line 237...
107
		global: false
237
	});
108
	});
-
 
109
	
238
 
110
	ajouterListenerDefinitions();
239
	regexp_complete = new RegExp("(?:\\s|^|\\W)(" + restr + ")\\b", "ig"); // accents
111
}
240
	regexp_thin = new RegExp(exclureSpan + "(" + restr + ")\\b", "ig");
112
 
241
}
113
function formaterTemplateMotADefinition(motOriginal) {
242
 
Line 141... Line 270...
141
 
270
 
142
function chargerDefinitionDistante(element) {
271
function chargerDefinitionDistante(element) {
143
	date = new Date();
272
	date = new Date();
144
	mot = element.attr('rel');
273
	mot = element.attr('rel');
145
	$.ajax({
274
	$.ajax({
146
		url: getUrlBaseService()+'def/'+mot,
275
		url: URL_BASE_SERVICE+'def/'+mot, // provient de dictionnaire.config.js
147
		success: function(data) {
276
		success: function(data) {
148
			retour = data;
277
			retour = data;
149
			definition = retour.valeur;
278
			definition = retour.valeur;
150
			dictionnaire[mot] = definition;
279
			dictionnaire[mot] = definition;
Line 185... Line 314...
185
	mouseX = e.pageX;
314
	mouseX = e.pageX;
186
    mouseY = e.pageY - $(window).scrollTop();
315
    mouseY = e.pageY - $(window).scrollTop();
187
});
316
});
Line 188... Line 317...
188
 
317
 
-
 
318
$(document).ready(function() {
189
$(document).ready(function() {
319
	$.getScript(URL_BASE_SERVICE + "../../../scripts/helpers.js");
-
 
320
	getMotsADefinitions();
190
	getMotsADefinitions();
321
	ajouterListenerDefinitions();
191
	afficherLienDefinitions();
322
	afficherLienDefinitions();
192
});
-