首页
友链
导航
影视
壁纸
统计
留言板
Search
1
el-upload自定义触发按钮及触发上传前判断
826 阅读
2
vue配置二级目录以及nginx多网站部署
698 阅读
3
el-cascader选择任意一级搭配懒加载使用,单选框radio不会触发懒加载
574 阅读
4
joe主题自定义导航页面
502 阅读
5
js获取昨天今天明天日期
471 阅读
web前端
vue
react
javascript
nuxt
typescript
indexDB数据库
微信小程序
美文欣赏
心情随笔
技术分享
其他
PHP
nodejs
博客api实战项目
typecho
登录
Search
标签搜索
web
vue
node项目实战
js
javascript
typecho
css
vuex
router
nginx
git
element
joe
utils
leaflet
dateFormat
map
date
axios
reg
辰漪
累计撰写
66
篇文章
累计收到
122
条评论
首页
栏目
web前端
vue
react
javascript
nuxt
typescript
indexDB数据库
微信小程序
美文欣赏
心情随笔
技术分享
其他
PHP
nodejs
博客api实战项目
typecho
页面
友链
导航
影视
壁纸
统计
留言板
搜索到
2
篇与
joe
的结果
2022-09-11
joe主题自定义导航页面
joe自定义导航模板{callout color="#f0ad4e"}背景: 就想要一个导航页面,用来存放自己的常用链接网站,方便自己使用目标: 可以在后台设置导航的链接,导航页面响应式,支持设置网站名称、网站链接、图标注意:themeUrl('cyThemeBin/assets/js/clipboard.min.js') 类似的静态资源文件,需要替换成自己原来的{/callout}后台设置页面:前台展示页面:创建导航模板在joe主题下创建mynav.php文件文件存放目录:Typecho-joe\usr\themes\default<?php /** * 导航 * * @package custom * **/ ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <?php $this->need('public/include.php'); ?> <?php if ($this->options->JPrismTheme) : ?> <link rel="stylesheet" href="<?php $this->options->JPrismTheme() ?>"> <?php else : ?> <!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.23.0/themes/prism.min.css"> --> <link rel="stylesheet" href="<?php $this->options->themeUrl('cyThemeBin/assets/css/prism.min.css'); ?>"> <?php endif; ?> <!-- <script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.6/dist/clipboard.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/typecho-joe-next@6.2.4/plugin/prism/prism.min.js"></script> --> <script src="<?php $this->options->themeUrl('cyThemeBin/assets/js/clipboard.min.js'); ?>"></script> <script src="<?php $this->options->themeUrl('cyThemeBin/assets/js/prism.min.js'); ?>"></script> <script src="<?php $this->options->themeUrl('cyThemeBin/assets/js/joe.post_page.min.js?v=20210525'); ?>"></script> <style> .nav-clist { display: flex; flex-wrap: wrap; } .nav-clist .nav-citem { position: relative; top: 0; background: #f2f2f2; margin-bottom: 10px; border-radius: 5px; transition: 0.3s; } .nav-clist .nav-citem:hover { box-shadow: 0px 0px 5px rgba(0,0,0,0.5); top: -8px; } .nav-clist .nav-citem:hover a { color: var(--theme); } .nav-clist .nav-citem:hover a .right_icon { filter: drop-shadow(var(--theme) 25px 0); } .nav-clist .nav-citem a { color: #252525; padding: 10px 5px; display: flex; align-items: center; } .nav-clist .nav-citem a img { width: 25px; height: 25px; vertical-align: middle; } .nav-clist .nav-citem a span { flex: 0.9; } .nav-clist .nav-citem a .nav-icon { margin-right: 8px; } .nav-citem .r_icon_box { overflow: hidden; } .nav-clist .nav-citem a .right_icon { position: relative; left: -24px; filter: drop-shadow(#ccc 25px 0); } @media screen and (min-width: 1201px) { .nav-clist .nav-citem { width: 24%; margin-right: 1%; } } @media screen and (max-width: 1200px) { .nav-clist .nav-citem { width: 32%; margin-right: 1.3%; } } @media screen and (max-width: 768px) { .nav-clist .nav-citem { width: 100%; } } </style> </head> <body> <div id="Joe"> <?php $this->need('public/header.php'); ?> <div class="joe_container"> <div class="joe_main"> <div class="joe_detail" data-cid="<?php echo $this->cid ?>"> <?php $this->need('public/batten.php'); ?> <?php $this->need('public/article.php'); ?> <?php $JFnav_str = $this->options->JFnav; $JFnav_arr = json_decode($JFnav_str, true); ?> <?php foreach($JFnav_arr as $t => $v) : ?> <div class="joe_detail__article nav-title"> <h3><?php echo $t ?></h3> </div> <div class="nav-clist"> <?php foreach($v as $a => $item) : ?> <div class="nav-citem"> <a href="<?php echo trim($item['url'])?>" target="_blank"> <img class="nav-icon" src="<?php echo trim($item['icon'])?>" alt=""> <span><?php echo trim($item['name'])?></span> <div class="r_icon_box"> <img class="right_icon" src="<?php $this->options->themeUrl('cyThemeBin/assets/img/right_icon.svg') ?>" alt=""> </div> </a> </div> <?php endforeach; ?> </div> <?php endforeach; ?> <?php $this->need('public/handle.php'); ?> <?php $this->need('public/copyright.php'); ?> </div> <?php $this->need('public/comment.php'); ?> </div> <?php $this->need('public/aside.php'); ?> </div> <?php $this->need('public/footer.php'); ?> </div> </body> <script> // console.log($, 'jquery'); </script> </html> 修改functions.php文件文件目录:Typecho-joe\usr\themes\default\functions.php在适当位置新增以下代码,此时后台即可设置导航链接$JFnav = new Typecho_Widget_Helper_Form_Element_Textarea( 'JFnav', NULL, '{"视频直播": [{"name": "腾讯视频", "url": "https://v.qq.com", "icon": ""}]}', '个人导航(非必填)', '介绍:用于填写导航链接 <br /> 注意:需要先添加导航页面(新增独立页面-右侧模板选择友链),该项才会生效 <br /> 格式:{"视频直播": [{"name": "腾讯视频", "url": "https://v.qq.com", "icon": ""}]}<br /> 其他:JSON对象的形式添加' ); $JFnav->setAttribute('class', 'joe_content joe_other'); $form->addInput($JFnav);新建页面选择模板即可新建导航页面,设置页面路径选择自定义模板,选择自己创建的导航模板发布即可生效{callout color="#f0ad4e"}内容以支持移动端响应式,样式啥的可以根据自己的喜好进行修改调整{/callout}注:本文原创,转载请附带本文链接,非常感谢!
2022年09月11日
502 阅读
26 评论
4 点赞
2022-09-11
typecho自定义文章目录侧边栏
joe文章目录侧边栏{callout color="#f0ad4e"}背景: joe主题没有目录功能,想要目标:能自动创建文章目录,支持显示H1-H3共3级标题;标题和目录可以联动{/callout}效果如图:实现代码修改php文件需要修改的文件: /usr/themes/Joe/public/aside.php在 aside.php 的合适位置增加如下代码,用于在侧边栏创建目录容器# 仅在文章和页面生效 <?php if (($this->is('post') || $this->is('page')) : ?> <section class="joe_aside__item catalogue"> <div class="joe_aside__item-title"> <svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2084" width="18" height="18"><path d="M640 192H224c-17.7 0-32-14.3-32-32s14.3-32 32-32h416c17.7 0 32 14.3 32 32s-14.3 32-32 32zM960 544H224c-17.7 0-32-14.3-32-32s14.3-32 32-32h736c17.7 0 32 14.3 32 32s-14.3 32-32 32zM640 896H224c-17.7 0-32-14.3-32-32s14.3-32 32-32h416c17.7 0 32 14.3 32 32s-14.3 32-32 32zM96 192H64c-17.7 0-32-14.3-32-32s14.3-32 32-32h32c17.7 0 32 14.3 32 32s-14.3 32-32 32zM96 544H64c-17.7 0-32-14.3-32-32s14.3-32 32-32h32c17.7 0 32 14.3 32 32s-14.3 32-32 32zM96 896H64c-17.7 0-32-14.3-32-32s14.3-32 32-32h32c17.7 0 32 14.3 32 32s-14.3 32-32 32z" p-id="2085"></path></svg> <span class="text">目录</span> <span class="line"></span> </div> <div class="joe_aside__item-contain"> <ul class="catalogue-items"> </ul> </div> </section> <?php endif; ?>增加js代码下面的js可以直接在Joe主题的设置中添加位置: 控制台->外观->设置外观->全局设置->自定义jsfunction get_catalogs(article_content) { const titleTag = ["H1", "H2", "H3"]; let titles = []; article_content.childNodes.forEach((e, index) => { const id = "header-" + index; if(titleTag.includes(e.nodeName)){ titles.push({ id: id, text: e.textContent, level: Number(e.nodeName.substring(1, 2)) }); e.setAttribute("id", id); } }); return titles; } // 找到目录容器 article_content = document.querySelector('.joe_detail__article'); if (article_content) { var catalog = get_catalogs(article_content); if (catalog.length == 0) { // 无目录,隐藏 $('.catalogue').hide(); } else { let catalogue = ''; for (let i = 0; i < catalog.length; i++) { let node = '<li class="catalogue-item"><a href="javascript:;" id="to-' + catalog[i].id + '" to="' + catalog[i].id + '" title="' + catalog[i].text + '">' + catalog[i].text + '</a>'; if (i == catalog.length - 1) { catalogue += node + '</li>' } else { if (catalog[i + 1].level == catalog[i].level) { catalogue += node + '</li>'; } else if (catalog[i + 1].level > catalog[i].level) { catalogue += (catalog[i + 1].level > 1) ? node + '<ul class="level-' + catalog[i + 1].level + '">' : node + '</li>'; } else { if (catalog[i + 1].level - catalog[i].level == -2) { catalogue += i > 1 ? node + '</li></ul></li></ul></li>' : node + '</li></ul></li>'; } else { catalogue += i > 1 ? node + '</li></ul></li>' : node + '</li>'; } } } } document.querySelector('.catalogue-items').innerHTML = catalogue; $('.catalogue-item > a').on('mouseenter', function () { $(this).parent().addClass('_active'); }); $('.catalogue-item > a').on('mouseleave', function () { $(this).parent().removeClass('_active'); }); // 根据目录定位到标题 $('.catalogue-item > a').on('click', function () { document.removeEventListener("scroll", autoActive); $('.catalogue-item').removeClass('active'); $(this).parent().addClass('active'); let aim = document.querySelector('#' + $(this).attr('to')); let aim_top = aim.offsetTop; let aim_h = aim.clientHeight; let above_h = document.querySelector('.joe_header__above').clientHeight; let below_h = document.querySelector('.joe_header__below').clientHeight; let offset = 0; let case1 = !document.querySelector('.joe_header__above').className.includes('active'); let case2 = document.getElementsByTagName("html")[0].scrollTop + above_h > aim_top; if (case1 && case2) { offset = above_h; } window.scrollTo({ top: aim_top - offset - below_h - 10, behavior: 'smooth' }); setTimeout(() => { document.addEventListener("scroll", autoActive); }, 500); }); if (catalog.length) $('.catalogue-item').eq(0).addClass('active'); // 目录侧标题自动定位 let autoActive = function () { let html_top = document.getElementsByTagName("html")[0].scrollTop; //获得父级卷去的高度 for (let i = 0; i < catalog.length; i++) { let offset = 0; let h_id = '#' + catalog[i].id; let h_offset = document.querySelector(h_id).offsetTop; let above_h = document.querySelector('.joe_header__above').clientHeight; let below_h = document.querySelector('.joe_header__below').clientHeight; if (!document.querySelector('.joe_header').className.includes('active')) offset = above_h; if (h_offset + below_h + offset + 10 >= html_top) { $('.catalogue-item').removeClass('active'); if (i > 0 && i < catalog.length - 1 && document.querySelector('#' + catalog[i].id).offsetTop > html_top + window.innerHeight * 0.2) { //还没到下一个标题 i--; } $('#to-' + catalog[i].id).parent().addClass('active'); break; } } }; document.addEventListener("scroll", autoActive); } } else { // 不是文章,隐藏目录 $('.catalogue').hide(); }css样式表样式表同js,也可以在Joe主题的设置中添加位置: 控制台->外观->设置外观->全局设置->自定义css 以下样式表是我自己博客使用的,仅供参考.joe_aside__item.catalogue { z-index: 999; position: sticky; top: 45px; margin-bottom: 15px; transition: top 0.35s; background: var(--background) } .joe_aside__item.catalogue .joe_aside__item-contain { padding: 0; margin: 0; margin-left: 10px } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items { border-left: 1px solid var(--classC); border-bottom: 1px solid var(--background); padding: 15px } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item { margin: 0; padding: 0; line-height: 26px; font-size: 16px } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item a { position: relative; display: block; line-height: 26px; color: var(--main); transition: color 0.5s } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item a: hover { color: var(--theme) } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item._active>a, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item.active>a { color: var(--theme) } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item._active>a::before, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item.active>a::before { content: ""; position: absolute; left: -17px; top: 0; width: 2px; height: 26px; background-color: var(--theme); transition: height 0.35s } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-2.catalogue-item, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-3 .catalogue-item { font-size: 14px } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-2 .catalogue-item._active>a::before, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-2 .catalogue-item.active>a::before, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-3 .catalogue-item._active>a::before, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-3 .catalogue-item.active>a::before { left: -34px } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-2 .catalogue-item .level-3 .catalogue-item, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-3 .catalogue-item .level-3 .catalogue-item { font-size: 12px } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-2 .catalogue-item .level-3 .catalogue-item._active>a::before, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-2 .catalogue-item .level-3 .catalogue-item.active>a::before, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-3 .catalogue-item .level-3 .catalogue-item._active>a::before, .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-3 .catalogue-item .level-3 .catalogue-item.active>a::before { left: -51px } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item .level-3 .catalogue-item { font-size: 12px } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items .catalogue-item ul { padding-left: 17px } .joe_aside__item.catalogue .joe_aside__item-contain .catalogue-items ul { display: block; list-style-type: disc }二次修改 js代码{callout color="#f0ad4e"}由于上述js和本博客有些出入,在原基础上进行改变,目录从 H2-H6 样式的话,只做到level-3,所以目前支持是 H2-H4解决二次点击目录定位错误问题解决目录生成混乱问题{/callout}js代码// 自定义文章目录侧边栏-start function get_catalogs(article_content) { const titleTag = ["H2", "H3", "H4"]; let titles = []; article_content.childNodes.forEach((e, index) => { const id = "header-" + index; if(titleTag.includes(e.nodeName)){ titles.push({ id: id, text: e.textContent, level: Number(e.nodeName.substring(1, 2) - 1) }); e.setAttribute("id", id); } }); return titles; } // 找到目录容器 article_content = document.querySelector('.joe_detail__article'); if (article_content) { var catalog = get_catalogs(article_content); console.log(catalog, '标题级别'); if (catalog.length == 0) { // 无目录,隐藏 $('.catalogue').hide(); } else { const arr = [] function getLv1(catalog, index, arr, lv, lv1Item) { // 获取一级菜单 // console.log(arr, '传递的arr / itemchildren”'); const newArr = JSON.parse(JSON.stringify(catalog)).slice(index) // 从哪个位置开始遍历 // console.log(newArr, '索引位置截取'); if (newArr.length === 0) return // console.log(lv1Item, '一级'); // for循环可以进行 打破 终结循环 for(let i = 0; i < newArr.length; i++) { newArr[i].children = [] if (newArr[i].level === lv) { // 拿到对应等级的 放到一起 newArr[i].el = ` <li class="catalogue-item"> <a href="javascript:;" id="to-${ newArr[i].id }" to="${ newArr[i].id }" title="${ newArr[i].text }" > ${ newArr[i].text } </a> <ul class="level-${lv+1}"> cy_oo${newArr[i].id + i} </ul> </li> ` newArr[i].replaceName = 'cy_oo' + newArr[i].id + i arr.push(newArr[i]) // console.log(newArr[i], '当前item'); } // console.log(arr, '123456'); // if (item.level !== 1 && item.level < catalog[i - 1].level) lv1.push(item) // newArr[i + 1].level < newArr[i].level // 没有下一个了 if(!newArr[i + 1]) return // if (newArr[i + 1].level < newArr[i].level) continue // 下个级别 = 1 遇到级别 为1 停止遍历 if (((newArr[i + 1].level === 1 || newArr[i + 1].level < lv) && lv !== 1)) return // if (newArr[i].text === '示例') { // console.log(newArr[i], '当前item1111'); // console.log(newArr[i], '上一个item1111'); // console.log(newArr[i + 1], '下一个item'); // } // 从 索引 + 1 位置循环 // 判断下一级 是否大于 当前级别 if(newArr[i + 1].level > newArr[i].level) { // console.log(i + 1, '下一级别索引'); // console.log(item, '当前item'); // console.log(item.children, '当前children', catalog[i + 1].level, '下一级级别'); let lv1ItemEl = lv1Item if (lv === 1) { lv1ItemEl = newArr[i] } getLv1(newArr, i + 1, newArr[i].children, newArr[i + 1].level, lv1ItemEl) } // === if (newArr[i + 1].level === newArr[i].level) { // break; } } } getLv1(catalog, 0, arr, 1, null) // console.log(arr, '最终'); // 拼接dom字符串 function getDomStr(obj, arr) { // console.log(arr, 123456); let liStr = '' arr.forEach(li => { liStr += li.el }) // cy_oo + id // console.log(obj.lv1Item.replaceName, '55555555555'); obj.domStr = obj.domStr.replace(obj.lv1Item.replaceName, liStr) arr.forEach((item, i) => { // console.log(obj, obj.domStr); if (item.children && item.children.length) { obj.lv1Item = item getDomStr(obj, item.children) } else { // console.log(item, '999999999999999'); obj.domStr = obj.domStr.replace(item.replaceName, '') } }) // console.log(lv1Item.el.replace('cy_oo', 123456)); // console.log(domStr, 99999999999); } let catalogue = '' arr.forEach(item => { const lv1Item = item let domStr = lv1Item.el const obj = { domStr, lv1Item, rStr: 'cy_oo', newStr: '' } // if (item.children && item.children.length) { // getDomStr(domStr, item.children) // } getDomStr(obj, lv1Item.children) // if (item.text === '介绍') { // console.log(obj.domStr, '9999999999999'); // } // console.log(obj.domStr, '9999999999999'); catalogue+=obj.domStr // console.log(domStr, '9999999999999'); }) // console.log(catalogue, 6666666666666); // document.querySelector('.catalogue-items').innerHTML = catalogue; document.querySelector('.catalogue-items').innerHTML = catalogue; $('.catalogue-item > a').on('mouseenter', function () { $(this).parent().addClass('_active'); }); $('.catalogue-item > a').on('mouseleave', function () { $(this).parent().removeClass('_active'); }); // 根据目录定位到标题 $('.catalogue-item > a').on('click', function () { document.removeEventListener("scroll", autoActive); $('.catalogue-item').removeClass('active'); $(this).parent().addClass('active'); let aim = document.querySelector('#' + $(this).attr('to')); let aim_top = aim.offsetTop; let aim_h = aim.clientHeight; let above_h = document.querySelector('.joe_header__above').clientHeight; let below_h = document.querySelector('.joe_header__below').clientHeight; let offset = 0; let case1 = !document.querySelector('.joe_header__above').className.includes('active'); let case2 = document.getElementsByTagName("html")[0].scrollTop + above_h > aim_top; // console.log(case1, case2); // if (case1 && case2) { // offset = above_h; // } window.scrollTo({ top: aim_top - offset - above_h - below_h - 10, behavior: 'smooth' }); setTimeout(() => { document.addEventListener("scroll", autoActive); }, 500); }); if (catalog.length) $('.catalogue-item').eq(0).addClass('active'); // 目录侧标题自动定位 let autoActive = function () { let html_top = document.getElementsByTagName("html")[0].scrollTop; //获得父级卷去的高度 for (let i = 0; i < catalog.length; i++) { let offset = 0; let h_id = '#' + catalog[i].id; let h_offset = document.querySelector(h_id).offsetTop; let above_h = document.querySelector('.joe_header__above').clientHeight; let below_h = document.querySelector('.joe_header__below').clientHeight; if (!document.querySelector('.joe_header').className.includes('active')) offset = above_h; if (h_offset + below_h + offset + 10 >= html_top) { $('.catalogue-item').removeClass('active'); if (i > 0 && i < catalog.length - 1 && document.querySelector('#' + catalog[i].id).offsetTop > html_top + window.innerHeight * 0.2) { //还没到下一个标题 i--; } $('#to-' + catalog[i].id).parent().addClass('active'); break; } } }; document.addEventListener("scroll", autoActive); } } else { // 不是文章,隐藏目录 $('.catalogue').hide(); } // 自定义文章目录侧边栏-end本文内容参考:开发者社区-苏苏
2022年09月11日
415 阅读
8 评论
2 点赞