instance-recherche.js (8815B)
1 function MInstanceRecherche() { 2 $.extend(this, { 3 uid: singleton.uid(), 4 // Propriétés 5 mRecherche: null, 6 termes: '', 7 sélection: [], 8 ajouterRésultatSélection: function(s) { 9 this.sélection.push(s); 10 s.ajoutSélection(); 11 }, 12 supprimerRésultatSélection: function(s) { 13 this.sélection.remove(s); 14 s.suppressionSélection(); 15 }, 16 effacerSélection: function(s) { 17 for (var i = 0; i < this.sélection.length; i++) 18 this.sélection[i].suppressionSélection(); 19 this.sélection = []; 20 } 21 }); 22 } 23 24 function VInstanceRecherche(vMondeParente) { 25 $.extend(this,( 26 $('#vue-recherche') 27 .jqote({}) 28 .appendTo(vMondeParente))); 29 30 this.vBarreTitre = this.find('.barre-titre'); 31 this.vTitre = this.find('.titre'); 32 this.vChampTermes = this.find('.termes'); 33 this.vRésultats = this.find('.résultats'); 34 this.premièreFois = true; 35 this.addClass('première-fois'); 36 37 var that = this; 38 (this.vChampTermes) 39 .focus(function() { 40 if (that.premièreFois) { 41 that.premièreFois = false; 42 that.vChampTermes.val(""); 43 // TODO : unbind focus 44 } 45 }); 46 47 this.ajoutVRésultatRecherche = function(vrr, position) { 48 if (position === undefined || position >= this.vRésultats.children().size() - 1) { 49 this.vRésultats.append(vrr); 50 } else { 51 this.vRésultats.children().eq(position).before(vrr); 52 } 53 }; 54 55 this.sélection = function(s) { 56 this.vRésultats.children.removeClass('sélectionné'); 57 s.addClass('sélectionné'); 58 }; 59 60 this.termes = function(val) { 61 if (val !== undefined) { 62 this.vChampTermes.val(val); 63 this.removeClass('première-fois'); 64 this.premièreFois = false; 65 // TODO : unbind focus 66 } else if (this.premièreFois) { 67 return ""; 68 } else { 69 return this.vChampTermes.val(); 70 } 71 }; 72 73 /*this.effacerRésultats = function() { 74 this.vRésultats.empty(); 75 };*/ 76 77 this.draggable(); 78 this.resizable(); 79 this.vRésultats.css('top', this.vBarreTitre.outerHeight()); 80 } 81 82 function CInstanceRecherche(mInstanceRecherche, vMondeParente) { 83 this.modèle = mInstanceRecherche; 84 this.vue = new VInstanceRecherche(vMondeParente); 85 this.ancienTerme = ""; 86 this.anciensRésultats = []; 87 88 var that = this; 89 (this.vue.vChampTermes) 90 .keyup(function() { // keypress ne prend pas en compte le backspace 91 that.actualiserRecherche(); 92 }); 93 94 (this.modèle.mRecherche.monde) 95 .onAjoutBloc(function(bloc) { 96 that.actualiserRecherche([bloc], true, true); 97 }); 98 99 (this.modèle.mRecherche.monde) 100 .onModificationBloc(function(bloc) { 101 that.actualiserRecherche([bloc], true, true); 102 }); 103 104 this.actualiserRecherche = function(domaine, animAjout, animSuppression) { 105 var termes = this.vue.termes().toLowerCase().split(" "); 106 var domaine = domaine || this.modèle.mRecherche.monde.blocs; 107 var résultats = filtrerValeurs(mInstanceRecherche, domaine, termes, function(b) { 108 return { 109 original: b.nom, 110 searchOn: b.nom.toLowerCase() 111 }; 112 }); 113 114 this.anciensRésultats = fusionRésultats(this.anciensRésultats, domaine, résultats, this.vue, this.modèle, animAjout, animSuppression); 115 } 116 117 this.actualiserRecherche(null, true, true); 118 } 119 120 /* Fonctions auxiliaires */ 121 122 function filtrerValeurs(mInstanceRecherche, ensemble, termes, getTexte) { 123 var maxres = 50; 124 var résultats = []; 125 var nbres = 0; 126 var ensemble_length = ensemble.length; 127 termes = termes.filter(function (e) { return e != ""; }); 128 129 for (var i = 0; i < ensemble_length; i++) { 130 var texte = getTexte(ensemble[i]); 131 var mrr = searchAndReturnFormatted(mInstanceRecherche, texte.searchOn, texte.original, termes); 132 133 if (mrr !== false) { 134 mrr.objet = ensemble[i]; 135 mrr.uid = ensemble[i].uid; 136 résultats.push(mrr); 137 nbres++; 138 if (nbres >= maxres) break; 139 } 140 } 141 142 résultats.sort(function(a,b){return a.score - b.score}); 143 for (var i = 0; i<résultats.length; i++) { résultats[i].position = i; } 144 return résultats; 145 } 146 147 /* searchAndReturnFormatted("abcdefghijkabcxyz", ["abc", "ef", "cxy"]); */ 148 function searchAndReturnFormatted(mInstanceRecherche, haystack, original, needles) { 149 var status = new Array(haystack.length); 150 for (var i = 0; i < status.length; i++) { 151 status[i] = 0; 152 } 153 154 for (var n = 0; n < needles.length; n++) { 155 var nl = needles[n].length; 156 var idx = haystack.indexOf(needles[n]); 157 if (idx < 0) { 158 // Aucune occurence de needles[n] 159 return false; 160 } 161 while (idx >= 0) { 162 for (var i = idx; i < idx + nl; i++) { 163 if (status[i] > 0) { 164 for (j = idx; j < idx + nl; j++) { 165 if (j >= i && status[j] >= 1) { 166 status[j] = 3; 167 } else { 168 status[j] = 2; 169 } 170 } 171 i = idx + nl; 172 break; 173 } 174 status[i] = 1; 175 } 176 idx = haystack.indexOf(needles[n], i); 177 } 178 } 179 180 var old = -1; 181 var str = ""; 182 for (var i = 0; i < status.length; i++) { 183 if (old != status[i]) { 184 if (old >= 1) 185 str += '</span>'; 186 if (status[i] == 1) { 187 str += '<span class="occurence">'; 188 } else if (status[i] == 2) { 189 str += '<span class="superposée">'; 190 } else if (status[i] == 3) { 191 str += '<span class="superposition">'; 192 } 193 } 194 str += original[i]; 195 old = status[i]; 196 } 197 198 if (old >= 1) 199 str += '</span>'; 200 var mrr = new MRésultatRecherche(); 201 mrr.mInstanceRecherche = mInstanceRecherche; 202 mrr.html = str; 203 mrr.score = $.sum(status); // We definitely need a better score calculation… 204 return mrr; 205 } 206 207 /* anciens = [] of CRésultatRecherche; 208 * domaine = [] of MBloc; 209 * nouveaux = [] of MRésultatRecherche; 210 * vRechercheParente is a VRechercheParente 211 * mInstanceRecherche is a MInstanceRecherche 212 * animAjout is a boolean 213 * animSuppression is a boolean 214 */ 215 216 function fusionRésultats(anciens, domaine, nouveaux, vRechercheParente, mInstanceRecherche, animAjout, animSuppression) { 217 anciens.sort(function(a,b) { return a.modèle.objet.uid - b.modèle.objet.uid; }); 218 domaine.sort(function(a,b) { return a.uid - b.uid; }); 219 nouveaux.sort(function(a,b) { return a.objet.uid - b.objet.uid; }); 220 221 // Ceci est une sorte de tri fusion à trois tableaux… aaaaaarrrgggh ! 222 223 /* anciens domaine nouveaux || Action 224 * oui non non (obligé) || = Reste 225 * oui oui oui || = Reste 226 * oui oui non || - Supprime 227 * non oui oui || + Ajoute 228 * non oui non || 0 Aucune 229 */ 230 231 var fusion = []; 232 var iD = 0; 233 var iN = 0; 234 var iA = 0; 235 var lA = anciens.length; 236 var lD = domaine.length; 237 var lN = nouveaux.length; 238 while ((iA < lA) || (iD < lD) || (iN < lN)) { 239 var uidA = (iA < lA) ? anciens[iA].modèle.objet.uid : Infinity; 240 var uidD = (iD < lD) ? domaine[iD].uid : Infinity; 241 var uidN = (iN < lN) ? nouveaux[iN].objet.uid : Infinity; 242 243 var a = (iA < lA && uidA <= uidD); 244 var d = (iD < lD && uidA >= uidD); 245 var n = (iN < lN && uidD == uidN) && d; 246 247 //console.log([iA,iD,iN], [uidA,uidD,uidN], [a,d,n]); 248 249 if (a && !(d && !n)) { // Reste 250 if (n) { 251 anciens[iA].setModèle(nouveaux[iN]); 252 } 253 fusion.push(anciens[iA]); 254 } 255 if (a && d && !n) { // Supprime 256 anciens[iA].suppression(animSuppression); 257 } 258 if (!a && d && n) { // Ajoute 259 var cr = new CRésultatRecherche(nouveaux[iN], vRechercheParente); 260 if (animAjout) { 261 cr.vue.animAjout(); 262 } 263 fusion.push(cr); 264 } 265 266 if (a) iA++; 267 if (d) iD++; 268 if (n) iN++; 269 } 270 return fusion; 271 }