引言
本博客使用的handsome主题
十分美观,遗憾的是其默认情况下对多级分类的显示并不那么友好,优化的想法也是由来已久,昨日终于克服惰性写了简单实现。
先看看修改之前的样式:
简洁,但多重分类下展现并不是那么好,多重分类中父级分类显得很朴素,在侧栏中比重也相对小了,但我希望分类能够占据侧栏中的优势地位,而且加上图标也不失为一个Great idea,于是就进行简单修改了。
修改之后:
代码实现
对于小技巧、小功能的毫无保留,有助于不成熟技术的发展和微小功能的扩大化,进而不断提升自我;对低级操作的故步自封只能导致开发的停滞。——我自己
以下讨论全部以handsome模板根目录
为当前目录,Typecho环境下为usr/themes/handsome/
,特此说明。
分析aside.php
- 文件位置:
component/aside.php
- 功能:侧栏布局显示
结合开发人员工具定位到相关输出位置(第101
行至第186
行):
<?php if (!$hideHomeItem): ?>
<!--主页-->
<li>
<a href="<?php $this->options->rootUrl(); ?>/" class="auto">
<i class="iconfont icon-zhuye icon text-md"></i>
<span><?php _me("首页") ?></span>
</a>
</li>
<!-- /主页 -->
<?php endif; ?>
<?php echo @$asideItemsOutput ?>
<?php if (@!in_array('component',$this->options->asideSetting)): ?>
<li class="line dk"></li>
<!--Components-->
<li class="hidden-folded padder m-t m-b-sm text-muted text-xs">
<span><?php _me("组成") ?></span>
</li>
<!--分类category-->
<li>
<a class="auto">
<span class="pull-right text-muted">
<i class="fontello icon-fw fontello-angle-right text"></i>
<i class="fontello icon-fw fontello-angle-down text-active"></i>
</span>
<i class="glyphicon glyphicon-th"></i>
<span><?php _me("分类") ?></span>
</a>
<ul class="nav nav-sub dk">
<li class="nav-sub-header">
<a>
<span><?php _me("分类") ?></span>
</a>
</li>
<!--循环输出分类-->
<?php
$this->widget('Widget_Metas_Category_List')->to($categorys);
echo Content::returnCategories($categorys) ?>
</ul>
</li>
<!--独立页面pages-->
<li>
<a class="auto">
<span class="pull-right text-muted">
<i class="fontello icon-fw fontello-angle-right text"></i>
<i class="fontello icon-fw fontello-angle-down text-active"></i>
</span>
<i class="glyphicon glyphicon-file"></i>
<span><?php _me("页面") ?></span>
</a>
<ul class="nav nav-sub dk">
<li class="nav-sub-header">
<a data-no-instant>
<span><?php _me("页面") ?></span>
</a>
</li><!--这个字段不会被显示出来-->
<!--循环输出独立页面-->
<?php $this->widget('Widget_Contents_Page_List')->to($pages); ?>
<?php while($pages->next()): ?>
<?php if ($pages->fields->navbar == "hide") continue; ?>
<li><a href="<?php $pages->permalink(); ?>"><span><?php $pages->title(); ?></span></a></li>
<?php endwhile; ?>
</ul>
</li>
<!--友情链接-->
<li>
<a class="auto">
<span class="pull-right text-muted">
<i class="fontello icon-fw fontello-angle-right text"></i>
<i class="fontello icon-fw fontello-angle-down text-active"></i>
</span>
<i class="iconfont icon-links"></i>
<span><?php _me("友链") ?></span>
</a>
<ul class="nav nav-sub dk">
<li class="nav-sub-header">
<a data-no-instant>
<span><?php _me("友链") ?></span>
</a>
</li>
<!--使用links插件,输出全站友链-->
<?php $mypattern1 = "<li data-original-title=\"{title}\" data-toggle=\"tooltip\"
data-placement=\"top\"><a href=\"{url}\" target=\"_blank\"><span>{name}</span></a></li>";
Links_Plugin::output($mypattern1, 0, "ten");?>
</ul>
</li>
<?php endif; ?>
在这里,你可以了解侧栏的基本组成方式,以及其样式的写法。我们可以暂且记住<li class="line dk"></li>
生成分割线等特性,准备之后的修改使用。
不难发现分类结构的输出由Content::returnCategories($categorys)
方法生成,不同主题输出分类结构不一定相同,所以它不会是Typecho自带方法,猜测为libs/Content.php
所实现,不出意料。
改写returnCategories方法
- 文件位置:
libs/Content.php
- 功能:使用PHP方法输出内容
第2262
行至第2301
行:
/**
* @param $categories
* @return string
*/
public static function returnCategories($categories){
$html = "";
$options = mget();
while($categories->next()){
if ($categories->levels === 0){//父亲分类
$children = $categories->getAllChildren($categories->mid);//获取当前父分类所有子分类
//print_r($children);
//var_dump(empty($children));
if (!empty($children)){//子分类不为空
$html .= '<li><a class="auto" href="'.$categories->permalink.'"><span class="pull-right text-muted">
<i class="fontello icon-fw fontello-angle-right text"></i>
<i class="fontello icon-fw fontello-angle-down text-active"></i>
</span><span>'.$categories->name.'</span></a>';
//循环输出子分类
$childCategoryHtml = '<ul class="nav nav-sub dk child-nav">';
//有子分类判断是否输出父分类
if (!in_array('noShowParentCategory',$options->featuresetup)){
$childCategoryHtml .= '<li><a href="'.$categories->permalink.'"><b class="badge pull-right">'.$categories->count.'</b><span>'.$categories->name.'</span></a></li>';
}
foreach ($children as $mid){
$child = $categories->getCategory($mid);
$childCategoryHtml .= '<li><a href="'.$child['permalink'].'"><b class="badge pull-right">'.$child['count'].'</b><span>'.$child['name'].'</span></a></li>';
}
$childCategoryHtml .= '</ul>';
$html .= $childCategoryHtml;
$html .= "</li>";
}else{//没有子分类
$html .= '<li><a href="'.$categories->permalink.'"><b class="badge pull-right">'.$categories->count.'</b><span>'.$categories->name.'</span></a></li>';
}
}
}
return $html;
}
作者的逻辑比较清晰,Modify起来可以省很多事。
先捡软柿子捏,首先,第2281
行删除其child-nav
样式,将子项目显示等级提高(否则左侧会有不协调的空白);然后,参考aside.php
中了解到的样式写法,检查该方法的返回数据。非常幸运,这些数据已经可以直接作为一级侧栏列表项使用了,并不需要结构上的修改。
下面就是比较难以描述的自定义图标实现了。
我的思路是定义一个$icons
索引数组,将分类的slug
(英文名称)作为索引,结合本博客实际情况,如下:
$icons = array(
//$slug => 'icon',
'algorithm-oi' => 'iconfont icon-kinds',
'project-share' => 'fa fa-tasks',
'acgn' => 'fa fa-gift',
'words' => 'fa fa-heartbeat',
'files' => 'fa fa-folder',
);
写好了图标映射表,下一步就是将它插入到返回的分类数据中去。图标我们一般使用<i class="xxx"></i>
来实现。插入的过程不好描述,贴出代码,请自行领悟:
/**
* @param $categories
* @return string
*/
public static function returnCategories($categories){
$html = "";
$options = mget();
$icons = array(
//$slug => 'icon',
'algorithm-oi' => 'iconfont icon-kinds',
'project-share' => 'fa fa-tasks',
'acgn' => 'fa fa-gift',
'words' => 'fa fa-heartbeat',
'files' => 'fa fa-folder',
);
while($categories->next()){
if ($categories->levels === 0){//父亲分类
$children = $categories->getAllChildren($categories->mid);//获取当前父分类所有子分类
//print_r($children);
//var_dump(empty($children));
if (!empty($children)){//子分类不为空
$html .= '<li><a class="auto" href="'.$categories->permalink.'"><span class="pull-right text-muted">
<i class="fontello icon-fw fontello-angle-right text"></i>
<i class="fontello icon-fw fontello-angle-down text-active"></i>
</span><i class="'.$icons[$categories->slug].'"></i><span>'.$categories->name.'</span></a>';//* 这里
//循环输出子分类
$childCategoryHtml = '<ul class="nav nav-sub dk">
<li class="nav-sub-header">
<a>
<span>'.$categories->name.'</span>
</a>
</li>';
//有子分类判断是否输出父分类
if (!in_array('noShowParentCategory',$options->featuresetup)){
$childCategoryHtml .= '<li><a href="'.$categories->permalink.'"><b class="badge pull-right">'.$categories->count.'</b><i class="'.$icons[$categories->slug].'"></i><span>'.$categories->name.'</span></a></li>';//* 这里
}
foreach ($children as $mid){
$child = $categories->getCategory($mid);
$childCategoryHtml .= '<li><a href="'.$child['permalink'].'"><b class="badge pull-right">'.$child['count'].'</b><i class="'.$icons[$child['slug']].'"></i><span>'.$child['name'].'</span></a></li>';//* 这里
}
$childCategoryHtml .= '</ul>';
$html .= $childCategoryHtml;
$html .= "</li>";
}else{//没有子分类
$html .= '<li><a href="'.$categories->permalink.'"><b class="badge pull-right">'.$categories->count.'</b><i class="'.$icons[$categories->slug].'"></i><span>'.$categories->name.'</span></a></li>';//* 这里
}
}
}
return $html;
}
上述代码中插入图标元素的位置均已使用//* 这里
标示。
至此,关于难啃的硬骨头Content.php
中returnCategories
方法的修改已经全部完成。
修改aside.php
- 文件位置及功能参考“分析aside.php”中叙述。
原始代码不再贴出,稍作讲解后将贴出修改后代码。
刚刚已经提到,returnCategories
方法的返回值现在已经可以直接作为一级列表项使用,于是删除外层套着的<li>
元素,并在适当位置添加分割线(还记得吗,分析时已经看到的)即可。
对于页面项目的修改同理可以完成,不再赘述。
这里介绍一个小技巧,在后台编辑页面的“自定义字段”中,新增一条名为navbar
的字段,将其值设置为hide
,即可在侧栏中隐藏该页面。
<?php if (!$hideHomeItem): ?>
<!--主页-->
<li>
<a href="<?php $this->options->rootUrl(); ?>/" class="auto">
<i class="iconfont icon-zhuye icon text-md"></i>
<span><?php _me("首页") ?></span>
</a>
</li>
<!-- /主页 -->
<?php endif; ?>
<?php echo @$asideItemsOutput ?>
<?php if (@!in_array('component',$this->options->asideSetting)): ?>
<li class="line dk"></li>
<!--Components-->
<li class="hidden-folded padder m-t m-b-sm text-muted text-xs">
<span><?php _me("分类") ?></span>
</li>
<!--分类category-->
<!--循环输出分类-->
<?php
$this->widget('Widget_Metas_Category_List')->to($categorys);
echo Content::returnCategories($categorys) ?>
<li class="line dk"></li>
<!--独立页面pages-->
<li class="hidden-folded padder m-t m-b-sm text-muted text-xs">
<span><?php _me("页面") ?></span>
</li>
<!--循环输出独立页面-->
<?php
$icons = array(
//$slug => 'icon',
'articles' => 'fa fa-archive',
'board' => 'fa fa-commenting',
'cross' => 'fa fa-coffee',
);
?>
<?php $this->widget('Widget_Contents_Page_List')->to($pages); ?>
<?php while($pages->next()): ?>
<?php if ($pages->fields->navbar == "hide") continue; ?>
<li><a href="<?php $pages->permalink(); ?>"><i class="<?php _me($icons[$pages->slug]); ?>"></i><span><?php $pages->title(); ?></span></a></li>
<?php endwhile; ?>
<!--友情链接-->
<li>
<a class="auto">
<span class="pull-right text-muted">
<i class="fontello icon-fw fontello-angle-right text"></i>
<i class="fontello icon-fw fontello-angle-down text-active"></i>
</span>
<i class="iconfont icon-links"></i>
<span><?php _me("友情链接") ?></span>
</a>
<ul class="nav nav-sub dk">
<li class="nav-sub-header">
<a data-no-instant>
<span><?php _me("友情链接") ?></span>
</a>
</li>
<li><a href="/links.html"><span>总览</span></a></li>
<!--使用links插件,输出全站友链-->
<?php $mypattern1 = "<li data-original-title=\"{title}\" data-toggle=\"tooltip\"
data-placement=\"top\"><a href=\"{url}\" target=\"_blank\"><span>{name}</span></a></li>";
Links_Plugin::output($mypattern1, 0, "ten");?>
</ul>
</li>
<?php endif; ?>
由于我比较懒,在输出总览时直接输出了永久链接,而没有动态获取,需要注意。
部署后即可实现目标效果。
更新指导
Update on 2019-07-22
已更新至handsome 5.2.0
,上述内容基本适用,但行号稍有偏差,请联系具体代码上下文确定新版本文件应修改的位置。
Update on 2020-05-10
对于 handsome 6.x
以及后续不再提供“不输出父分类”选项的版本,使用以下代码:
/**
* @param $categories
* @return string
*/
public static function returnCategories($categories){
$html = "";
$options = mget();
$icons = array(
//$slug => 'icon',
'algorithm-oi' => 'iconfont icon-kinds',
'project-share' => 'fa fa-tasks',
'acgn' => 'fa fa-gift',
'words' => 'fa fa-heartbeat',
'files' => 'fa fa-folder',
);
while($categories->next()){
if ($categories->levels === 0){//父亲分类
$children = $categories->getAllChildren($categories->mid);//获取当前父分类所有子分类
//print_r($children);
//var_dump(empty($children));
if (!empty($children)){//子分类不为空
$html .= '<li><a class="auto" href="'.$categories->permalink.'"><span class="pull-right text-muted">
<i class="fontello icon-fw fontello-angle-right text"></i>
<i class="fontello icon-fw fontello-angle-down text-active"></i>
</span><i class="'.$icons[$categories->slug].'"></i><span>'.$categories->name.'</span></a>';//* 这里
//循环输出子分类
$childCategoryHtml = '<ul class="nav nav-sub dk">
<li class="nav-sub-header">
<a>
<span>'.$categories->name.'</span>
</a>
</li>';
foreach ($children as $mid){
$child = $categories->getCategory($mid);
$childCategoryHtml .= '<li><a href="'.$child['permalink'].'"><b class="badge pull-right">'.$child['count'].'</b><i class="'.$icons[$child['slug']].'"></i><span>'.$child['name'].'</span></a></li>';//* 这里
}
$childCategoryHtml .= '</ul>';
$html .= $childCategoryHtml;
$html .= "</li>";
}else{//没有子分类
$html .= '<li><a href="'.$categories->permalink.'"><b class="badge pull-right">'.$categories->count.'</b><i class="'.$icons[$categories->slug].'"></i><span>'.$categories->name.'</span></a></li>';//* 这里
}
}
}
return $html;
}
版权声明:本文是原创文章,版权归 无限UCW 所有。
本文链接:https://ucw.moe/archives/handsome-aside-category.html
本站所有原创文章采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
您可以自由地转载和修改,但请务必注明文章来源并且不可用于商业目的。
dalao请问可以更新下教程吗,新版本照着做无法实现嘞
博主能更新一下吗,支持一下最新的9.2版本
大佬你好,请问怎么让页脚底部的信息可以延长到这个右侧栏呢,我只能显示在中间
我用 Devtools 检查了你的 blog,
#footer
这个元素(它是<footer id="footer" ...>
这个东西)有一个margin-right: 240px
的样式,把这个margin-right
调小就可以了。我将/usr/themes/handsome/component/footer.php里的<footer id="footer" class="app-footer" role="footer">,约117行,改为<footer id="footer" class="app-footer" role="footer" style="margin-right: 0px;">后还是不行,可能是什么原因呢
你的修改方法应该是有效的,建议仔细检查数据链路,确保前台 Devtools 中查看到的样式正确生效。
好的,谢谢大佬,我再去试试
Hi,友链一个可以吗?
博客名称:乔戈路阔阔;
博客网址:https://chelgr.com;
博客头像:https://chelgr.com/share/chelgr-com-icon.png;
博客介绍:缅怀过去 | 记录现在 | 心存未来...
博主,我想请教一下几个问题
1.如何实现这个主题的左右侧边栏比原生主题窄了一点/导航文字也是;
2.还有就是如何添加像你网站盒子里面的框线,例如右边栏,页头,面包屑,博客信息等等位置
3.然后就是在手机自适应页面下,右上角是个setting的icon,是怎么弄的呢?
请问这些是怎么设置的呢?主题后台无法直接实现!
不好意思,这个具体我也记不太清了 ,有些可能是旧版本 handsome 的特性(我很久没有仔细维护 Blog 了),有些可能是无意中改的。一般这种主题后台无法直接改的东西,需要修改源码实现更高度的客制化,但我印象中后续版本的 handsome 引入源代码混淆加密使得这个操作可能不太轻松。我知道的就只有这些了,很遗憾提供不了什么帮助……
感激你的回复!你的回答至少也让我清楚了一些关于主题版本有可能造成的差别!要在茫茫博主中得到诚心的回复也不容易!所以你的回复已经对我很nice了!谢谢!我会继续学习的,也会在以后耐心指导别人,倘若遇到比我还新的人!哈哈... 感恩!好人
前端
后端
然后偷偷在后台魔改个自定义设置区域
是不是就能随便改了
兄嘚,苦思,但难耐学识有限。我看了你的博客“https://gamesme.cn/”, 终于找到了我想要的侧边栏,也看过许多资料,但是如果自己动手的话,真的不知道怎么下。希望,看到如果你看到此留言能够分享一下你的操作经验(*❦ω❦)。(群里没人会,但有很多人问。)
兄弟你在哪个群啊 我在群里没看到你 我所在群号 553158260
搞定了,哎呀,痛苦的过程 ̄﹃ ̄
其实你魔改出自定义设置区域以后就没必要再传参了,写在配置里面(可以考虑插件)然后手改
returnCategories
方法让它自动获取出来可能会舒服一点对√
不过我比较懒就没写
轮子偷走了
欢迎指点
博主用的是哪一款的代码高亮鸭,蛮喜欢的
手改的……不过不是我改的……
https://moe.best/ 参考这位大佬Orz
博主我很喜欢你这个侧边栏,能直接伸手1比1拿走吗OωO,我又菜又懒耶
上面就是全部文件了……OωO
这个操作定制化比较强,我即使把我改过的代码发给你,也是不会显示图标的,而你按照我上面所叙述的方式进行修改也可以得到相同的效果,改掉
$icons
数组就可以实现图标了。