纯PHP或CSS -树菜单只显示活动节点


pure php or css - tree menu show only active nodes

我在PHP中建立了一个树菜单,使用递归函数,它工作正常。我的菜单结构是这样的:


——Categ1
——Categ11
——Categ111
——Categ112
——Categ12
——Categ121
——Categ122
——Categ2
——Categ3
——Categ4

我正在使用bootstrap。

我只需要显示活动节点和顶层子节点。对于我的例子,我需要菜单像这样打开(我点击了类别112和类别12的子类别隐藏):

——Categ1
——Categ11
——Categ111
——Categ112
——Categ12
——Categ2
——Categ3
——Categ4

生成我的菜单树的php函数是:
/** show all subcategs of the selected category
 * @param $iCategIDSelected
 * @param null $arrCategs
 * @param bool $bIsOnTheLeaf
 * @return string
 */
static function getHTMLCategsForMenuBySelected($iCategIDSelected, $arrCategs=null, $arrAllParents=null){
    $bIsVisible = false;
    if($arrCategs == null){
        $oController = new ShopcategoriesController();
        $arrCategs = $oController->getShopCategories(0);
    }
    //find if we make the current node visible or not
    //if the current node id is on the parent's of the selected node then make it visible
    //take all nodes starting with root until the selected node
    if($arrAllParents==null){
        $arrAllParents = ShopcategoriesController::getParentsBySelectedCategID($iCategIDSelected,$arrCategs);
    }

    $sHTML = '<ul class="nav nav-pills nav-stacked">';
    foreach($arrCategs as $oneCateg){
        //find if is active or not
        $bActiveClass = '';
        if(in_array($oneCateg['id'],$arrAllParents)){$bActiveClass = 'active';}
        $sHTML .= '<li class="'.$bActiveClass.'">';
        $sHTML .= '<a href="'.URL::to('showcategory/'.$oneCateg['id']).'" class="list-group-item">'.ucfirst($oneCateg['name']).'</a>';
        if(count($oneCateg['subCategories'])>0){
            $sHTML .= ShopcategoriesController::getHTMLCategsForMenuBySelected($iCategIDSelected, $oneCateg['subCategories'],$arrAllParents);
            $sHTML .= '</li>';
        }else{
            $sHTML .= '';
        }
    }
    $sHTML .= '</ul>';
    return $sHTML;
}

html结构为:

ul.nav > li > a{
    padding-left: 30px;
}
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<div id="menuCateg">
	<ul class="nav nav-pills nav-stacked">
		<li class="active">
			<a class="list-group-item" href="http://localhost:8000/showcategory/1">Categ1</a>
			<ul class="nav nav-pills nav-stacked">
				<li class="active">
					<a class="list-group-item" href="http://localhost:8000/showcategory/2">Categ11 </a>
					<ul class="nav nav-pills nav-stacked">
						<li class=""><a class="list-group-item" href="http://localhost:8000/showcategory/3">Categ111</a></li>
						<li class="active"><a class="list-group-item" href="http://localhost:8000/showcategory/4">Categ112</a></li>
					</ul>
				</li>
				<li class=""><a class="list-group-item" href="http://localhost:8000/showcategory/18">Categ12</a></li>
			</ul>
		</li>
		<li class="">
          <a class="list-group-item" href="http://localhost:8000/showcategory/6">Categ2</a>
          <ul class="nav nav-pills nav-stacked">
			<li class=""><a class="list-group-item" href="http://localhost:8000/showcategory/3">Categ121</a></li>
			<li class=""><a class="list-group-item" href="http://localhost:8000/showcategory/4">Categ122</a></li>
		  </ul>
      </li>
		<li class=""><a class="list-group-item" href="http://localhost:8000/showcategory/8">Categ3</a>
		<li class=""><a class="list-group-item" href="http://localhost:8000/showcategory/8">Categ4</a>
	</ul>
    </div>

我找到了解决方案,以便生成具有多级子类别的菜单树,并仅显示已选择的级别(不包括树中的所有子级别)。

诀窍是:

 if( //if the current subcateg parentid is on the parent that must be active then show his children's otherwise do not
                ( in_array($oneCateg['parentid'],$arrAllParents)  && in_array($oneCateg['id'],$arrAllParents))
            )

谢谢你的帮助!

/** show all subcategs of the selected category
 * @param $iCategIDSelected
 * @param null $arrCategs
 * @param bool $bIsOnTheLeaf
 * @return string
 */
static function getHTMLCategsForMenuBySelected($iCategIDSelected, $arrCategs=null, $arrAllParents=null, $iLevel=0){
    $bIsVisible = false;
    if($arrCategs == null){
        $oController = new ShopcategoriesController();
        $arrCategs = $oController->getShopCategories(0);
    }
    //find if we make the current node visible or not
    //if the current node id is on the parent's of the selected node then make it visible
    //take all nodes starting with root until the selected node
    if($arrAllParents==null){
        $arrAllParents = ShopcategoriesController::getParentsBySelectedCategID($iCategIDSelected,$arrCategs);
        $arrAllParents[]=0;
    }
    $iLevel++;
    $sHTML = '<ul class="nav nav-pills nav-stacked level_'.$iLevel.'">';
    foreach($arrCategs as $oneCateg){
        //find if is active or not
        $bActiveClass = '';
        if(in_array($oneCateg['id'],$arrAllParents)){$bActiveClass = 'active';}
        $sHTML .= '<li class="'.$bActiveClass.'">';
        $sHTML .= '<a href="'.URL::to('showcategory/'.$oneCateg['id']).'" class="list-group-item">'.ucfirst($oneCateg['name']).'</a>';
        if(count($oneCateg['subCategories'])>0){
            if( //if the current subcateg parentid is on the parent that must be active then show his children's otherwise do not
                ( in_array($oneCateg['parentid'],$arrAllParents)  && in_array($oneCateg['id'],$arrAllParents))
            ) {
                $sHTML .= ShopcategoriesController::getHTMLCategsForMenuBySelected($iCategIDSelected, $oneCateg['subCategories'], $arrAllParents, $iLevel);
                $sHTML .= '</li>';
            }
        }else{
            $sHTML .= '';
        }
    }
    $sHTML .= '</ul>';
    return $sHTML;
}

你应该添加一个类,当它不活动,如.not-active

.not-active{ 
   display: none;
}

编辑

我不确定是否正确理解了你的观点,但这样说吧:

foreach($arrCategs as $oneCateg){
        //find if is active or not
        $bActiveClass = '';
        if(in_array($oneCateg['id'],$arrAllParents)){ //modified
           $bActiveClass = 'active';
        }else{
           $bActiveClass = 'not-active';
        }
        $sHTML .= '<li class="'.$bActiveClass.'">';
        $sHTML .= '<a href="'.URL::to('showcategory/'.$oneCateg['id']).'" class="list-group-item">'.ucfirst($oneCateg['name']).'</a>';
        if(count($oneCateg['subCategories'])>0){
            $sHTML .= ShopcategoriesController::getHTMLCategsForMenuBySelected($iCategIDSelected, $oneCateg['subCategories'],$arrAllParents);
            $sHTML .= '</li>';
        }else{
            $sHTML .= '';
        }
    }