Bonjour,
Je voulais combiner le plugin nestedSortable de jquery( https://github.com/mjsarfatti/nestedSortable) avec le tree Behavior du cakephp( http://book.cakephp.org/2.0/fr/core-libraries/behaviors/tree.html)
J'ai pas trouvé comment affiché le code formaté dès le début
J'explique:
la méthode generateTreeList() renvoie en clé l'ID et en valeur le nom(champs name/title de la table) avec un préfixe 'spacer'(par défaut c'est un underscore '_' ) pour les éléments enfant qu'on peut le modifier
example :

<?php
array(
    [1] => "Non catégorisé",
    [2] => "Blog",
    [3] => "_Html",
    [4] => "_Css",
    [5] => "_Php",
    [6] => "Portfolio",
    [7] => "_Web",
    [8] => "_Graphisme",
)
?>

il faut générer ce code html :

<ol class="nested">
      <li id="sort-1"><div>Non catégorisé</div></li>
      <li id="sort-2">
        <div>blog</div>
        <ol>
          <li id="sort-3"><div>html</div></li>
          <li id="sort-4"><div>css</div></li>
          <li id="sort-5"><div>php</div></li>
        </ol>
      </li>
      <li id="sort-6">
        <div>portfolio</div>
        <ol>
          <li id="sort-7"><div>web</div></li>
          <li id="sort-8"><div>graphism</div></li>
        </ol>
      </li>
    </ol>

Merci d'avance ;)

3 réponses


BenFarhat
Réponse acceptée

Bonjour flashios
j'ai essayé de pondre un truc vite fait qui apparemment semble marcher pour moi (mais il y a peut être un cas particulier qui pourrait bloquer) bref le principe y est, du moins c'est ce que je pense :)

Commençons d'abord par l'explication du menu et sous menu en html basés sur des <ul> et <li>
quand on est au même niveau de menu on a des ensemble de <li>
comme pour ton cas

<li id="sort-3"><div>html</div></li>
      <li id="sort-4"><div>css</div></li>
      <li id="sort-5"><div>php</div></li>

si on monte d'un niveau alors on ouvre un <li> sans le fermer puis on prépare un <ul> qui va accepter les sous menu
logiquement dans ton cas ca aurait été

<li><a href="#">blog</a>
    <ul>
      <li id="sort-3"><div>html</div></li>
      <li id="sort-4"><div>css</div></li>
      <li id="sort-5"><div>php</div></li>
    </ul>
    </li>

et si on descend d'un niveau on fait ce que je viens de dire, on faire le <ul> puis le <li>
(dans ton cas c'est autre chose ! j'y arrive à la fin)
A présent le principe pour savoir si on monte, descend ou reste au même niveau c'est d'utiliser le caractère ajouter dans la fonction generatetreelist, il suffit de les compter et de comparer à la position de l’élément précédent et le tour est joué

Donc mon code
au niveau du controller

$table = $this->Menu->generateTreeList(null, null, null, '%'); // j'utilise ici le pourcentage
$this->set('table', $table);

au niveau de la vue j'ai ca

//debug($table);
    $pos=0; // on initialise la position de l'élement précédent
    echo '<ul class="nav nav-pills">'; // la j'ouvre ce qui encadre mon menu (ici basé sur bootstrap)
    $i=0; // ici c'est un compteur pour savoir si je début ou pas
    foreach($table as $k=>$v){ // je parcours mon tableau (pour le cas j'utilise pas vraiment $k)
        $tab=explode("%",$v); // j'explose la table en séparant chaque cellule par un "%"
        $nombre=count($tab) -1; // je compte le nombre de cellule puis j'enlève 1 pour avoir la position courant
        if ($nombre==$pos) { // et la opérer la magie je teste par rapport à la position précédente
            if($i>0) echo "</li>"; 
            echo "<li><a href='#'>$tab$nombre]</a>"; // ici en fait je ferme pas le li car je sais pas si il y a un sous menu
        }
        if ($nombre>$pos) echo "<ul><li><a href='#'>$tab$nombre]</a>"; // s'il y a des enfant j'insérér le ul puis le li
                if ($nombre<$pos) {
                                  for($i=$nombre;$i>=$pos;$i--) echo "</ul></li>"; // ici c'est le cas ou on tombe d'un niveau X à x-2 x-3 etc...
                                  echo "</li></ul><li id='sort-$k'><a href='#'>$tab$nombre]</a>";   
                           }
        $pos=$nombre; // ensuite je met la position courante $nombre dans la position précédent $pos pour tester à la prochaine boucle
    }
    for($pos;$pos>0;$pos--) echo "</ul></li>"; // ici j'ai juste dans le cas ou je fini par exemple directement au niveau 4 je doit fermer les ul et li correspondant
    echo '</ul>'; // et la je ferme le <ul> du menu

Pour ce qui est de ton cas c'est pareil j'ai juste changé les balises A par DIV et UL par OL

voila le code de la vue (pour le controller pense à change le tiret bas "_" par le pourcentage "%"

$pos=0;
    echo '<ol class=nested">';
    $i=0;
    foreach($table as $k=>$v){
        $tab=explode("%",$v);
        $nombre=count($tab) -1;
        if ($nombre==$pos) {
            if($i>0) echo "</li>";
            echo "<li id='sort-$k'><div>$tab$nombre]</div>"; // ici $tab[nombre] m'affiche la dernière position et donc j'évite le réaffichage des %
        }
        if ($nombre>$pos) echo "<ol><li id='sort-$k'><div>$tab$nombre]</div>";
        if ($nombre<$pos) {
                                  for($i=$nombre;$i>=$pos;$i--) echo "</ol></li>"; // ici c'est le cas ou on tombe d'un niveau X à x-2 x-3 etc...
                                  echo "</li></ol><li id='sort-$k'><div>$tab$nombre]</div>";    
                           }
                   $pos=$nombre;
    }
    for($pos;$pos>0;$pos--) echo "</ol></li>";
    echo '</ol>';

et le résultat de mon test

<ol class="nested"">
    <li id="sort-1">
        <div>Mes catégories</div>
            <ol>
                <li id="sort-2">
                    <div>Fun</div>
                        <ol>
                            <li id="sort-6">
                                <div>Amis</div>
                                    <ol>
                                        <li id="sort-7">
                                            <div>Gérard</div>
                                        </li>
                                        <li id="sort-8">
                                            <div>Gwendoline</div>
                                        </li>
                                    </ol>
                            </li>
                            <li id="sort-16">
                                <div>test</div>
                            </li>
                        </ol>
                </li>
                <li id="sort-3">
                    <div>Sport</div>
                        <ol>
                            <li id="sort-4">
                                <div>Surf</div>
                            </li>
                            <li id="sort-5">
                                <div>Tricot Extreme </div>
                                    <ol>
                                        <li id="sort-9">
                                            <div>Travail</div>
                                        </li>
                                    </ol>
                            </li>
                        </ol>
                    </li>
            </ol>
    </li>
</ol>

Voila j'espère ne pas avoir dit de bêtises et que ca t'aidera Bonne continuation :)

Si tu veut le nombre d'articles enfants dans ton controlleur tu rajoutes ceci

foreach($tableas $k=>$v)
    $child$k]=$this->Menu->childCount($k);
    $this->set('childCount',$child);

et au niveau du code de la vue tu met ce qui suit:

echo "<li id='sort-$k'><div>$tab$nombre] ($childCount$k])</div>";

Meci BenFarhat mais j'ai trouvé déjà une solution plus simple.
J'utilise find('threaded') à la place de generateTreeList() et j'ai créer un p'tit helper pour générer le code de la vue.

public function generate($categories, $options = array()){
        $this->__options = array_merge(
            array(
                'model' => null,
                'listType' => 'ol',
                'id' => null,
                'class' => null,
                'wrapper' => 'div'
            ), 
            (array)$options
        );
        if($this->__options'model'] == null){
            $model = current($this->request->params'models']);
            $model = $model'className'];
        }
        $listType = $this->__options'listType'];
        $this-> __options'id'] !== null ? $id = ' id="'.$this->__ options'id'].'"' : $id = '';
        $this-> __options'class'] !== null ? $class = ' class="'.$this->__ options'class'].'"' : $class = '';
        $wrapper = $this->__options'wrapper'];
        $this->html .= '<'.$listType.$id.$class.'>';
        foreach ($categories as $key => $category) {
            $this->html .= '<li id="sort-'.$category$model]'id'].'">';
            $this->html .= '<'.$wrapper.'>';
            $this->html .= $category$model]'name'];
            $this->html .= '</'.$wrapper.'>' ;
            if (!empty($category'children'])) {
                $this->generate($category'children'], array('model' => $this-> __options'model'], 'listType' => $this->__ options'listType'], 'wrapper' => $this->__options'wrapper']));
            }
            $this->html .= '</li>';
        }
        $this->html .= '</'.$listType.'>';
        return $this->html;
    }

Merci à tous les deux, vous venez de me faire économiser pas mal de taff. Puis en faire un plugin a destination de github ?