www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 3525f79c252a0ff264af683f365dec1364b5b7f4
parent 1d2692d3f517dad75b7fe8c8aa3b1906b1c57505
Author: gduperon <gduperon@5d9ba3ac-444b-4713-9fb3-0b58e79229a2>
Date:   Sat, 15 May 2010 15:12:30 +0000

Recherche incrémentale avec surlignage, ajout dynamique, … la grande classe quoi + ajout blocs quand on zone (mais pas encore taille/position dudit bloc)

git-svn-id: https://projetud.info-ufr.univ-montp2.fr/svn/flin607-2009-gduperon@47 5d9ba3ac-444b-4713-9fb3-0b58e79229a2

Diffstat:
Mjside3/extensions-jQuery.js | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mjside3/index.html | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mjside3/jquery/jquery.my.enumerable.js | 7++++---
Mjside3/mvc/barre-outils.js | 23++++++++++++++++++++---
Mjside3/mvc/bloc.js | 18++++++++++++++++--
Mjside3/mvc/definition.js | 33++++++++++++++++++++++++---------
Ajside3/mvc/definitions.js | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mjside3/mvc/instance-bloc.js | 82++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Ajside3/mvc/instance-recherche.js | 271+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mjside3/mvc/monde.js | 73++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Ajside3/mvc/recherche.js | 23+++++++++++++++++++++++
Ajside3/mvc/resultat-recherche.js | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mjside3/style.css | 144++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
13 files changed, 853 insertions(+), 116 deletions(-)

diff --git a/jside3/extensions-jQuery.js b/jside3/extensions-jQuery.js @@ -22,6 +22,10 @@ String.prototype.appendTo = function() { // Extensions de jQuery jQuery.fn.extend({ + /* Mathias Bynens - http://stackoverflow.com/questions/2059743/detect-elements-overflow-using-jquery */ + overflows: function() { + return ($(this).width() !== this.clientWidth || $(this).height() !== this.clientHeight); + }, scrollToLast: function(speed) { return this.scrollTo(this.children().last(), speed); }, @@ -118,7 +122,7 @@ function surchargeAccesseur(nom, type, get, set) { var args = arguments; if (options !== undefined) { var that = this; - var ret = this.map(function (i) { + var ret = $(this).map(function (i) { if (that[i] instanceof type) { return set(that[i], options); } else { @@ -186,6 +190,86 @@ surchargeAccesseur( }(jQuery)); +getRectangle = function(x1,y1,x2,y2) { + if (x2 === undefined) { + var oa = $(x1).offset(); + var ob = $(y1).offset(); + return getRectangle(oa.left, oa.top, ob.left, ob.top); + } + return { + x1: Math.min(x1,x2), + y1: Math.min(y1,y2), + x2: Math.max(x1,x2), + y2: Math.max(y1,y2), + width: Math.abs(x1 - x2), + height: Math.abs(y1 - y2) + }; +}; + +jQuery.fn.corners = function(x1,y1,x2,y2) { + var rect = getRectangle(x1,y1,x2,y2); + this.offset({left: rect.x1, top: rect.y1}); + this.width(rect.width); + this.height(rect.height); +} + +jQuery.fn.zonable = function(start, zone, end) { + var opts = { + start: function() {return true;}, + zone: function() {return true;}, + end: function() {return true;} + }; + if (typeof start == "function") { + if (start) opts.start = start; + if (zone) opts.start = start; + if (end) opts.start = start; + } else { + if (start) $.extend(opts, start); + } + + var z = {}; + z.vZone = $('#vue-zone').jqote({}).appendTo(this); + z.vZone.hide(); + z.zoning = false; + z.start = null; + + z.manageDown = function(e) { + if (e.target != this || opts.start(e) === false) { + return true; + } + z.start = $(e); + z.zoning = true; + z.vZone.show(); + z.manageMove(e); + return false; + }; + z.manageMove = function(e) { + if (z.zoning) { + if (opts.zone(z.start, e) === false) { + return true; + } + z.vZone.corners(z.start, e); + return false; + } + }; + z.manageUp = function(e) { + if (z.zoning) { + z.manageMove(e); + if (opts.end(z.start, e, getRectangle(z.start, e)) === false) { + return true; + } + z.vZone.hide(); + z.zoning = false; + return false; + } + } + + var that = this; + this.mousedown(z.manageDown); + this.mousemove(z.manageMove); + this.mouseup(z.manageUp); +} + /* Fioritures graphique */ jQuery.fn.extend({ diff --git a/jside3/index.html b/jside3/index.html @@ -35,11 +35,20 @@ <!-- MVC --> <script type="text/javascript" src="mvc/monde.js"></script> + <script type="text/javascript" src="mvc/barre-outils.js"></script> + <script type="text/javascript" src="mvc/log.js"></script> <script type="text/javascript" src="mvc/instance-log.js"></script> + + <script type="text/javascript" src="mvc/recherche.js"></script> + <script type="text/javascript" src="mvc/instance-recherche.js"></script> + <script type="text/javascript" src="mvc/resultat-recherche.js"></script> + <script type="text/javascript" src="mvc/bloc.js"></script> <script type="text/javascript" src="mvc/instance-bloc.js"></script> + <script type="text/javascript" src="mvc/definitions.js"></script> + <script type="text/javascript" src="mvc/definition.js"></script> <script type="text/javascript" src="mvc/connexion.js"></script> <script type="text/javascript" src="mvc/port.js"></script> @@ -77,6 +86,7 @@ <input type="button" class="log pause" value="▌▌" style="padding-right: 0.2em;" /> <input type="button" class="log play" value="▶"/> <h2 class="titre">Log</h2> + <div class="clearfloat"></div> </div> <div class="log messages"> <div><!-- Il faut au moins un message (vide). --></div> @@ -84,16 +94,55 @@ </div> ]]> </script> - <script type="text/x-jqote-template" id="vue-bloc"> + <script type="text/x-jqote-template" id="vue-recherche"> <![CDATA[ - <div class="bloc fenetre"> - <h2 class="bloc barre-titre titre">Nom du bloc</h2> - <div class="bloc tabs titres"> - <h3 class="définition titre aucune-définition">Aucune définition</h3> - <input type="button" class="nouvelle-définition" value="+"/> + <div class="recherche fenetre"> + <div class="recherche barre-titre"> + <input type="text" class="recherche termes" value="Recherche…"/> + <h2 class="titre">Recherche</h2> + <div class="clearfloat"></div> + </div> + <div class="recherche résultats"> </div> - <div class="bloc définitions"> - <div class="définition contenu aucune-définition"> + </div> + ]]> + </script> + <script type="text/x-jqote-template" id="vue-résultat-recherche"> + <![CDATA[ + <div class="résultat-recherche vMain"> + <span class="résultat-recherche vUid"> + </span> + <span class="résultat-recherche vTexte"> + </span> + </div> + ]]> + </script> + <script type="text/x-jqote-template" id="vue-instance-bloc"> + <![CDATA[ + <div class="instance-bloc vMain fenetre"> + <div class="instance-bloc vBarre-titre"> + <h2 class="instance-bloc vTitre vVue-titre">Nom du bloc</h2> + <form action="#" class="instance-bloc vÉdition-titre"> + <input type="text" class="instance-bloc vChamp-titre" value=""/> + <input type="submit" class="instance-bloc vBouton-valider-titre" value="ok"/> + </form> + <div class="clearfloat"></div> + </div> + <div class="instance-bloc vDéfinitions"> + </div> + </div> + ]]> + </script> + <script type="text/x-jqote-template" id="vue-définitions"> + <![CDATA[ + <div class="définitions vMain"> + <div class="définitions vTitresTabs"> + <h3 class="définition vTitre vAucune-définition">Aucune définition</h3> + <input type="button" class="définitions vNouvelle-définition" value="+"/> + <div class="clearfloat"></div> + </div> + <div class="définitions vContenusTabs"> + <div class="définition vCorps vAucune-définition"> Aucune définition. <br/> Cliquez sur le + ci-dessus pour en créer une. @@ -104,13 +153,18 @@ </script> <script type="text/x-jqote-template" id="vue-définition-titre"> <![CDATA[ - <h3 class="définition titre">Nom de la définition</h3> + <h3 class="définition vTitre">Nom de la définition</h3> ]]> </script> <script type="text/x-jqote-template" id="vue-définition"> <![CDATA[ - <div class="définition contenu"> - + <div class="définition vCorps"> + </div> + ]]> + </script> + <script type="text/x-jqote-template" id="vue-zone"> + <![CDATA[ + <div class="vZone"> </div> ]]> </script> diff --git a/jside3/jquery/jquery.my.enumerable.js b/jside3/jquery/jquery.my.enumerable.js @@ -38,18 +38,19 @@ }, // $([1,2,3]).select(function() { return this % 2 == 1 }) // => [1, 3] - select: function(enumerable, callback) { + /* Removed by jspam@free.fr : conflicts with $.select() (for input forms) + select: function(enumerable, callback) { var result = []; $.each(enumerable, function(index) { if (callback.call(this, index)) result.push(this); }); return $(result); - }, + }, */ // $([1,2,3]).reject(function() { return this % 2 == 1 }) // => [2] reject: function(enumerable, callback) { - return $.select(enumerable, negate(callback)); + return /*$.select*/$.filter(enumerable, negate(callback)); }, // $([1,2]).any(function() { return this == 1 }) // => true diff --git a/jside3/mvc/barre-outils.js b/jside3/mvc/barre-outils.js @@ -27,11 +27,28 @@ function CBarreOutils(mBarreOutils, vMondeParente) { var that = this; (this.vue.vBoutonNouveauBloc) .click(function() { - that.modèle.monde.log.envoiMessage("Nouveau bloc."); - var mb = new MBloc(); + that.modèle.monde.log.envoiMessage("Cliquez-glissez pour créer un nouveau bloc."); + that.modèle.monde.outilZone = function(cDéfinition, rect) { + console.log('Zone sur', cDéfinition, rect.x1, rect.y1, rect.x2, rect.y2, rect.width, rect.height); + that.modèle.monde.outilZone = that.modèle.monde.actionAucune; + + var mb = new MBloc(); + that.modèle.monde.ajouterBloc(mb); + var mib = mb.demanderInstance(); + cDéfinition.modèle.ajouterInstanceBloc(mib); + } +/* var mb = new MBloc(); that.modèle.monde.ajouterBloc(mb); var mib = mb.demanderInstance(); - that.modèle.monde.scratch.ajouterInstanceBloc(mib); + that.modèle.monde.scratch.ajouterInstanceBloc(mib);*/ + }); + + (this.vue.vBoutonRecherche) + .click(function() { + that.modèle.monde.log.envoiMessage("Nouvelle recherche."); + var mr = that.modèle.monde.recherche; + var mir = mr.demanderInstance(); + that.modèle.monde.ajouterInstanceRecherche(mir); }); (this.vue.vBoutonLog) diff --git a/jside3/mvc/bloc.js b/jside3/mvc/bloc.js @@ -22,8 +22,13 @@ function MBloc() { this.instances.push(mib); return mib; }, - // Modification + changeNom: function(nouveauNom) { + this.nom = nouveauNom; + faireCallbacks(this.cbChangeNom, this); + faireCallbacks(this.cbModification, this); + }, + /*déplacerDéfinition: function(def, position) { var pos = définitions.remove(def); if (pos < position) position--; @@ -45,10 +50,19 @@ function MBloc() { d.bloc = this; this.définitions.push(d); faireCallbacks(this.cbAjoutDéfinition, d); + faireCallbacks(this.cbModification, this); }, cbAjoutDéfinition: [], onAjoutDéfinition: function(callback) { this.cbAjoutDéfinition.push(callback); - } + }, + cbChangeNom: [], + onChangeNom: function(callback) { + this.cbChangeNom.push(callback); + }, + cbModification: [], + onModification: function(callback) { + this.cbModification.push(callback); + }, }); } diff --git a/jside3/mvc/definition.js b/jside3/mvc/definition.js @@ -29,19 +29,34 @@ function MDéfinition() { blablabla = 0; function VDéfinition(vInstanceBlocParente) { - var t = $('#vue-définition-titre').jqote({}); - var d = $('#vue-définition').jqote({}).toDom(); - d.append(blablabla++); - vInstanceBlocParente.ajoutVDéfinition(t, d) - $.extend(this,d); + $.extend(this,( + $('#vue-définition') + .jqote({}) + .toDom())); + this.vTitre = $('#vue-définition-titre').jqote({}); + vInstanceBlocParente.ajoutVDéfinition(this.vTitre, this); - this.mousedown(function(e) { - console.log("mousedown"); - return false; - }); + this.append(blablabla++); // Debug } function CDéfinition(mDéfinition, vInstanceBlocParente) { this.modèle = mDéfinition; this.vue = new VDéfinition(vInstanceBlocParente); + + var that = this; + this.vue.zonable({ + start: function() { + console.log('startZone'); + }, + zone: function() { + //console.log('zone'); + }, + end: function(start, end, rect) { + console.log('endZone'); + that.modèle.bloc.monde.outilZone(that, rect); + } + }); + this.modèle.onAjoutInstanceBloc(function(instanceBloc) { + var cib = new CInstanceBloc(instanceBloc, that.vue); + }); } diff --git a/jside3/mvc/definitions.js b/jside3/mvc/definitions.js @@ -0,0 +1,60 @@ +/* Pas de modèle pour définitions: c'est juste une partie de instanceBloc */ + +function VDéfinitions(vInstanceBlocParente) { + $.extend(this,( + $('#vue-définitions') + .jqote({}) + .appendTo(vInstanceBlocParente))); + + this.vTitresTabs = this.find('.définitions.vTitresTabs'); + this.vBoutonNouvelleDéfinition = this.find('.définitions.vNouvelle-définition'); + + this.vContenusTabs = this.find('.définitions.vContenusTabs'); + this.vTitreAucuneDéfinition = this.find('.définition.vTitre.vAucune-définition'); + this.vCorpsAucuneDéfinition = this.find('.définition.vCorps.vAucune-définition'); + + this.aucuneDéfinition = true; + + var that = this; + this.ajoutVDéfinition = function(vTitreDéfinition, vCorpsDéfinition) { + if (this.aucuneDéfinition) { + this.vTitreAucuneDéfinition.hide(); + this.aucuneDéfinition = false; + } + var vtd = $(vTitreDéfinition).insertBefore(this.vTitresTabs.children('.clearfloat')); // hack… + var vcd = vCorpsDéfinition.appendTo(this.vContenusTabs); + + vtd.click(function() { + that.changerTab(vtd, vcd); + }); + this.changerTab(vtd, vcd); + return vcd; + }; + + this.changerTab = function(titreTab, contenuTab) { + this.vTitresTabs.children().removeClass("active"); + this.vContenusTabs.children().hide(); + titreTab.addClass("active"); + contenuTab.show(); + }; + + this.vContenusTabs.css('top', this.vTitresTabs.outerHeight()); +} + +function CDéfinitions(mInstanceBloc, vInstanceBlocParente) { + this.modèle = mInstanceBloc; + this.vue = new VDéfinitions(vInstanceBlocParente); + + var that = this; + (this.vue.vBoutonNouvelleDéfinition) + .click(function() { + that.modèle.bloc.monde.log.envoiMessage("Nouvelle définition."); + var md = new MDéfinition(); + that.modèle.bloc.ajouterDéfinition(md); + }); + + this.modèle.bloc.onAjoutDéfinition(function(définition) { + that.modèle.bloc.monde.log.envoiMessage("Ajout de définition", définition); + new CDéfinition(définition, that.vue); + }); +} diff --git a/jside3/mvc/instance-bloc.js b/jside3/mvc/instance-bloc.js @@ -13,46 +13,48 @@ function MInstanceBloc() { function VInstanceBloc(vDéfinitionParente) { $.extend(this,( - $('#vue-bloc') + $('#vue-instance-bloc') .jqote({}) .appendTo(vDéfinitionParente))); - this.vBarreTitre = this.find('.barre-titre'); - this.vTitre = this.find('.titre'); - this.vBoutonNouvelleDéfinition = this.find('.nouvelle-définition'); - this.vTitresTabs = this.find('.bloc.tabs.titres'); - this.vDéfinitions = this.find('.définitions'); - this.vAucuneDéfinition = this.find('.aucune-définition'); - - this.aucuneDéfinition = true; + this.vBarreTitre = this.find('.instance-bloc.vBarre-titre'); + this.vTitre = this.find('.instance-bloc.vTitre'); + this.vVueTitre = this.find('.instance-bloc.vVue-titre'); + this.vÉditionTitre = this.find('.instance-bloc.vÉdition-titre'); + this.vChampTitre = this.find('.instance-bloc.vChamp-titre'); + this.vBoutonValiderTitre = this.find('.instance-bloc.vBoutonValiderTitre'); + this.vDéfinitions = this.find('.instance-bloc.vDéfinitions'); var that = this; - this.ajoutVDéfinition = function(vTitreDéfinition, vDéfinition) { - if (this.aucuneDéfinition) { - this.vAucuneDéfinition.hide(); - this.aucuneDéfinition = false; + this.titre = function(val) { + if (typeof val != "function") { + this.vTitre.text(val); + this.ajusterBarreTitre(); + return true; } - var vD = vDéfinition.appendTo(this.vDéfinitions); - var vTD = vTitreDéfinition.appendTo(this.vTitresTabs); - - vTD.click(function() { - that.changerTab(vTD, vD); + this.vTitre.hide(); + this.vChampTitre.val(this.vTitre.text()); + this.vÉditionTitre.show(); + this.ajusterBarreTitre(); + this.vChampTitre.select(); + var cbModifTitre = val; + this.vÉditionTitre.submit(function(ev) { + that.vTitre.show(); + that.vÉditionTitre.hide(); + that.ajusterBarreTitre(); + window.setTimeout(function() {cbModifTitre(that.vChampTitre.val());}, 0); + return false; }); - this.changerTab(vTD, vD); - return vD; - }; + } - this.changerTab = function(titreTab, contenuTab) { - this.vDéfinitions.children().hide(); - this.vTitresTabs.children().removeClass("active"); - titreTab.addClass("active"); - contenuTab.show(); - }; + this.ajusterBarreTitre = function() { + this.vDéfinitions.css('top', this.vBarreTitre.outerHeight()); + } this.draggable(); this.resizable(); - this.vTitresTabs.css('top', this.vBarreTitre.outerHeight()); - this.vDéfinitions.css('top', this.vBarreTitre.outerHeight() + this.vTitresTabs.outerHeight()); + this.vÉditionTitre.hide(); + this.ajusterBarreTitre(); } function CInstanceBloc(mInstanceBloc, vDéfinitionParente) { @@ -60,15 +62,19 @@ function CInstanceBloc(mInstanceBloc, vDéfinitionParente) { this.vue = new VInstanceBloc(vDéfinitionParente); var that = this; - (this.vue.vBoutonNouvelleDéfinition) - .click(function() { - that.modèle.bloc.monde.log.envoiMessage("Nouvelle définition."); - var md = new MDéfinition(); - that.modèle.bloc.ajouterDéfinition(md); + (this.vue.vTitre) + .dblclick(function() { + that.vue.titre(function(nouveauNom) { + that.modèle.bloc.changeNom(nouveauNom); + }); }); - this.modèle.bloc.onAjoutDéfinition(function(définition) { - that.modèle.bloc.monde.log.envoiMessage("Ajout de définition", définition); - new CDéfinition(définition, that.vue); - }); + (this.modèle.bloc) + .onChangeNom(function(nouveauNom) { + that.vue.titre(that.modèle.bloc.nom); + }); + + this.vue.titre(this.modèle.bloc.nom); + + new CDéfinitions(this.modèle, this.vue.vDéfinitions); } diff --git a/jside3/mvc/instance-recherche.js b/jside3/mvc/instance-recherche.js @@ -0,0 +1,271 @@ +function MInstanceRecherche() { + $.extend(this, { + uid: singleton.uid(), + // Propriétés + recherche: null, + termes: '', + sélection: [], + ajouterRésultatSélection: function(s) { + this.sélection.push(s); + s.ajoutSélection(); + }, + supprimerRésultatSélection: function(s) { + this.sélection.remove(s); + s.suppressionSélection(); + }, + effacerSélection: function(s) { + for (var i = 0; i < this.sélection.length; i++) + this.sélection[i].suppressionSélection(); + this.sélection = []; + } + }); +} + +function VInstanceRecherche(vMondeParente) { + $.extend(this,( + $('#vue-recherche') + .jqote({}) + .appendTo(vMondeParente))); + + this.vBarreTitre = this.find('.barre-titre'); + this.vTitre = this.find('.titre'); + this.vChampTermes = this.find('.termes'); + this.vRésultats = this.find('.résultats'); + this.premièreFois = true; + this.addClass('première-fois'); + + var that = this; + (this.vChampTermes) + .focus(function() { + if (that.premièreFois) { + that.premièreFois = false; + that.vChampTermes.val(""); + // TODO : unbind focus + } + }); + + this.ajoutVRésultatRecherche = function(vrr, position) { + if (position === undefined || position >= this.vRésultats.children().size() - 1) { + this.vRésultats.append(vrr); + } else { + this.vRésultats.children().eq(position).before(vrr); + } + }; + + this.sélection = function(s) { + this.vRésultats.children.removeClass('sélectionné'); + s.addClass('sélectionné'); + }; + + this.termes = function(val) { + if (val !== undefined) { + this.vChampTermes.val(val); + this.removeClass('première-fois'); + this.premièreFois = false; + // TODO : unbind focus + } else if (this.premièreFois) { + return ""; + } else { + return this.vChampTermes.val(); + } + }; + + /*this.effacerRésultats = function() { + this.vRésultats.empty(); + };*/ + + this.draggable(); + this.resizable(); + this.vRésultats.css('top', this.vBarreTitre.outerHeight()); +} + +function CInstanceRecherche(mInstanceRecherche, vMondeParente) { + this.modèle = mInstanceRecherche; + this.vue = new VInstanceRecherche(vMondeParente); + this.ancienTerme = ""; + this.anciensRésultats = []; + + var that = this; + (this.vue.vChampTermes) + .keyup(function() { // keypress ne prend pas en compte le backspace + that.actualiserRecherche(); + }); + + (this.modèle.recherche.monde) + .onAjoutBloc(function(bloc) { + that.actualiserRecherche([bloc], true, true); + }); + + (this.modèle.recherche.monde) + .onModificationBloc(function(bloc) { + that.actualiserRecherche([bloc], true, true); + }); + + this.actualiserRecherche = function(domaine, animAjout, animSuppression) { + var termes = this.vue.termes().toLowerCase().split(" "); + var domaine = domaine || this.modèle.recherche.monde.blocs; + var résultats = filtrerValeurs(mInstanceRecherche, domaine, termes, function(b) { + return { + original: b.nom, + searchOn: b.nom.toLowerCase() + }; + }); + + this.anciensRésultats = fusionRésultats(this.anciensRésultats, domaine, résultats, this.vue, this.modèle, animAjout, animSuppression); + } + + this.actualiserRecherche(null, true, true); +} + +/* Fonctions auxiliaires */ + +function filtrerValeurs(mInstanceRecherche, ensemble, termes, getTexte) { + var maxres = 50; + var résultats = []; + var nbres = 0; + var ensemble_length = ensemble.length; + termes = termes.filter(function (e) { return e != ""; }); + + for (var i = 0; i < ensemble_length; i++) { + var texte = getTexte(ensemble[i]); + var mrr = searchAndReturnFormatted(mInstanceRecherche, texte.searchOn, texte.original, termes); + + if (mrr !== false) { + mrr.objet = ensemble[i]; + mrr.uid = ensemble[i].uid; + résultats.push(mrr); + nbres++; + if (nbres >= maxres) break; + } + } + + résultats.sort(function(a,b){return a.score - b.score}); + for (var i = 0; i<résultats.length; i++) { résultats[i].position = i; } + return résultats; +} + +/* searchAndReturnFormatted("abcdefghijkabcxyz", ["abc", "ef", "cxy"]); */ +function searchAndReturnFormatted(mInstanceRecherche, haystack, original, needles) { + var status = new Array(haystack.length); + for (var i = 0; i < status.length; i++) { + status[i] = 0; + } + + for (var n = 0; n < needles.length; n++) { + var nl = needles[n].length; + var idx = haystack.indexOf(needles[n]); + if (idx < 0) { + // Aucune occurence de needles[n] + return false; + } + while (idx >= 0) { + for (var i = idx; i < idx + nl; i++) { + if (status[i] > 0) { + for (j = idx; j < idx + nl; j++) { + if (j >= i && status[j] >= 1) { + status[j] = 3; + } else { + status[j] = 2; + } + } + i = idx + nl; + break; + } + status[i] = 1; + } + idx = haystack.indexOf(needles[n], i); + } + } + + var old = -1; + var str = ""; + for (var i = 0; i < status.length; i++) { + if (old != status[i]) { + if (old >= 1) + str += '</span>'; + if (status[i] == 1) { + str += '<span class="occurence">'; + } else if (status[i] == 2) { + str += '<span class="superposée">'; + } else if (status[i] == 3) { + str += '<span class="superposition">'; + } + } + str += original[i]; + old = status[i]; + } + + if (old >= 1) + str += '</span>'; + var mrr = new MRésultatRecherche(); + mrr.mInstanceRecherche = mInstanceRecherche; + mrr.html = str; + mrr.score = $.sum(status); // We definitely need a better score calculation… + return mrr; +} + +/* anciens = [] of CRésultatRecherche; + * domaine = [] of MBloc; + * nouveaux = [] of MRésultatRecherche; + * vRechercheParente is a VRechercheParente + * mInstanceRecherche is a MInstanceRecherche + * animAjout is a boolean + * animSuppression is a boolean + */ + +function fusionRésultats(anciens, domaine, nouveaux, vRechercheParente, mInstanceRecherche, animAjout, animSuppression) { + anciens.sort(function(a,b) { return a.modèle.objet.uid - b.modèle.objet.uid; }); + domaine.sort(function(a,b) { return a.uid - b.uid; }); + nouveaux.sort(function(a,b) { return a.objet.uid - b.objet.uid; }); + + // Ceci est une sorte de tri fusion à trois tableaux… aaaaaarrrgggh ! + + /* anciens domaine nouveaux || Action + * oui non non (obligé) || = Reste + * oui oui oui || = Reste + * oui oui non || - Supprime + * non oui oui || + Ajoute + * non oui non || 0 Aucune + */ + + var fusion = []; + var iD = 0; + var iN = 0; + var iA = 0; + var lA = anciens.length; + var lD = domaine.length; + var lN = nouveaux.length; + while ((iA < lA) || (iD < lD) || (iN < lN)) { + var uidA = (iA < lA) ? anciens[iA].modèle.objet.uid : Infinity; + var uidD = (iD < lD) ? domaine[iD].uid : Infinity; + var uidN = (iN < lN) ? nouveaux[iN].objet.uid : Infinity; + + var a = (iA < lA && uidA <= uidD); + var d = (iD < lD && uidA >= uidD); + var n = (iN < lN && uidD == uidN) && d; + + //console.log([iA,iD,iN], [uidA,uidD,uidN], [a,d,n]); + + if (a && !(d && !n)) { // Reste + if (n) { + anciens[iA].setModèle(nouveaux[iN]); + } + fusion.push(anciens[iA]); + } + if (a && d && !n) { // Supprime + anciens[iA].suppression(animSuppression); + } + if (!a && d && n) { // Ajoute + var cr = new CRésultatRecherche(nouveaux[iN], vRechercheParente); + if (animAjout) { + cr.vue.animAjout(); + } + fusion.push(cr); + } + + if (a) iA++; + if (d) iD++; + if (n) iN++; + } + return fusion; +} diff --git a/jside3/mvc/monde.js b/jside3/mvc/monde.js @@ -6,21 +6,28 @@ function MMonde(nom) { // Parents // Enfants log: null, + recherche: null, barreOutils: null, // J'ai des doutes sur la présence de barreOutils… blocs: [], - scratch: null, + mBlocScratch: null, + mDéfinitionScratch: null, // Ajout ajouterBloc: function(b) { b.monde = this; this.blocs.push(b); + var that = this; + b.onModification(function(b) { + faireCallbacks(that.cbModificationBloc, b); + }); + faireCallbacks(this.cbAjoutBloc, b); }, - définirBarreOutils: function(bo) { - bo.monde = this; - this.barreOutils = bo; + cbAjoutBloc: [], + onAjoutBloc: function(callback) { + this.cbAjoutBloc.push(callback); }, - définirLog: function(l) { - l.monde = this; - this.log = l; + cbModificationBloc: [], + onModificationBloc: function(callback) { + this.cbModificationBloc.push(callback); }, instancesLog: [], ajouterInstanceLog: function(il) { @@ -31,18 +38,40 @@ function MMonde(nom) { onAjoutInstanceLog: function(callback) { this.cbAjoutInstanceLog.push(callback); }, + instancesRecherche: [], + ajouterInstanceRecherche: function(ir) { + this.instancesRecherche.push(ir); + faireCallbacks(this.cbAjoutInstanceRecherche, ir); + }, + cbAjoutInstanceRecherche: [], + onAjoutInstanceRecherche: function(callback) { + this.cbAjoutInstanceRecherche.push(callback); + }, // Suppression supprimerBloc: function(b) { this.blocs.remove(b); } }); - /*this.scratch = new Bloc("Scratch"); - this.ajouterBloc(this.scratch); - var iscratch = new InstanceBloc(this.scratch, {vues: this.vues}); // Attention, devrait utiliser une définition !!! - this.scratch.ajouterInstance(iscratch);*/ - this.scratch = new MDéfinition(); // this.scratch.bloc == null; - this.définirBarreOutils(new MBarreOutils()); - this.définirLog(new MLog()); + + /* Actions */ + this.actionAucune = function() {} + + /* Outils */ + this.outilZone = this.actionAucune; + + /* Scratch */ + this.mBlocScratch = new MBloc(); // this.scratch.bloc == null; + this.ajouterBloc(this.mBlocScratch); + this.mDéfinitionScratch = new MDéfinition(); + this.mBlocScratch.ajouterDéfinition(this.mDéfinitionScratch); + + /* this.scratch = new MDéfinition(); // this.scratch.bloc == null; */ + this.barreOutils = new MBarreOutils(); + this.barreOutils.monde = this; + this.recherche = new MRecherche(); + this.recherche.monde = this; + this.log = new MLog(); + this.log.monde = this; } function VMonde(appendToElement) { @@ -52,23 +81,29 @@ function VMonde(appendToElement) { .appendTo(appendToElement))); this.vBarreOutils = null; - this.vLog = null; this.vScratch = this.find('.scratch'); + + this.ajoutVDéfinition = function(vTitreDéfinition, vCorpsDéfinition) { + this.vScratch.replaceWith(vCorpsDéfinition); + this.vScratch = vCorpsDéfinition; + } } function CMonde(mMonde, appendToElement) { this.modèle = mMonde; this.vue = new VMonde(appendToElement, mMonde); this.vue.vBarreOutils = new CBarreOutils(this.modèle.barreOutils, this.vue); - //this.vue.vLog = new CLog(this.modèle.log, this.vue); var that = this; - this.modèle.scratch.onAjoutInstanceBloc(function(instanceBloc) { - var cib = new CInstanceBloc(instanceBloc, that.vue.vScratch); - }); + + CDéfinition(this.modèle.mDéfinitionScratch, this.vue); this.modèle.onAjoutInstanceLog(function (instanceLog) { var cil = new CInstanceLog(instanceLog, that.vue); }); + + this.modèle.onAjoutInstanceRecherche(function (instanceRecherche) { + var cil = new CInstanceRecherche(instanceRecherche, that.vue); + }); } diff --git a/jside3/mvc/recherche.js b/jside3/mvc/recherche.js @@ -0,0 +1,23 @@ +function MRecherche() { + $.extend(this, { + uid: singleton.uid(), + + // Parents + monde: null, + + // Enfants + + // Instanciation + instances: [], + demanderInstance: function() { + var mir = new MInstanceRecherche(); + mir.recherche = this; + this.instances.push(mir); + return mir; + }, + + // Ajout + + // Évènements + }); +} diff --git a/jside3/mvc/resultat-recherche.js b/jside3/mvc/resultat-recherche.js @@ -0,0 +1,72 @@ +function MRésultatRecherche() { + $.extend(this, { + objet: null, + html: "", + score: 0, + position: null, + mInstanceRecherche: null + }); +} + +function VRésultatRecherche(vInstanceRechercheParente, position) { + var vrr = $('#vue-résultat-recherche').jqote({}).toDom(); + vInstanceRechercheParente.ajoutVRésultatRecherche(vrr, position); + $.extend(this,vrr); + + this.vTexte = this.find('.résultat-recherche.vTexte'); + this.vUid = this.find('.résultat-recherche.vUid'); + + var that = this; + this.animAjout = function() { + that.addClass("ajout") + .delay(2000) + .queue(function(next){ + that.removeClass("ajout", 1000); + next(); + }); + }; + + this.animSuppression = function() { + that.addClass("suppression", 500) + .height(that.height) // hauteur fixée + .animate({height: 0, opacity: 0}, 500, function() { + that.suppression(false); + }); + }; + + this.suppression = function(anim) { + if (anim) { return this.animSuppression(); } + this.remove(); + } +} + +function CRésultatRecherche(mRésultatRecherche, vInstanceRechercheParente) { + this.vue = new VRésultatRecherche(vInstanceRechercheParente, mRésultatRecherche.position); + this.setModèle = function(mRésultatRecherche) { + this.modèle = mRésultatRecherche; + this.vue.vTexte.html(this.modèle.html); + this.vue.vUid.text(this.modèle.uid); + } + + var that = this; + this.vue.toggle(function() { + that.modèle.mInstanceRecherche.ajouterRésultatSélection(that); + }, function() { + that.modèle.mInstanceRecherche.supprimerRésultatSélection(that); + }); + + this.ajoutSélection = function() { + this.vue.addClass('sélectionné'); + }; + + this.suppressionSélection = function() { + this.vue.removeClass('sélectionné'); + }; + + this.suppression = function(anim) { + that.modèle.mInstanceRecherche.supprimerRésultatSélection(that); + that.vue.suppression(anim); + } + + this.setModèle(mRésultatRecherche); +} +\ No newline at end of file diff --git a/jside3/style.css b/jside3/style.css @@ -3,6 +3,10 @@ overflow: hidden; } +.clearfloat { + clear: both; +} + body { cursor: default; position:absolute; @@ -28,7 +32,78 @@ body { left: 100px; border: thin solid blue; - background-color: lightblue; + background-color: white; +} + +/* Recherche */ +.recherche.fenetre { + position: absolute; + bottom: 250px; + right: 100px; + width: 15em; + min-width: 4em; + min-height: 3em; + height: 8em; + + border: thin solid blue; + background-color: white; +} + +.recherche.résultats { + position: absolute; + top: 1.4em; + bottom: 0; + width: 100%; + overflow: auto; +} + +.recherche.termes { + float: right; +} + +/* Résultat-recherche */ +.résultat-recherche:hover { + /* Doit être plus important que les flashouillages + * rouges et verts */ + background-color: #eee !important; +} + +.résultat-recherche.sélectionné { + background-color: lightgray; !important; +} + +.résultat-recherche.ajout { + background-color: lightgreen; +} + +.résultat-recherche.suppression { + background-color: pink; + overflow: hidden; +} + +.résultat-recherche.vUid { + display: block; + font-size: small; + color: gray; + padding-right: 0.2em; + float: right; +} + +.résultat-recherche .occurence { + color: green; + font-weight: bold; +} + +.résultat-recherche .superposée { + color: orange; + font-weight: bold; +} + +.résultat-recherche .superposition { + /* Yeah, sorry, that character is overlapped by + two or more matches. Want some chocolate ? */ + color: chocolate; + font-weight: bold; } /* Log */ @@ -61,8 +136,8 @@ body { float: right; } -/* Bloc */ -.bloc.fenetre { +/* Instance-bloc */ +.instance-bloc.vMain { position: absolute; top: 250px; left: 300px; @@ -75,23 +150,22 @@ body { background-color: white; } -.bloc.titre { - background-color: lightgray; - border: medium solid white; -} - -.bloc.titre { +.instance-bloc.vBarre-titre { background-color: lightgray; border: medium solid white; border-bottom: none; } -/* Tabs */ -.bloc.tabs.titres { +.instance-bloc.vDéfinitions { position: absolute; top: 1.4em; left: 0; right: 0; + bottom: 0; +} + +/* Définitions (Tabs) */ +.définitions.vTitresTabs { background: lightgray; padding-bottom: 0; @@ -99,23 +173,11 @@ body { border-style: none solid none solid; } -.définition.titre { - background-color: white; - border: thin solid gray; - margin: 0.1em 0.1em 0 0; - float: left; -} - -.définition.titre.active { - background-color: #eee; - border-bottom: thin solid white; -} - -.nouvelle-définition { +.définitions.vNouvelle-définition { float: right; } -.définitions { +.définitions.vContenusTabs { position: absolute; top: 2.9em; left: 0; @@ -125,18 +187,39 @@ body { padding-bottom: .1em; } -/* Définitions */ -.définition.contenu { +/* Définition */ +.définition.vTitre { + background-color: white; + border: thin solid gray; + margin: 0.1em 0.1em 0 0; + float: left; +} + +.définition.vTitre.active { + background-color: #eee; + border-bottom: thin solid white; +} + +.définition.vCorps { height: 100%; } -.définition.contenu.aucune-définition { +.définition.vCorps.vAucune-définition { text-align: center; padding-top: 1em; } +/* Zone */ +.vZone { + position: absolute; + border: thin solid blue; + background-color: lightblue; + opacity: 0.5; +} + /* Fenêtres */ -.barre-titre { +.barre-titre, +.vBarre-titre{ background-color: #eef; border-bottom: thin solid blue; padding: .1em; @@ -144,7 +227,8 @@ body { text-align: center; } -h2.titre { +h2.titre, +h2.vTitre { font-size: 100%; margin: 0; }