plugins: Manage our navigation through a plugin not manually
This commit is contained in:
parent
1148adb6bf
commit
e727f07ce5
|
@ -0,0 +1,16 @@
|
|||
# Config file for travis-ci.org
|
||||
|
||||
language: php
|
||||
php:
|
||||
- "7.0"
|
||||
- "5.6"
|
||||
- "5.5"
|
||||
- "5.4"
|
||||
- "5.3"
|
||||
env:
|
||||
matrix:
|
||||
- DOKUWIKI=master
|
||||
- DOKUWIKI=stable
|
||||
before_install: wget https://raw.github.com/splitbrain/dokuwiki-travis/master/travis.sh
|
||||
install: sh travis.sh
|
||||
script: cd _test && phpunit --stderr --group plugin_navi
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Tests for functionality of the navi plugin
|
||||
*
|
||||
* @group plugin_navi
|
||||
* @group plugins
|
||||
*
|
||||
*/
|
||||
class basic_plugin_navi_test extends DokuWikiTest {
|
||||
|
||||
protected $pluginsEnabled = array('navi');
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_controlpage_simple() {
|
||||
// arrange
|
||||
$controlpage = " * [[a]]\n * [[b]]\n * [[c]]";
|
||||
saveWikiText('controlpage', $controlpage, '');
|
||||
saveWikiText('navi', '{{navi>controlpage}}', '');
|
||||
|
||||
// act
|
||||
$info = array();
|
||||
$actualHTML = p_render('xhtml', p_get_instructions('{{navi>controlpage}}'), $info);
|
||||
|
||||
// assert
|
||||
$expectedHTML = '<div class="plugin__navi left"><ul>
|
||||
<li class="level1 "><div class="li"><a href="/./doku.php?id=a" class="wikilink2" title="a" rel="nofollow">a</a></div>
|
||||
</li>
|
||||
<li class="level1 close"><div class="li"><a href="/./doku.php?id=b" class="wikilink2" title="b" rel="nofollow">b</a></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>';
|
||||
$this->assertEquals($expectedHTML, $actualHTML);
|
||||
|
||||
}
|
||||
|
||||
public function test_controlpage_complex() {
|
||||
// arrange
|
||||
$controlpage = "
|
||||
* [[en:products:a:start|BasePage]]
|
||||
* [[en:products:b:d:start|2nd-level Page with hidden child]]
|
||||
* [[en:products:c:projects|hidden 3rd-level page]]
|
||||
* [[en:products:b:archive:start|2nd-level pape]]
|
||||
* [[en:products:c:start|current 2nd-level page with visible child]]
|
||||
* [[en:products:d:start|visible 3rd-level page]]
|
||||
";
|
||||
saveWikiText('controlpage', $controlpage, '');
|
||||
saveWikiText('navi', '{{navi>controlpage}}', '');
|
||||
global $ID, $INFO;
|
||||
|
||||
// act
|
||||
$info = array();
|
||||
$ID = 'en:products:c:start';
|
||||
$INFO['id'] = 'en:products:c:start';
|
||||
$actualHTML = p_render('xhtml', p_get_instructions('{{navi>controlpage}}'), $info);
|
||||
|
||||
$pq = phpQuery::newDocumentXHTML($actualHTML);
|
||||
|
||||
$actualPages = array();
|
||||
foreach ($pq->find('a') as $page) {
|
||||
$actualPages[] = $page->getAttribute('title');
|
||||
}
|
||||
|
||||
$actualLiOpen = array();
|
||||
foreach ($pq->find('li.open > div > a, li.open > div > span > a') as $page) {
|
||||
$actualLiOpen[] = $page->getAttribute('title');
|
||||
}
|
||||
|
||||
$actualLiClose = array();
|
||||
foreach ($pq->find('li.close > div > a, li.close > div > span > a') as $page) {
|
||||
$actualLiClose[] = $page->getAttribute('title');
|
||||
}
|
||||
|
||||
$this->assertEquals(array(
|
||||
0 => 'en:products:a:start',
|
||||
1 => 'en:products:b:d:start',
|
||||
2 => 'en:products:b:archive:start',
|
||||
3 => 'en:products:c:start',
|
||||
4 => 'en:products:d:start',
|
||||
), $actualPages, 'the correct pages in the correct order');
|
||||
$this->assertEquals(array(
|
||||
0 => 'en:products:a:start',
|
||||
1 => 'en:products:c:start',
|
||||
), $actualLiOpen, 'the pages which have have children and are open should have the "open" class');
|
||||
$this->assertEquals(array(
|
||||
0 => 'en:products:b:d:start',
|
||||
), $actualLiClose, 'the pages which have have children, but are closed should have the "close" class');
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Tests for functionality of the navi plugin
|
||||
*
|
||||
* @group plugin_navi
|
||||
* @group plugins
|
||||
*
|
||||
*/
|
||||
class external_plugin_navi_test extends DokuWikiTest {
|
||||
|
||||
protected $pluginsEnabled = array('navi');
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_controlpage_with_external_link() {
|
||||
// arrange
|
||||
$controlpage = "
|
||||
* [[en:products:a:start|BasePage]]
|
||||
* [[en:products:b:d:start|2nd-level Page with hidden child]]
|
||||
* [[en:products:c:projects|hidden 3rd-level page]]
|
||||
* [[en:products:b:archive:start|2nd-level pape]]
|
||||
* [[en:products:c:start|current 2nd-level page with visible child]]
|
||||
* [[https://www.example.org|Example Page]]
|
||||
";
|
||||
saveWikiText('controlpage', $controlpage, '');
|
||||
saveWikiText('navi', '{{navi>controlpage}}', '');
|
||||
global $ID, $INFO;
|
||||
|
||||
// act
|
||||
$info = array();
|
||||
$ID = 'en:products:c:start';
|
||||
$INFO['id'] = 'en:products:c:start';
|
||||
$actualHTML = p_render('xhtml', p_get_instructions('{{navi>controlpage}}'), $info);
|
||||
// print_r($actualHTML);
|
||||
|
||||
$pq = phpQuery::newDocumentXHTML($actualHTML);
|
||||
|
||||
$actualPages = array();
|
||||
foreach ($pq->find('a') as $page) {
|
||||
$actualPages[] = $page->getAttribute('title');
|
||||
}
|
||||
|
||||
$actualLiOpen = array();
|
||||
foreach ($pq->find('li.open > div > a, li.open > div > span > a') as $page) {
|
||||
$actualLiOpen[] = $page->getAttribute('title');
|
||||
}
|
||||
|
||||
$actualLiClose = array();
|
||||
foreach ($pq->find('li.close > div > a, li.close > div > span > a') as $page) {
|
||||
$actualLiClose[] = $page->getAttribute('title');
|
||||
}
|
||||
|
||||
$this->assertEquals(array(
|
||||
0 => 'en:products:a:start',
|
||||
1 => 'en:products:b:d:start',
|
||||
2 => 'en:products:b:archive:start',
|
||||
3 => 'en:products:c:start',
|
||||
4 => 'https://www.example.org',
|
||||
), $actualPages, 'the correct pages in the correct order');
|
||||
$this->assertEquals(array(
|
||||
0 => 'en:products:a:start',
|
||||
1 => 'en:products:c:start',
|
||||
), $actualLiOpen, 'the pages which have have children and are open should have the "open" class');
|
||||
$this->assertEquals(array(
|
||||
0 => 'en:products:b:d:start',
|
||||
), $actualLiClose, 'the pages which have have children, but are closed should have the "close" class');
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
/**
|
||||
* General tests for the navi plugin
|
||||
*
|
||||
* @group plugin_navi
|
||||
* @group plugins
|
||||
*/
|
||||
class general_plugin_navi_test extends DokuWikiTest {
|
||||
|
||||
/**
|
||||
* Simple test to make sure the plugin.info.txt is in correct format
|
||||
*/
|
||||
public function test_plugininfo() {
|
||||
$file = __DIR__.'/../plugin.info.txt';
|
||||
$this->assertFileExists($file);
|
||||
|
||||
$info = confToHash($file);
|
||||
|
||||
$this->assertArrayHasKey('base', $info);
|
||||
$this->assertArrayHasKey('author', $info);
|
||||
$this->assertArrayHasKey('email', $info);
|
||||
$this->assertArrayHasKey('date', $info);
|
||||
$this->assertArrayHasKey('name', $info);
|
||||
$this->assertArrayHasKey('desc', $info);
|
||||
$this->assertArrayHasKey('url', $info);
|
||||
|
||||
$this->assertEquals('navi', $info['base']);
|
||||
$this->assertRegExp('/^https?:\/\//', $info['url']);
|
||||
$this->assertTrue(mail_isvalid($info['email']));
|
||||
$this->assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']);
|
||||
$this->assertTrue(false !== strtotime($info['date']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to ensure that every conf['...'] entry in conf/default.php has a corresponding meta['...'] entry in
|
||||
* conf/metadata.php.
|
||||
*/
|
||||
public function test_plugin_conf() {
|
||||
$conf_file = __DIR__.'/../conf/default.php';
|
||||
if (file_exists($conf_file)){
|
||||
include($conf_file);
|
||||
}
|
||||
$meta_file = __DIR__.'/../conf/metadata.php';
|
||||
if (file_exists($meta_file)) {
|
||||
include($meta_file);
|
||||
}
|
||||
|
||||
$this->assertEquals(gettype($conf), gettype($meta),'Both ' . DOKU_PLUGIN . 'navi/conf/default.php and ' . DOKU_PLUGIN . 'navi/conf/metadata.php have to exist and contain the same keys.');
|
||||
|
||||
if (gettype($conf) != 'NULL' && gettype($meta) != 'NULL') {
|
||||
foreach($conf as $key => $value) {
|
||||
$this->assertArrayHasKey($key, $meta, 'Key $meta[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'navi/conf/metadata.php');
|
||||
}
|
||||
|
||||
foreach($meta as $key => $value) {
|
||||
$this->assertArrayHasKey($key, $conf, 'Key $conf[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'navi/conf/default.php');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*Test that the levels have the right classes
|
||||
public function render_test() {
|
||||
$data = array(
|
||||
0 => '/home/michael/public_html/dokuwiki/data/pages/plugins/navi.txt',
|
||||
1 => array(
|
||||
'lvl1' => array(
|
||||
'parents' => array(),
|
||||
'page' => 'lvl1:start',
|
||||
'title' => '',
|
||||
'lvl' => 1,
|
||||
),
|
||||
'lvl2' => array(
|
||||
'parents' => Array(
|
||||
0 => 'lvl1',
|
||||
),
|
||||
'page' => 'lvl2:start',
|
||||
'title' => '',
|
||||
'lvl' => 2,
|
||||
),
|
||||
'lvl3' => array(
|
||||
'parents' => Array(
|
||||
0 => 'lvl1',
|
||||
1 => 'lvl2',
|
||||
),
|
||||
'page' => 'lvl3:start',
|
||||
'title' => '',
|
||||
'lvl' => 3,
|
||||
),
|
||||
'lvl4' => array(
|
||||
'parents' => Array(
|
||||
0 => 'lvl1',
|
||||
1 => 'lvl2',
|
||||
2 => 'lvl3',
|
||||
),
|
||||
'page' => 'lvl4:start',
|
||||
'title' => '',
|
||||
'lvl' => 4,
|
||||
),
|
||||
|
||||
),
|
||||
2 => '',
|
||||
);
|
||||
render('xhtml',$data);
|
||||
}*/
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Andreas Gohr <gohr@cosmocode.de>
|
||||
*/
|
||||
if(!defined('DOKU_INC')) die();
|
||||
|
||||
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
|
||||
require_once(DOKU_PLUGIN.'action.php');
|
||||
|
||||
/**
|
||||
* All DokuWiki plugins to extend the parser/rendering mechanism
|
||||
* need to inherit from this class
|
||||
*/
|
||||
class action_plugin_navi extends DokuWiki_Action_Plugin {
|
||||
|
||||
/**
|
||||
* plugin should use this method to register its handlers with the dokuwiki's event controller
|
||||
*/
|
||||
function register(Doku_Event_Handler $controller) {
|
||||
$controller->register_hook('PARSER_CACHE_USE','BEFORE', $this, 'handle_cache_prepare');
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare the cache object for default _useCache action
|
||||
*/
|
||||
function handle_cache_prepare(&$event, $param) {
|
||||
$cache =& $event->data;
|
||||
|
||||
// we're only interested in wiki pages
|
||||
if (!isset($cache->page)) return;
|
||||
if ($cache->mode != 'i') return;
|
||||
|
||||
// get meta data
|
||||
$depends = p_get_metadata($cache->page, 'relation naviplugin');
|
||||
if(!is_array($depends) || !count($depends)) return; // nothing to do
|
||||
$cache->depends['files'] = !empty($cache->depends['files']) ? array_merge($cache->depends['files'], $depends) : $depends;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
$conf['arrow'] = 'left';
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
$meta['arrow'] = array('multichoice','_choices' => array('left', 'right', 'none'));
|
|
@ -0,0 +1,8 @@
|
|||
base navi
|
||||
author Andreas Gohr
|
||||
email dokuwiki@cosmocode.de
|
||||
date 2016-10-12
|
||||
name Navigation Plugin
|
||||
desc Build a navigation menu from a list
|
||||
url http://www.dokuwiki.org/plugin:navi
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
jQuery(function() {
|
||||
'use strict';
|
||||
|
||||
jQuery('li.open, li.close').find('> div.li').each(function (index, element){
|
||||
var link = jQuery(element).find('a').attr('href');
|
||||
var $arrowSpan = jQuery('<span></span>').click(function (event) {
|
||||
window.location = link;
|
||||
});
|
||||
$arrowSpan.addClass('arrowUnderlay');
|
||||
jQuery(element).append($arrowSpan);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,45 @@
|
|||
#dokuwiki__aside, .sidebar_box {
|
||||
div.plugin__navi {
|
||||
span.arrowUnderlay {
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
background: no-repeat top right/100%;
|
||||
}
|
||||
|
||||
li.open {
|
||||
span.arrowUnderlay {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAAANlBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC3dmhyAAAAEXRSTlMAAQcJCgsUIDZGW2Jjmt75/Rmge4gAAABISURBVBjTY2CgJWDmwBRj4RPkxiImiC4KEuNHEwWJcbPyoYiyQLgsyKJwDpIoNiY2TUyYxnMxsAlgOISXgYGdE827PIy0CEUAdlAEbg1NcZ0AAAAASUVORK5CYII=);
|
||||
}
|
||||
}
|
||||
|
||||
li.close {
|
||||
span.arrowUnderlay {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUBAMAAAB/pwA+AAAAMFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABaPxwLAAAAD3RSTlMAAQIECiMlYWJ3psPc3v2CpcpnAAAARklEQVQIW2NgIAgUoLQBg9QVCIvjGUP8Xwcws/83A8d/sDCY6gcLg0kwHyoHEoBIgUSggiDh+VBjgMIwQZghYMB+hIF8AABJKyB+OnNcUQAAAABJRU5ErkJggg==);
|
||||
}
|
||||
}
|
||||
|
||||
&.none {
|
||||
span.arrowUnderlay {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.left {
|
||||
li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
span.arrowUnderlay {
|
||||
position: absolute;
|
||||
left: 1.3em;
|
||||
}
|
||||
}
|
||||
|
||||
&.right {
|
||||
span.arrowUnderlay {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
<?php
|
||||
/**
|
||||
* Build a navigation menu from a list
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Andreas Gohr <gohr@cosmocode.de>
|
||||
*/
|
||||
// must be run within Dokuwiki
|
||||
if(!defined('DOKU_INC')) die();
|
||||
|
||||
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
|
||||
require_once(DOKU_PLUGIN.'syntax.php');
|
||||
|
||||
class syntax_plugin_navi extends DokuWiki_Syntax_Plugin {
|
||||
|
||||
/**
|
||||
* What kind of syntax are we?
|
||||
*/
|
||||
function getType(){
|
||||
return 'substition';
|
||||
}
|
||||
|
||||
/**
|
||||
* What about paragraphs?
|
||||
*/
|
||||
function getPType(){
|
||||
return 'block';
|
||||
}
|
||||
|
||||
/**
|
||||
* Where to sort in?
|
||||
*/
|
||||
function getSort(){
|
||||
return 155;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect pattern to lexer
|
||||
*/
|
||||
function connectTo($mode) {
|
||||
$this->Lexer->addSpecialPattern('{{navi>[^}]+}}',$mode,'plugin_navi');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the match
|
||||
*/
|
||||
function handle($match, $state, $pos, Doku_Handler $handler){
|
||||
global $ID;
|
||||
|
||||
$id = substr($match,7,-2);
|
||||
list($id,$opt) = explode('?',$id,2);
|
||||
$id = cleanID($id);
|
||||
|
||||
// fetch the instructions of the control page
|
||||
$instructions = p_cached_instructions(wikiFN($id),false,$id);
|
||||
|
||||
// prepare some vars
|
||||
$max = count($instructions);
|
||||
$pre = true;
|
||||
$lvl = 0;
|
||||
$parents = array();
|
||||
$page = '';
|
||||
$cnt = 0;
|
||||
|
||||
// build a lookup table
|
||||
for($i=0; $i<$max; $i++){
|
||||
if($instructions[$i][0] == 'listu_open'){
|
||||
$pre = false;
|
||||
$lvl++;
|
||||
if($page) array_push($parents,$page);
|
||||
}elseif($instructions[$i][0] == 'listu_close'){
|
||||
$lvl--;
|
||||
array_pop($parents);
|
||||
}elseif($pre || $lvl == 0){
|
||||
unset($instructions[$i]);
|
||||
}elseif($instructions[$i][0] == 'listitem_close'){
|
||||
$cnt++;
|
||||
}elseif($instructions[$i][0] == 'internallink'){
|
||||
$foo = true;
|
||||
$page = $instructions[$i][1][0];
|
||||
resolve_pageid(getNS($ID),$page,$foo); // resolve relative to sidebar ID
|
||||
$list[$page] = array(
|
||||
'parents' => $parents,
|
||||
'page' => $page,
|
||||
'title' => $instructions[$i][1][1],
|
||||
'lvl' => $lvl
|
||||
);
|
||||
} elseif ($instructions[$i][0] == 'externallink') {
|
||||
$url = $instructions[$i][1][0];
|
||||
$list['_'.$page] = array(
|
||||
'parents' => $parents,
|
||||
'page' => $url,
|
||||
'title' => $instructions[$i][1][1],
|
||||
'lvl' => $lvl
|
||||
);
|
||||
}
|
||||
}
|
||||
return array(wikiFN($id),$list,$opt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create output
|
||||
*
|
||||
* We handle all modes (except meta) because we pass all output creation back to the parent
|
||||
*/
|
||||
function render($format, Doku_Renderer $R, $data) {
|
||||
$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
|
||||
|
||||
$path = $this->getOpenPath($data, $opt);
|
||||
$arrowLocation = $this->getConf('arrow');
|
||||
|
||||
$R->doc .= '<div class="plugin__navi ' . $arrowLocation . '">';
|
||||
$this->renderTree($data, $path, $R);
|
||||
$R->doc .= '</div>';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getOpenPath($data, $opt) {
|
||||
global $INFO;
|
||||
$openPath = array();
|
||||
if(isset($data[$INFO['id']])){
|
||||
$openPath = (array) $data[$INFO['id']]['parents']; // get the "path" of the page we're on currently
|
||||
array_push($openPath,$INFO['id']);
|
||||
}elseif($opt == 'ns'){
|
||||
$ns = $INFO['id'];
|
||||
|
||||
// traverse up for matching namespaces
|
||||
if($data) do {
|
||||
$ns = getNS($ns);
|
||||
$try = "$ns:";
|
||||
resolve_pageid('',$try,$foo);
|
||||
if(isset($data[$try])){
|
||||
// got a start page
|
||||
$openPath = (array) $data[$try]['parents'];
|
||||
array_push($openPath,$try);
|
||||
break;
|
||||
}else{
|
||||
// search for the first page matching the namespace
|
||||
foreach($data as $key => $junk){
|
||||
if(getNS($key) == $ns){
|
||||
$openPath = (array) $data[$key]['parents'];
|
||||
array_push($openPath,$key);
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}while($ns);
|
||||
}
|
||||
return $openPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param $parent
|
||||
* @param Doku_Renderer $R
|
||||
*/
|
||||
public function renderTree($data, $parent, Doku_Renderer $R) {
|
||||
// create a correctly nested list (or so I hope)
|
||||
$open = false;
|
||||
$lvl = 1;
|
||||
$R->listu_open();
|
||||
|
||||
// read if item has childs and if it is open or closed
|
||||
$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';
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($pid);
|
||||
|
||||
foreach ((array)$data as $pid => $info) {
|
||||
// only show if we are in the "path"
|
||||
if (array_diff($info['parents'], $parent)) {
|
||||
continue;
|
||||
}
|
||||
if ($upper[$pid]) {
|
||||
$menuitem = ($upper[$pid] == 'open') ? 'open' : 'close';
|
||||
} else {
|
||||
$menuitem = '';
|
||||
}
|
||||
|
||||
// skip every non readable page
|
||||
if (auth_quickaclcheck(cleanID($info['page'])) < AUTH_READ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($info['lvl'] == $lvl) {
|
||||
if ($open) {
|
||||
$R->listitem_close();
|
||||
}
|
||||
$R->listitem_open($lvl . ' ' . $menuitem);
|
||||
$open = true;
|
||||
} elseif ($lvl > $info['lvl']) {
|
||||
for ($lvl; $lvl > $info['lvl']; --$lvl) {
|
||||
$R->listitem_close();
|
||||
$R->listu_close();
|
||||
}
|
||||
$R->listitem_close();
|
||||
$R->listitem_open($lvl . ' ' . $menuitem);
|
||||
} elseif ($lvl < $info['lvl']) {
|
||||
// more than one run is bad nesting!
|
||||
for ($lvl; $lvl < $info['lvl']; ++$lvl) {
|
||||
$R->listu_open();
|
||||
$R->listitem_open($lvl + 1 . ' ' . $menuitem);
|
||||
$open = true;
|
||||
}
|
||||
}
|
||||
|
||||
$R->listcontent_open();
|
||||
if (substr($pid, 0, 1) != '_') {
|
||||
$R->internallink(':' . $info['page'], $info['title']);
|
||||
} else {
|
||||
$R->externallink($info['page'], $info['title']);
|
||||
}
|
||||
|
||||
$R->listcontent_close();
|
||||
}
|
||||
while ($lvl > 0) {
|
||||
$R->listitem_close();
|
||||
$R->listu_close();
|
||||
--$lvl;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -106,6 +106,25 @@ h1, h2, h3, h4, h5, h6,
|
|||
display: block;
|
||||
}
|
||||
|
||||
.nav .close {
|
||||
float: none;
|
||||
font-size: inherit;
|
||||
font-weight: normal;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
text-shadow: inherit;
|
||||
opacity: 1;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.nav .open {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav .open ul {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) and (max-width: 993px) {
|
||||
.bs-sidebar {
|
||||
margin-top: 50px;
|
||||
|
|
Loading…
Reference in New Issue