--- /dev/null
+;(function($){
+
+$.fn.spiptree = function(options) {
+
+ var $mytree = $(this);
+ var $mytree_source = $mytree.clone();
+ // $mytree.after($mytree_source);
+
+ options.plugins = [ "types", "search", "state" ];
+ if (options.drag) {
+ options.plugins.push("dnd");
+ }
+
+ options.types = {
+ "#" : {
+ "valid_children" : ["default"]
+ },
+ "default" : {
+ "icon" : options.default.icon,
+ "valid_children" : [ "default" ]
+ }
+ }
+
+ options.confirm = {
+ move: null
+ };
+
+ $.each(options.objets, function(nom, desc) {
+ options.types.default.valid_children.push(desc.type);
+ options.types.default.valid_children.push("box_" + desc.type);
+ options.types[desc.type] = {
+ "icon" : desc.icon,
+ "max_children" : 0,
+ "max_depth" : 0
+ };
+ options.types["box_" + desc.type] = {
+ "icon" : desc.icon,
+ "max_depth" : 1,
+ "valid_children" : [ desc.type ]
+ };
+ });
+
+ $mytree.jstree({
+ "plugins" : options.plugins,
+ "core" : {
+ "animation" : 0,
+ "check_callback" : function (op, node, par, pos, more) {
+ if (op === "move_node") {
+ // à la fin d'un déplacement
+ // (pas de trig spécifique au début d'un déplacement :( )
+ if (more && more.core) {
+ // ne pas tenter de déplacer une box non chargée
+ var box = (node.type.substring(0, 4) == 'box_');
+ if (box && (!node.children || !node.children.length)) {
+ $('#contenu p.success, #contenu div.error').remove();
+ $("#contenu #mytree_actions").after("<div class='error removable' onClick='$(this).remove();'><p /><ul class='spip' /></div>");
+ $box = $("#contenu div.error");
+ $box.find('p').text(options.textes.deplacement.vide + ' ' + options.textes.deplacement.suggerer_deplier);
+ return false;
+ }
+
+ // Demander 1 fois (et 1 seule) une confirmation, même si on déplace 5 items d'un coup
+ if (options.confirm.move === null) {
+ options.confirm.move = confirm( options.textes.deplacement.confirmation );
+ // enlever les messages de réussite ou d'erreur pour en avoir des tout neufs
+ if (options.confirm.move) {
+ $('#contenu p.success, #contenu div.error').remove();
+ }
+ }
+ return options.confirm.move;
+ } else {
+ // redemander la confirmation au prochain tour
+ options.confirm.move = null;
+ }
+ }
+ return true;
+ },
+ "data" : function (node, cb) {
+ // on est obligé de tout charger en ajax (même la racine)
+ // donc on charge 1 fois la racine avec le html d'origine
+ if (node.id === '#') {
+ cb($mytree_source.html());
+ }
+
+ // et pour ce qu'on ne connait pas (classe css 'jstree-closed' sur un LI, et pas de UL à l'intérieur)
+ // on fait un appel ajax pour obtenir la liste correspondant à l'objet souhaité, lorsque c'est demandé.
+ else {
+ var objet = node.data.objet;
+ var id_rubrique = (objet == 'rubrique')
+ ? node.id.split('-')[1]
+ : node.parent.split('-')[1];
+ var params = {
+ "id_rubrique": id_rubrique,
+ "objet": objet
+ };
+ if (options.statut) {
+ params.statut = options.statut;
+ }
+
+ $.ajax({
+ url: options.urls.plan,
+ data: params,
+ dataType: 'html',
+ cache: false,
+ }).done(function(data) {
+ if (data !== undefined) {
+ cb(data);
+ } else {
+ cb("");
+ }
+ });
+ }
+ }
+ },
+ "search" : {
+ "show_only_matches" : true,
+ },
+ "types" : options.types
+ });
+
+ if (options.drag) {
+ $mytree.addClass('drag');
+ }
+
+ // un clic d'une feuille amène sur son lien
+ // mais… éviter que le plugin 'state' clique automatiquement lorsqu'il restaure
+ // la sélection précédente !
+ $mytree.one("state_ready.jstree", function () {
+ $(this).on("changed.jstree", function (e, data) {
+ data.instance.save_state();
+ var node = data.instance.get_node(data.node, true);
+ if (node) {
+ var lien = node.children('a').attr('href');
+ if (lien && !(options.drag && $(data.event.target).hasClass('jstree-icon'))) {
+ location.href = lien;
+ }
+ }
+ });
+ });
+
+ var recharge_plan = false;
+ // lorsqu'on déplace un nœud
+ $mytree.on("move_node.jstree", function(event, data) {
+ // si les parents sont identiques : pas de changement,
+ // on ne peut/veut pas gérer ici les positionnements
+
+ if (data.old_parent == data.parent) {
+ // data.instance.refresh();
+ return true;
+ }
+
+ // il existe 2 cas de boites :
+ // - un item (rubrique, article, site) a été déplacé
+ // - un conteneur (box_xx) a été déplacé (ie: tous les articles qu'il contient par exemple)
+ // dans ce cas on retrouve tous les identifiants déplacés
+ var box = (data.node.type.substring(0, 4) == 'box_');
+ var infos = data.node.id.split('-'); // articles-rubrique-30 (box) ou article-30 (item)
+
+ if (box) {
+ var ids = [];
+ $.each(data.node.children, function(key, val) {
+ ids.push( val.split('-')[1] );
+ });
+ var params = {
+ objet: infos[0],
+ id_objet: ids,
+ id_rubrique_source: infos[2],
+ id_rubrique_destination: data.parent.split('-')[1]
+ }
+ } else if (infos[0] == 'rubrique') {
+ // les rubriques n'ont pas de 'box_' et sont directement dans les sous rubriques
+ var params = {
+ objet: infos[0],
+ id_objet: [ infos[1] ],
+ id_rubrique_source: (data.old_parent == '#' ? 0 : data.old_parent.split('-')[1]),
+ id_rubrique_destination: (data.parent == '#' ? 0 : data.parent.split('-')[1])
+ }
+ } else {
+ // un item, sa destination est soit une box (de même type) soit une rubrique
+ var dest = data.parent.split('-'); // articles-rubrique-30 (box) ou rubrique-30
+ var params = {
+ objet: infos[0],
+ id_objet: [ infos[1] ],
+ id_rubrique_source: data.old_parent.split('-')[2],
+ id_rubrique_destination: (dest.length == 3 ? dest[2] : dest[1]),
+ }
+ }
+
+ $mytree.animateLoading();
+
+ $.ajax({
+ url: options.urls.deplacer,
+ data: params,
+ dataType: 'json',
+ cache: false,
+ }).done(function(response) {
+
+ if (response) {
+ var nb_success = Object.keys(response.success).length;
+ var nb_errors = Object.keys(response.errors).length;
+ if (nb_success) {
+ var $box = $("#contenu p.success");
+ if (!$box.length) {
+ $("#contenu #mytree_actions").after("<p class='success removable' onClick='$(this).remove();'></p>");
+ $box = $("#contenu p.success").data('nb', 0);
+ }
+ nb = nb_success + $box.data('nb');
+ $box.data('nb', nb).text(nb == 1
+ ? options.textes.deplacement.reussi
+ : options.textes.deplacement.reussis.replace('@nb@', nb));
+ }
+ if (nb_errors) {
+ var $box = $("#contenu div.error");
+ if (!$box.length) {
+ $("#contenu #mytree_actions").after("<div class='error removable' onClick='$(this).remove();'><p /><ul class='spip' /></div>");
+ $box = $("#contenu div.error").data('nb', 0);
+ }
+ nb = nb_errors + $box.data('nb');
+ $box.data('nb', nb).find('p').text(nb == 1
+ ? options.textes.deplacement.echec
+ : options.textes.deplacement.echecs.replace('@nb@', nb));
+ $.each(response.errors, function(i, error) {
+ $box.find('ul').append("<li>[ " + i + "] " + error+ "</li>");
+ });
+ }
+ $mytree.endLoading();
+ }
+
+ if (recharge_plan) {
+ clearTimeout(recharge_plan);
+ }
+ recharge_plan = setTimeout(function () {
+ ajaxReload('plan');
+ }, 500);
+ });
+
+ return true;
+ });
+
+
+ // recherche automatique
+ $mytree_search = $("#mytree_search");
+
+ var to = false;
+ $mytree_search.keyup(function () {
+ if (to) { clearTimeout(to); }
+ to = setTimeout(function () {
+ var v = $mytree_search.val();
+ $mytree.jstree(true).search(v);
+ }, 250);
+ });
+
+};
+
+})(jQuery);