项目中的那些事---目录树

最近做了一个项目,是在网页中实现一份包含树目录导航的word文档的功能,简单点说就是将一个word文档,包括它的左侧导航部分,用网页的方式实现。

一、需求

1、  左侧实现目录树,右侧是内容

2、  点击左侧目录,右侧跳转到对应的章节

3、  左侧树要有全部展开、全部折叠、点击父节点前的加号可展开收缩、点击目录只可展开不可收缩、按关键字搜索目录等功能

4、  右侧内容包含翻页,点击翻页时,右侧在跳转到对应页面的同时,左侧要选中右侧页面对应的章节目录

二、思路

1、用iframe分左右两栏,左侧是目录树页面,右侧是内容页面

2、树用zTree实现

三、实现过程

1、iframe实现分栏

<iframe height="100%" id="left" style="border:none"></iframe>
<iframe height="100%" id="right" name="main"  style="border:none;"></iframe>
$("iframe").css({
    "border" : "1",
    "border-color" : "#B2DFEE",
    "scrolling" : "yes"
});
$("#left").attr({
    "src" : "left.html",
    "width" : "20%"
});
$("#right").attr({
    "src" :"right.html"
    "width" : "79.7%"
});

 上面的代码中有两个iframe,用jqueruy添加src属性,分别嵌入左侧的目录树left.html页面和右侧的right.html页面,并设置它们各自所占的宽度。

2、实现左侧的目录树

在实现树之前,要引入ztree的js库和css样式表以及jquery库,除此之外还可根据自己的需求,引入不同的js和css外部文件。如下所示:

<link rel="stylesheet" type="text/css" href="../js/zTree/js/zTreeStyle/zTreeStyle.css" />
<link rel="stylesheet" href="../js/bootstrap/css/bootstrap.min.css" />
<script type="text/javascript" src="../js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="../js/bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="../js/zTree/js/jquery.ztree.core-3.5.min.js"></script>

实现一棵ztree树,基本的操作有四步:

第一步:设置树的id,注意用的是<ul></ul>标签

<ul id="helpTree" class="ztree"></ul>

第二步:配置树

var setting = {
        edit :{
            enable:true
        },
        view : {
            dblClickExpand: false,
            showLine : true,
            checkable:true,
            showIcon:true,
            showTitle:true,
            fontCss:{
                'color' : '#009ACD',//#009ACD
                'font-weight' : 'normal'
            }
        },
        data : {
            simpleData : {
                enable : true,
                idKey : "id",
                pIdKey : "pId",
                rootPid :0
            },
            key:{
                title:"title"
            }
        },
        check:{
            enable:false,//不显示checkbox、radio
            chkStyle:"checkbox",
            radioType:"level"
            
        },
        callback : {
            beforeClick:function(treeId,treeNode){
                zTree=$.fn.zTree.getZTreeObj("helpTree");
                 if (treeNode.isParent) {
                        zTree.expandNode(treeNode,true);
                        return;
                    } 
            }, 
            beforeDblClick:function(treeId,treeNode){
                return false;//禁止双击事件onDblClick
            },
            onExpand : function(event,treeId,treeNode) {
                zTree = $.fn.zTree.getZTreeObj("helpTree");
                zTree.expandNode(treeNode,true);
            },
            onCollapse : function(event,treeId,treeNode) {
                zTree = $.fn.zTree.getZTreeObj("helpTree");
                zTree.expandNode(treeNode,false);
            },
            onClick :onClick
            /* beforeCollapse:function(treeId,treeNode){
                var id = treeNode.id;
                if(id==1||id==2||id==3||id==4||id==5){
                    return true;//禁止所有
                }else{
                    return false;
                }
            }, */
             

        }
    };


/* 节点点击事件 :点击某个节点将其值赋值给文本框*/
    function onClick(treeId, treeNode) {
        //在不输入关键字选中节点时禁止点击事件的发生
        var search = $("#keyName").val();
        if (search == "" || search == null) {
            return;
        } else {
            var zTree = getTree();
            var nodes = zTree.getSelectedNodes();
            var v = "";
            for (var i = 0, l = nodes.length; i < l; i++) {
                v += nodes[i].name + ",";
            }
            if (v.length > 1) {
                v = v.substring(0, v.length - 1);
            }
            $("#keyName").attr("value", v);
            $("#keyName").attr("title", v);
            return false;
        }

    }

第三步:设置树节点数据,以及各节点的链接页面

var zNodes =[
             /* 前言 */
             { id:17, pId:0, name:"前言",url:"./foreword.html",target:"main",icon:"../js/zTree/js/zTreeStyle/img/diy/3.png"},
               /* 第一章 */
             { id:1, pId:0, name:"1 第一章", open:false,url:"./cluster/cluster_1.1.html",target:"main"},
             { id:11, pId:1, name:"1.1 第一节", open:true,url:"./cluster/cluster_1.1.html",target:"main"},
             { id:12, pId:1, name:"1.2 第二节群",open:true,url:"./cluster/cluster_1.2.1.html",target:"main"},
             { id:120, pId:12, name:"1.2.1 第二节1群",open:true,url:"./cluster/cluster_1.2.1.html",target:"main"},
             { id:121, pId:120, name:"1.2.1.1 第二节11", open:true,url:"./cluster/cluster_1.2.1.html",target:"main"},
             { id:122, pId:120, name:"1.2.1.2第二节12", open:true,url:"./cluster/cluster_1.2.1.html#2",target:"main"},
             { id:123, pId:120, name:"1.2.1.3 第二节13", open:true,url:"./cluster/cluster_1.2.1.html#3",target:"main"},
             { id:124, pId:120, name:"1.2.1.4 第二节14", open:true,url:"./cluster/cluster_1.2.1.html#4",target:"main"},
             { id:125, pId:120, name:"1.2.1.5 第二节15", open:true,url:"./cluster/cluster_1.2.1.html#5",target:"main"},
             { id:126, pId:120, name:"1.2.1.6 第二节16", open:true,url:"./cluster/cluster_1.2.1.html#6",target:"main"},
             { id:127, pId:12, name:"1.2.2 第二节2",open:true,url:"./cluster/cluster_1.2.2.html",target:"main"},
             { id:13, pId:1, name:"1.3 第三节",open:true,url:"./cluster/cluster_1.3.html",target:"main"},
             { id:131, pId:13, name:"1.3.1 第三节1",open:true,url:"./cluster/cluster_1.3.html",target:"main"},
             { id:14, pId:1, name:"1.4 第四节",open:true,url:"./cluster/cluster_1.4.1.html",target:"main"},
             { id:141, pId:14, name:"1.4.1 第四节1",open:true,url:"./cluster/cluster_1.4.1.html",target:"main"},
             { id:142, pId:14, name:"1.4.2 第四节2",open:true,url:"./cluster/cluster_1.4.2.html",target:"main"},
             { id:143, pId:14, name:"1.4.3 第四节3",open:true,url:"./cluster/cluster_1.4.3.html",target:"main"},
             { id:15, pId:1, name:"1.5 第五节",open:true,url:"./cluster/cluster_1.5.html",target:"main"},
             { id:16, pId:1, name:"1.6 第六节",open:true,url:"./cluster/cluster_1.6.html",target:"main"},
             
             /*第二章 */
             { id:2, pId:0, name:"2 第二章",open:false,url:"./viewinfo/viewinfo_2.1.html",target:"main"},
             { id:21, pId:2, name:"2.1第一节", open:true,url:"./viewinfo/viewinfo_2.1.html",target:"main"},
             { id:22, pId:2, name:"2.2 第二节", open:true,url:"./viewinfo/viewinfo_2.2.html",target:"main"},
             { id:23, pId:2, name:"2.3 第三节", open:true,url:"./viewinfo/viewinfo_2.3.html",target:"main"},
             { id:24, pId:2, name:"2.4 第四节", open:true,url:"./viewinfo/viewinfo_2.4.1.html",target:"main"},
             { id:241, pId:24, name:"2.4.1 第四节1", open:true,url:"./viewinfo/viewinfo_2.4.1.html",target:"main"},
             { id:242, pId:24, name:"2.4.2 第四节2", open:true,url:"./viewinfo/viewinfo_2.4.2.html",target:"main"},
             { id:25, pId:2, name:"2.5 第五节", open:true,url:"./viewinfo/viewinfo_2.5.1.html",target:"main"},
             { id:251, pId:25, name:"2.5.1 第五节1", open:true,url:"./viewinfo/viewinfo_2.5.1.html",target:"main"},
             { id:252, pId:25, name:"2.5.2 第五节2", open:true,url:"./viewinfo/viewinfo_2.5.2.html",target:"main"},
             { id:253, pId:25, name:"2.5.3 3第五节", open:true,url:"./viewinfo/viewinfo_2.5.3.html",target:"main"},
             { id:26, pId:2, name:"2.6 第六节", open:true,url:"./viewinfo/viewinfo_2.6.html",target:"main"},
             
    

第四步:初始化树,即形成树

/* 初始化树 */
function initialTree() {
    $.fn.zTree.init($("#helpTree"), setting, zNodes);
}

通过以上这些步骤,就实现了前两个需求:创建一棵目录树,并在点击左侧树的目录标题时右侧会跳转到相应的内容。

关于树的配置,可以参考zTree的API进行查看,这里只是配置了一部分,根据不同的需求会有不同的配置,这里不加以阐述,因为我也还需要继续学习,毕竟我也是个后端儿!

3、点击按钮实现全部展开和全部折叠功能

第一步:创建按钮

<a href="#" title="全部展开" class="btn btn-info btn-sm" onclick="down()"> <span class="glyphicon glyphicon-plus" ></span></a> 
<a href="#" title="全部折叠" class="btn btn-info btn-sm" onclick="up()"> <span class="glyphicon glyphicon-minus" ></span></a>

第二步:点击【全部展开】功能

/*
* 展开所有树节点
*/

function
down() { $.fn.zTree.getZTreeObj("helpTree").expandAll(true); }

第三步:点击【全部折叠】功能

/*
 * 折叠所有树节点
 */
function up() {
    $.fn.zTree.getZTreeObj("helpTree").expandAll(false);
}

4、按关键字搜索树【该功能的实现是利用zTree中的getNodesByParamFuzzy("name", "test", null)方法进行模糊匹配】
第一步:创建搜索输入框和按钮

<input id="keyName" value="" type="text" placeholder="请输入搜索关键字"
class="form-control" onkeyup="searchClear()" style=" 180px;">

<a href="#" title="搜索" class="btn btn-info btn-sm" onclick="search()"> <span class="glyphicon glyphicon-search" ></span></a>

可以看到在input中有一个onkeyup()事件,这个事件会在键盘按键被松开时触发,即当用户准备输入时就会触发;另外在搜索按钮上也有一个点击事件,这个事件是当用户在输入搜索关键字,并点击搜索按钮时才会执行搜索动作
第二步:用户输入时,根据输入信息实时匹配出搜索结果

function searchClear() {
    var keyValue = $("#keyName").val();
   /* 当输入值为空时展示完整的树,并给树添加title属性*/
if (keyValue == "") { clear(); } else { autoMatch(keyValue) } } /* 自动匹配搜索结果 */ function autoMatch(name) { var nameValue = name.replace(/s+/g, ""); if (nameValue.length > 0) { initialTree(); var treeObj = getTree(); var nodeList = treeObj.getNodesByParamFuzzy("name", nameValue, null); /* 将搜索结果重新生成一棵树展示,并设置目录的title属性 */
if (nodeList && nodeList.length > 1) {
$.fn.zTree.init($(
"#helpTree"), setting, nodeList); showTree(); setTitle(); } else { hideTree(); initialTree(); setTitle(); } } else { showTree(); } } //手动清除搜索内容时初始化并显示树 function clear() { initialTree(); showTree(); setTitle(); } /* 隐藏树 */ function hideTree() { $("#content").hide(); } /* 显示树 */ function showTree() { $("#content").show(); }
/*给树节点设置title属性 */ function setTitle() { var zTree = getTree(); nodes = zTree.transformToArray(zTree.getNodes()); for (var i = 0; i < nodes.length; i++) { nodes[i].title = nodes[i].name; zTree.updateNode(nodes[i]); } }

第三步:点击搜索按钮时进行搜索

//点击搜索按钮进行模糊匹配
function search() {
    var keyValue = $("#keyName").val();
    autoMatch(keyValue);
}

5、点击清空按钮时显示整个树

当用户想改变搜索条件时,可以点击清空按钮重新输入搜索关键字,但是在清空搜索条件后,会还原树

清空按钮:

<a href="#" title="清空" class="btn btn-info btn-sm" onclick="clearKey()"> <span class="glyphicon glyphicon-remove" ></span></a>  

清空功能:

/* 点击清空按钮时清除搜索内容并显示初始化树 */
function clearKey() {
    $("#keyName").val("");
    initialTree();
    showTree();
    setTitle();
    inPlaceholder();
}

/**
 * IE9和IE8中实现placeholder属性的功能
 * @param inputId
 */
function inPlaceholder(){
    var inputId = "keyName";
    var isFocus = $("#"+inputId).is(":focus");
    var inputValue = $("#"+inputId).val();
    var phContent = $("#"+inputId).attr("placeholder");
    var isPlaceholder = "placeholder" in document.createElement("input");
    if(!isPlaceholder){
        //失去焦点并且input值为空时显示placeholder
        if(!isFocus){
            if(inputValue===""){
                $("#"+inputId).val(phContent).css("color","gray");
            }
        }
        
        $("#"+inputId).focus(function(){
            var inputValue1 = $("#"+inputId).val();
            if(inputValue1 && inputValue1==phContent){
                $("#"+inputId).val("");
            }else{
                $("#"+inputId).val(inputValue1);
            }
        });
        
        $("#"+inputId).blur(function(){
            var inputValue1 = $("#"+inputId).val();
            if(inputValue1 == ""){
                $("#"+inputId).val(phContent).css("color","gray");
            }else{
                $("#"+inputId).val(inputValue1);
            }
        });
    }
}

上面的3、4、5步实现了第二个需求,并且在清空搜索条件中有一个inPlaceholder()方法,解决了IE8和IE9不支持H5新特性placeholder属性的问题

6、实现翻页功能

第一步:在每一个内容页创建【上一页】和【下一页】的链接或按钮

<div  style="text-align: right;margin-top: 100px;margin-right: 100px;font: 25px;font-weight: bolder;">
<a type="button" href="../cluster/cluster_1.6.html" style="text-decoration: none;"  class="lastbtn">上一节</a>
<a type="button" href="../viewinfo/viewinfo_2.2.html" style="text-decoration: none;"  class="nextbtn">下一节</a>
</div>

第二步:给所有页面的上一页和下一页添加id属性

$(".nextbtn").attr("id","nextBtn");
$(".lastbtn").attr("id","lastBtn");

第三步:点击翻页按钮,进行页面跳转

$("#nextBtn").click(function(){
    selectNode(this);
}) ;

$("#lastBtn").click(function(){
    selectNode(this);
}) ;

/**
 * 调用左边iframe中的选中节点方法
 * @param id
 */
function selectNode(id){
    var href = $(id).attr("href");
    var start = href.lastIndexOf("/");
    if(start!=-1){
        href=href.substr(start+1,href.length);
    }
    getParent().getNode(href);
}

function getParent(){
    var frames=window.parent.window.document.getElementById("left"); 
    return frames.contentWindow;
}

/* 读取并选中链接所对应的树节点 */
function getNode(href) {
    var treeObj = getTree();
    var childNodes = treeObj.transformToArray(treeObj.getNodes());
    var url, id;
    for (var j = 0; j < childNodes.length; j++) {
        url = childNodes[j].url;
        id = childNodes[j].id;
        var start = url.lastIndexOf("/");
        var urlHref = url.substr(start+1, url.length);
        if (href == urlHref) {
            treeObj.selectNode(treeObj.getNodeByParam("id",id, null));
            return;
        }
    }
}

注意:上面的getNode(href)方法是在left.html页面,即在右侧页面的父页面中,所以在内容页面调用该方法时就要用到iframe在子页面获取父页面中元素或方法的方法getParent()

下面是实现翻页并选中对应页面目录的思路:

1、获取翻页链接中最后一个斜杠之后的内容right_href;

2、遍历树节点中的链接,并获取最后一个斜杠之后的内容left_href;

3、对比right_href和right_href,如果相同,则选中该节点;

最后附上一张树的效果图

以上就是这次遇到的问题及解决方法,里面延伸了一些内容,如IE89中不支持placeholder属性的解决方法,自己解决的有点击翻页选中跳转页面的目录,用户输入时进行匹配搜索结果等,

除此之外,其他内容都是关于ztree的部分,zTree中的内容比较多,我这里只是显示,没有涉及到编辑树的内容,所以这部分还需继续学习研究,以后有时间再补充吧,此篇就到这里......

最美好的时光里,不要一直是一个lowser!
原文地址:https://www.cnblogs.com/hellowhy/p/6396901.html