良百科

枯榆绕屋,迎门绿竹。

用户工具

站点工具

  • write
  • everyday
  • yufa
  • poem
  • template
  • syntax
  • random
  • xiangfen
  • baidu
  • 抱歉,您没有权限增加页面

    navi_plugin

    navi Plugin

    —- plugin —-
    description: Build a navigation menu from a list
    author : Andreas Gohr
    email : dokuwiki@cosmocode.de
    type : syntax
    lastupdate : 2019-03-20
    compatible : Detritus, Hrun, Elenor Of Tsort
    depends :
    conflicts :
    similar : indexmenu
    tags : navigation, menu
    alter : true

    sourcerepo : https://github.com/cosmocode/navi
    downloadurl: https://github.com/cosmocode/navi/zipball/master
    bugtracker : https://github.com/cosmocode/navi/issues


    This plugin allows you to create a nested navigation menu based on a list defined in a Wiki page. Lower navigation levels are shown or hidden dependent on the current page. It is intended for the use in the sidebar of a template supporting one (tested on Arctic). A notable feature is that it allows you to create hierarchical menus without the need of a hierarchical namespace structure.

    ===== Download and Install =====
    A CosmoCode Plugin

    Search and install the plugin using the Extension Manager. Refer to Plugins on how to install plugins manually.


    Changes

    Usage

    In the page defining the sidebar in your template add the following syntax:

    search?q=navigationmenu&btnI=lucky

    where navigationmenu is any other page containing an unordered list of page links — this page we call the “control page”.

    Notes:

    * The created menu is completely independent of any namespace structure. The hierarchy is created by the list nesting only. Exception: when the ?ns option is used (see below)
    * The navigation menu page should contain exactly one unordered list, other content will be ignored
    * The list items should only contain links, any other syntax will be ignored
    * Each page linked in the list should occur only once

    Control Page Example

    The following would create a menu with 4 top level entries: “Welcome”, “Products”, “Service” and “Wiki Syntax”. When you are on the “Products” page, the sub entries “Foomatic 2000” and “Foomatic 2010” are visible.

    \\
    * [[start|Welcome]]\\
    * [[Products|]]\\
      * [[Foomatic 2000|]]\\
      * [[Foomatic 2010|]]\\
    * [[Service|]]\\
      * [[about|About Foo Inc.]]\\
      * [[Contact|]]\\
    * [[syntax|Wiki Syntax]]\\
    

    This allows you to create hierarchical menus without the need of a hierarchical namespace structure.

    Making use of Namespaces

    Sometimes the navi plugin is used to create collapsible, editable navigation even though content is structured into nested namespaces. But since the plugin knows nothing about those namespaces by default it will collapse completely as soon as a page is opened that is not defined in the control page.

    By adding ?ns to the navi plugin syntax, e.g. {{navi>navigationmenu?ns}}, you can make the plugin to be clever about namespaces: When it is called on a page that is not mentioned on the control page, it will have a look at the namespace of the page. It then checks if a startpage for the namespace is to be found in the control page. If it is, it will be used as the current open branch, if not it is checked if there is any other page in the same namespace on the controlpage. If found it's used. This is repeated for each higher namespace until the top is reached or a matching page.


    Mods

    Persistent level2

    If you want the menu to always show the level2 items, and the deeper ones only when on the path, for example:

    one

    two\\
    three\\

    four

    five      <- you are here\\
      six\\
      seven\\
    height

    You can replace the line 190-192 of syntax.php by :

    \\
    $diff = array_diff($info['parents'],$parent);\\
    if (!empty($diff) && isset($diff[1])) {\\
     continue;\\
    }\\

    This is tested and working with the plugin releas of 2016-10-12.

    contact@nliautaud.fr 2017/03/12

    ==== Add class if child has item ====
    I modified the function render to use it a little bit like a dynamic version,
    Menuitems will have list items now. If a child is defined and if it is open the Icon will change.
    If no Child is defined there is no list item.
    I add to the DIV li an open or closed class which can be read from the template css like following css-code example.
    oh-mark 2011/06/20

    \\
    div.dokuwiki div.navigation li {\\
    list-style: none;\\
    margin-left: 5em; /** default if more than defined levels **/ \\
    }\\
    div.dokuwiki div.navigation li.open   { list-style-image: url(images/open.gif); }\\
    div.dokuwiki div.navigation li.close  { list-style-image: url(images/closed.gif); }\\
    div.dokuwiki div.navigation li.level1 { margin-left: 0em; }\\
    div.dokuwiki div.navigation li.level2 { margin-left: 1em; }\\
    div.dokuwiki div.navigation li.level3 { margin-left: 2em; }\\
    div.dokuwiki div.navigation li.level4 { margin-left: 3em; }\\
    div.dokuwiki div.navigation li.level5 { margin-left: 4em; }\\

    here is the mod

      /**\\
       * Create output\\
       *\\
       * We handle all modes (except meta) because we pass all output creation back to the parent\\
       * mod by Mark Wolfgruber 20.06.2011\\
       *      *           \\
       */\\
      function render($format, &$R, $data) {\\
          global $INFO;\\
          global $ID;\\
          $fn   = $data[0];\\
          $opt  = $data[2];\\
          $data = $data[1];
     
          if($format == 'metadata'){\\
              $R->meta['relation']['naviplugin'][] = $fn;\\
              return true;\\
          }
     
          $R->info['cache'] = false; // no cache please
     
          $parent = array();\\
          if(isset($data[$INFO['id']])){\\
              $parent = (array) $data[$INFO['id']]['parents']; // get the "path" of the page we're on currently\\
              array_push($parent,$INFO['id']);\\
              $current = $INFO['id'];\\
          }elseif($opt == 'ns'){\\
              $ns   = $INFO['id'];
     
              // traverse up for matching namespaces\\
              do {\\
                  $ns = getNS($ns);\\
                  $try = "$ns:";\\
                  resolve_pageid('',$try,$foo);\\
                  if(isset($data[$try])){\\
                      // got a start page\\
                      $parent = (array) $data[$try]['parents'];\\
                      array_push($parent,$try);\\
                      $current = $try;\\
                      break;\\
                  }else{\\
                      // search for the first page matching the namespace\\
                       foreach($data as $key => $junk){\\
                          if(getNS($key) == $ns){\\
                              $parent = (array) $data[$key]['parents'];\\
                              array_push($parent,$key);\\
                              $current = $key;\\
                              break 2;\\
                          } \\
                      } \\
                  }
     
              } while($ns);\\
          }
     
          // we need the top ID for the renderer\\
          $oldid = $ID;\\
          $ID = $INFO['id'];
     
          // create a correctly nested list (or so I hope)\\
    //        $open = false; /** deacivated by mark **/\\
          $lvl  = 1;\\
          $R->listu_open();
     
          // read if item has childs and if it is open or closed /** mod by mark **/\\
          $upper=array();\\
          foreach((array) $data as $pid => $info){\\
              $state=(array_diff($info['parents'],$parent)) ? 'close':'';\\
              $countparents=count($info['parents']);\\
              if ( $countparents > '0') {\\
                  for($i=0; $i < $countparents; $i++){\\
                    $upperlevel=$countparents-1;\\
                    $upper[$info['parents'][$upperlevel]]=($state=='close')? 'close' : 'open';\\
                  }\\
              }        \\
          } /** mod by mark **/ \\
          unset($pid); // break the reference with the last element /** mod by mark **/\\
          \\
              // read if item has childs if it is open or closed\\
              foreach((array) $data as $pid => $info){\\
                  // only show if we are in the "path"\\
                  if(array_diff($info['parents'],$parent)) continue;\\
                  \\
                  if ($upper[$pid]) { /** mod by mark **/\\
                    $menuitem=($upper[$pid]=='open') ? 'open' : 'close';\\
                   } else {\\
                    $menuitem='';\\
                   } /** mod by mark **/
     
                  // skip every non readable page\\
                  if(auth_quickaclcheck(cleanID($info['page'])) < AUTH_READ) continue;\\
      \\
                  if($info['lvl'] == $lvl){\\
    //                    if($open) $R->listitem_close(); /** deacivated by mark **/\\
                      $R->listitem_open($lvl.' '.$menuitem); /** mod by mark **/\\
    //                    $open = true; /** deacivated by mark **/\\
                  }elseif($lvl > $info['lvl']){\\
                      for($lvl; $lvl > $info['lvl']; $lvl--){\\
    //                      $R->listitem_close(); /** deacivated by mark **/\\
    //                      $R->listu_close();    /** deacivated by mark **/\\
                      }\\
    //                    $R->listitem_close();   /** deacivated by mark **/\\
                      $R->listitem_open($lvl.' '.$menuitem); /** mod by mark **/\\
                  }elseif($lvl < $info['lvl']){\\
                      // more than one run is bad nesting!\\
                      for($lvl; $lvl < $info['lvl']; $lvl++){\\
    //                    $R->listu_open(); /** deacivated by mark **/\\
                        $R->listitem_open($info['lvl'].' '.$menuitem); /** mod by oh-mark **/\\
    //                    $open = true;  /** deacivated by mark **/\\
                      }\\
                  }\\
      \\
                  $R->listcontent_open();\\
                  if(($format == 'xhtml') && ($info['page'] == $current)) $R->doc .= '<span class="current">';\\
                  $R->internallink(':'.$info['page'],$info['title']);\\
                  if(($format == 'xhtml') && ($info['page'] == $current)) $R->doc .= '</span>';\\
                  $R->listcontent_close();\\
                  $R->listitem_close();  /** mod by mark **/\\
              }\\
    /*        while($lvl > 0){ \\
              $R->listitem_close();\\
              $R->listu_close();\\
              $lvl--;\\
          }  /** deacivated by mark **/\\
              $R->listu_close();  /** mod by mark **/
     
          $ID = $oldid;
     
          return true;\\
      }

    ===== BUG =====

    first submenu item level1 instead level2

    i tried this plugin and have a problem with the first submenu item. it have to be in the div class level2 but it became level1 after the script did his work — oh-mark 2011/06/19

    found the error:
    replace $lvl with $info['lvl'] in line ~173 — oh-mark 2011/06/19 22:50
              }elseif($lvl < $info['lvl']){\\
                  // more than one run is bad nesting!\\
                  for($lvl; $lvl < $info['lvl']; $lvl++){\\
                      $R->listu_open();\\
                      $R->listitem_open($info['lvl']); /** mod by oh-mark **/\\
                      $open = true;\\
                  }
    
    

    Rendering Bugs

    The closing of open menu entries does not work.
    The open menu child entries are on the same level like the main menu entries.
    The user does not see any indicator for child menu items if the main menu is closed.

    Tested with the code modifications on this page with Dokuwiki dokuwiki-rc2011-11-10.tgz “Angua”.
    HH 29.12.2011

    navi_plugin.txt · 最后更改: 2019/12/07 21:07 (外部编辑)