Bonjour,
Je travaille actuellement sur une Single Page Application. Elle dispose de son propre système de routing. Chaque changement de hash se traduit par le chargement d'un contrôleur, qui à son tour charge une vue.
Dans un des contrôleurs je suis amené à charger un plugin jQuery associé un élément du DOM. Il permet de gérer une hiérarchie de manière horizontale:
[NIVEAU1] [FLECHE] [NIVEAU 2] [FLECHE] [NIVEAU 3] [FLECHE]
Si je clique sur "[FLECHE]" une div apparaît et permet de sélectionner les enfants.
Exemple:
Si je clique sur là "[FLECHE]" la plus à gauche j'affiche la liste des niveaux 2.
Le plugin a cette structure (version simplifiée):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 (function($) { function Hierarchy(element, options) { this.$element = $(element); this.initialize(); this.$element.on("click", "button", $.proxy(this.open, this)); } Hierarchy.prototype = { /** * initialize * On ajouteu un bouton **/ initialize: function() { this.$element.html('<button>Ouvrir</button>'); }, /** * open * Evènement déclenché lorsqu'on clique sur le bouton * @param event **/ open: function(event) { var that = this; var $that = $(event.currentTarget); var offset = $that.offset(); // création de la fenêtre au niveau du body var $animation = $('<div class="animation">Animation</div>').appendTo('body'); // positionnement de la fenêtre $animation.css({ position: "absolute", top: offset.top, left: offset.left + $that.outerWidth(), width: 100, height: 30, backgroundColor: "red" }); } } function Plugin(options) { $(document).on("click.hierarchyplugin", function(event) { /* * on supprime la fenêtre si la cible (event.target) n'a pas de parent * qui correspond à la fenêtre ou au bouton "ouvrir" */ }); return this.each(function() { new Hierarchy(this, options); }); } $.fn.hierarchy = Plugin; $.fn.hierarchy.Constructor = Hierarchy; })(jQuery); $('div.hierarchy').hierarchy();
1) On appelle le plugin jQuery sur une sélection de div.hierarchy
2) Pour chaque sélecteur on appelle l'objet Hierarchy(element, options)
3) On créer un bouton "Ouvrir" à l'intérieur de div.hiearchy
4) Si on clique sur "Ouvrir" une div ayant pour classe "animation" est ajoutée au body (et positionnée en absolute)
5) Si on clique en dehors de div.animation ou div.hierarchy alors on ferme div.animation
On a donc deux événements:
- Un événement "directement associé" à l’élément lié au plugin (div.hierarchy)
- Un événement associé à "document"
Le problème est le suivant: admettons que l'on change de route, et donc de vue: l’événement associé à "document" sera encore "vivant" (et même dupliqué si le plugin est de nouveau chargé).
Pour le moment j'ai 2 solutions:
1) avant l'affichage de chaque contrôleur je supprime le handler:
Inconvénient: le plugin ne fonctionne pas de manière indépendante
Code : Sélectionner tout - Visualiser dans une fenêtre à part $(document).off("click.hierarchyplugin");
2) avant de définir le handler je le supprime:
Inconvénient: le handler reste vivant si on va sur une vue qui ne fait pas appel au plugin
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 $(document).off("click.hierarchyplugin"); $(document.on("click.hierarchyplugin", function(event) { ... });
Auriez-vous d'autres solutions à proposer? Que pensez-vous du fonctionnement du plugin et de ma manière de faire?
Merci d'avance
Partager