zoukankan      html  css  js  c++  java
  • 项目中的那些事---目录树

    最近做了一个项目,是在网页中实现一份包含树目录导航的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
Copyright © 2011-2022 走看看