[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / plugins-dist / plan / prive / javascript / spiptree.js
1 ;(function($){
2
3 $.fn.spiptree = function(options) {
4
5 var $mytree = $(this);
6 var $mytree_source = $mytree.clone();
7 // $mytree.after($mytree_source);
8
9 options.plugins = [ "types", "search", "state" ];
10 if (options.drag) {
11 options.plugins.push("dnd");
12 }
13
14 options.types = {
15 "#" : {
16 "valid_children" : ["default"]
17 },
18 "default" : {
19 "icon" : options.default.icon,
20 "valid_children" : [ "default" ]
21 }
22 }
23
24 options.confirm = {
25 move: null
26 };
27
28 $.each(options.objets, function(nom, desc) {
29 options.types.default.valid_children.push(desc.type);
30 options.types.default.valid_children.push("box_" + desc.type);
31 options.types[desc.type] = {
32 "icon" : desc.icon,
33 "max_children" : 0,
34 "max_depth" : 0
35 };
36 options.types["box_" + desc.type] = {
37 "icon" : desc.icon,
38 "max_depth" : 1,
39 "valid_children" : [ desc.type ]
40 };
41 });
42
43 $mytree.jstree({
44 "plugins" : options.plugins,
45 "core" : {
46 "animation" : 0,
47 "check_callback" : function (op, node, par, pos, more) {
48 if (op === "move_node") {
49 // à la fin d'un déplacement
50 // (pas de trig spécifique au début d'un déplacement :( )
51 if (more && more.core) {
52 // ne pas tenter de déplacer une box non chargée
53 var box = (node.type.substring(0, 4) == 'box_');
54 if (box && (!node.children || !node.children.length)) {
55 $('#contenu p.success, #contenu div.error').remove();
56 $("#contenu #mytree_actions").after("<div class='error removable' onClick='$(this).remove();'><p /><ul class='spip' /></div>");
57 $box = $("#contenu div.error");
58 $box.find('p').text(options.textes.deplacement.vide + ' ' + options.textes.deplacement.suggerer_deplier);
59 return false;
60 }
61
62 // Demander 1 fois (et 1 seule) une confirmation, même si on déplace 5 items d'un coup
63 if (options.confirm.move === null) {
64 options.confirm.move = confirm( options.textes.deplacement.confirmation );
65 // enlever les messages de réussite ou d'erreur pour en avoir des tout neufs
66 if (options.confirm.move) {
67 $('#contenu p.success, #contenu div.error').remove();
68 }
69 }
70 return options.confirm.move;
71 } else {
72 // redemander la confirmation au prochain tour
73 options.confirm.move = null;
74 }
75 }
76 return true;
77 },
78 "data" : function (node, cb) {
79 // on est obligé de tout charger en ajax (même la racine)
80 // donc on charge 1 fois la racine avec le html d'origine
81 if (node.id === '#') {
82 cb($mytree_source.html());
83 }
84
85 // et pour ce qu'on ne connait pas (classe css 'jstree-closed' sur un LI, et pas de UL à l'intérieur)
86 // on fait un appel ajax pour obtenir la liste correspondant à l'objet souhaité, lorsque c'est demandé.
87 else {
88 var objet = node.data.objet;
89 var id_rubrique = (objet == 'rubrique')
90 ? node.id.split('-')[1]
91 : node.parent.split('-')[1];
92 var params = {
93 "id_rubrique": id_rubrique,
94 "objet": objet
95 };
96 if (options.statut) {
97 params.statut = options.statut;
98 }
99
100 $.ajax({
101 url: options.urls.plan,
102 data: params,
103 dataType: 'html',
104 cache: false,
105 }).done(function(data) {
106 if (data !== undefined) {
107 cb(data);
108 } else {
109 cb("");
110 }
111 });
112 }
113 }
114 },
115 "search" : {
116 "show_only_matches" : true,
117 },
118 "types" : options.types
119 });
120
121 if (options.drag) {
122 $mytree.addClass('drag');
123 }
124
125 // un clic d'une feuille amène sur son lien
126 // mais… éviter que le plugin 'state' clique automatiquement lorsqu'il restaure
127 // la sélection précédente !
128 $mytree.one("state_ready.jstree", function () {
129 $(this).on("changed.jstree", function (e, data) {
130 data.instance.save_state();
131 var node = data.instance.get_node(data.node, true);
132 if (node) {
133 var lien = node.children('a').attr('href');
134 if (lien && !(options.drag && $(data.event.target).hasClass('jstree-icon'))) {
135 location.href = lien;
136 }
137 }
138 });
139 });
140
141 var recharge_plan = false;
142 // lorsqu'on déplace un nœud
143 $mytree.on("move_node.jstree", function(event, data) {
144 // si les parents sont identiques : pas de changement,
145 // on ne peut/veut pas gérer ici les positionnements
146
147 if (data.old_parent == data.parent) {
148 // data.instance.refresh();
149 return true;
150 }
151
152 // il existe 2 cas de boites :
153 // - un item (rubrique, article, site) a été déplacé
154 // - un conteneur (box_xx) a été déplacé (ie: tous les articles qu'il contient par exemple)
155 // dans ce cas on retrouve tous les identifiants déplacés
156 var box = (data.node.type.substring(0, 4) == 'box_');
157 var infos = data.node.id.split('-'); // articles-rubrique-30 (box) ou article-30 (item)
158
159 if (box) {
160 var ids = [];
161 $.each(data.node.children, function(key, val) {
162 ids.push( val.split('-')[1] );
163 });
164 var params = {
165 objet: infos[0],
166 id_objet: ids,
167 id_rubrique_source: infos[2],
168 id_rubrique_destination: data.parent.split('-')[1]
169 }
170 } else if (infos[0] == 'rubrique') {
171 // les rubriques n'ont pas de 'box_' et sont directement dans les sous rubriques
172 var params = {
173 objet: infos[0],
174 id_objet: [ infos[1] ],
175 id_rubrique_source: (data.old_parent == '#' ? 0 : data.old_parent.split('-')[1]),
176 id_rubrique_destination: (data.parent == '#' ? 0 : data.parent.split('-')[1])
177 }
178 } else {
179 // un item, sa destination est soit une box (de même type) soit une rubrique
180 var dest = data.parent.split('-'); // articles-rubrique-30 (box) ou rubrique-30
181 var params = {
182 objet: infos[0],
183 id_objet: [ infos[1] ],
184 id_rubrique_source: data.old_parent.split('-')[2],
185 id_rubrique_destination: (dest.length == 3 ? dest[2] : dest[1]),
186 }
187 }
188
189 $mytree.animateLoading();
190
191 $.ajax({
192 url: options.urls.deplacer,
193 data: params,
194 dataType: 'json',
195 cache: false,
196 }).done(function(response) {
197
198 if (response) {
199 var nb_success = Object.keys(response.success).length;
200 var nb_errors = Object.keys(response.errors).length;
201 if (nb_success) {
202 var $box = $("#contenu p.success");
203 if (!$box.length) {
204 $("#contenu #mytree_actions").after("<p class='success removable' onClick='$(this).remove();'></p>");
205 $box = $("#contenu p.success").data('nb', 0);
206 }
207 nb = nb_success + $box.data('nb');
208 $box.data('nb', nb).text(nb == 1
209 ? options.textes.deplacement.reussi
210 : options.textes.deplacement.reussis.replace('@nb@', nb));
211 }
212 if (nb_errors) {
213 var $box = $("#contenu div.error");
214 if (!$box.length) {
215 $("#contenu #mytree_actions").after("<div class='error removable' onClick='$(this).remove();'><p /><ul class='spip' /></div>");
216 $box = $("#contenu div.error").data('nb', 0);
217 }
218 nb = nb_errors + $box.data('nb');
219 $box.data('nb', nb).find('p').text(nb == 1
220 ? options.textes.deplacement.echec
221 : options.textes.deplacement.echecs.replace('@nb@', nb));
222 $.each(response.errors, function(i, error) {
223 $box.find('ul').append("<li>[ " + i + "] " + error+ "</li>");
224 });
225 }
226 $mytree.endLoading();
227 }
228
229 if (recharge_plan) {
230 clearTimeout(recharge_plan);
231 }
232 recharge_plan = setTimeout(function () {
233 ajaxReload('plan');
234 }, 500);
235 });
236
237 return true;
238 });
239
240
241 // recherche automatique
242 $mytree_search = $("#mytree_search");
243
244 var to = false;
245 $mytree_search.keyup(function () {
246 if (to) { clearTimeout(to); }
247 to = setTimeout(function () {
248 var v = $mytree_search.val();
249 $mytree.jstree(true).search(v);
250 }, 250);
251 });
252
253 };
254
255 })(jQuery);