首页 前端知识 jquery文件夹菜单

jquery文件夹菜单

2024-04-18 00:04:27 前端知识 前端哥 582 923 我要收藏
上一篇讲到菜单:

手写jquery生成无限极的菜单icon-default.png?t=N7T8https://blog.csdn.net/qq_50145597/article/details/137338101?spm=1001.2014.3001.5502

这一次改成文件夹菜单,效果图如下:

Java对象和后端传入数据可以去看上一篇文章开头就是

css:
<style type="text/css">
  li{
    margin-left: 10%;
    list-style-type: none;
    /*disclosure-closed*/
  }
  .opr-span{
    width: 20%;
  }
  .opr li{
    display:inline-block;
  }
  .opr{
    width: 100px;
    position: absolute;
  }
  .new-li{
    font-size: 60%;
    width: 125%;
  }
  .menu-li{
    margin: 2%;
  }
html:
<div class="parent">
  <ul class="parent_ul" style="background-color: whitesmoke; width: 20%"></ul>
</div>
<ul class="opr">
  <!--添加文件的按钮-->
  <li><span class="opr-span glyphicon glyphicon-file" id="file"></span></li>
  <!--添加文件夹的按钮-->
  <li><span class="opr-span glyphicon glyphicon-folder-close" id="folder"></span></li>
</ul>

html主要写了两个部分,第一个是菜单div。第二个是一个创建文件和文件夹的按钮。

整体的js:
var $opr = $(".opr");
  $(function (){
    $opr.hide();
    init();
    closeAndOpen();
   // $("ul li .menu-ul").hide();
  });

  /**
   * 开光
   */
  function closeAndOpen(){
    let _this;
    var $body = $("body");
    var $oprli = $(".opr li");
    $body.on("click contextmenu","li span",function (e) {
      var children = $(this).parent().children(".menu-ul");
      if (e.type==="click" ){
        children.toggle(500);
        e.stopPropagation();
        $(this).toggleClass(function (){
          if ($(this).is("glyphicon-folder-close")){
            return "glyphicon-folder-close";
          }
          return "glyphicon-folder-open";});
      }
      if (e.type==="contextmenu" && !($(this).hasClass("glyphicon-file")) &&!($(this).hasClass("opr-span"))){
        //console.log($(this).attr("class"))
        e.preventDefault();
        var position = $(this).offset();
        $opr.css({
             top:position.top+"px",
             left:(position.left*(1.1))+"px"
                }).fadeIn(100);
       // console.log(children.attr('class'));
        _this=$(this);
        $(document).one("click", function(){
          $opr.hide();
        });
        e.stopPropagation();
      }
    });

    $oprli.on("click",function () {
      console.log($(this).attr("id"))
      if ($(this).attr("id")==="file"){
        //console.log( _this.parent("li").html())
        var childrens = _this.parent("li").children("ul>li");
         _this.parent().children("ul").append("<li><input class='new-li' value='新建文件夹'"+childrens.length+"/><span class='new-li-delete'>-</span></li>");
      }
    });
    $body.on("click","new-li-delete",function () {
      console.log($(this))
      $(this).parent("li").remove();
      alert($(this))
    });
  }

  /**
   * 初始化函数
   */
  function init(){
    $(".parent>ul>li>ul").remove();
    $.ajax({
      url: '/test/array',
      type: 'GET',
      dataType: 'json',
    }).done(function (data) {
      if (data.rs) {
        var res = data.data;
        var h1 = "<li>菜单";
        h1 =ul(res,h1);
        h1+="</li>";
        $(".parent>ul").append(h1);
        $("ul li .ul-close1").hide();
      }
    }).fail(function () {
    });
  }

  /**
   * 递归菜单
   * @param arry
   * @param h1
   * @returns {*}
   */
  var a1;
  var a2;
  var className;
  var childFlag = 0;
  var ulCloseClass = "";
  function ul(arry){
    if (arry.length===""){
      return "";
    }
    if (arry.length===0){
      return "";
    }
    ulCloseClass = (childFlag===0)?"":" ul-close1";
    var h1="<ul class='menu-ul "+ulCloseClass+ "'>";
    arry.forEach(item=>{
      a1 = (item.url!==null&&item.child.length===0)?"<a href='"+item.url+"'>":"";
      a2 = (item.child.length===0)?"</a>":"";
      className = item.child.length!==0?"glyphicon glyphicon-folder-close":"glyphicon glyphicon-file";
      h1+="<li class='menu-li'>"+a1+"<span class='menu-span "+className+"'" +
              "style=' background-image: url("+item.backgroundImage+"')\">"+item.name+"</span>";
      if (item.child.length!==0){
          childFlag = 1;
          var child = item.child;
          h1+=ul(child);
          childFlag =0;
      }
      h1+=(a2)+"</li>";
    })
    h1+="</ul>";
    return h1;
  }

js也就是想到哪儿写到哪儿,比较繁杂,毕竟不是前端出生,望请谅解。

解析js:

var $opr = $(".opr");
  $(function (){
    $opr.hide();
    init();
    closeAndOpen();
  });
加载js

执行事件{

1.隐藏创建文件夹和文件的按钮;

2.初始化;

3.监听文件<li>标签鼠标点击事件;

}        

没啥技术和坑点;

function init(){
   var h1 = "<li>菜单";
    h1 =ul(data,h1);
    h1+="</li>";
    $(".parent>ul").append(h1);
    $("ul li .ul-close1").hide();
}
初始化函数

注意data是上一篇中的后端传入的data json数据。关闭子菜单。也没啥坑点

  /**
   * 递归菜单
   * @param arry
   * @param h1
   * @returns {*}
   */
  var a1;
  var a2;
  var className;
  var childFlag = 0;
  var ulCloseClass = "";
  function ul(arry){
    if (arry.length===""){
      return "";
    }
    if (arry.length===0){
      return "";
    }
    ulCloseClass = (childFlag===0)?"":" ul-close1";
    var h1="<ul class='menu-ul "+ulCloseClass+ "'>";
    arry.forEach(item=>{
      a1 = (item.url!==null&&item.child.length===0)?"<a href='"+item.url+"'>":"";
      a2 = (item.child.length===0)?"</a>":"";
      className = item.child.length!==0?"glyphicon glyphicon-folder-close":"glyphicon glyphicon-file";
      h1+="<li class='menu-li'>"+a1+"<span class='menu-span "+className+"'" +
              "style=' background-image: url("+item.backgroundImage+"')\">"+item.name+"</span>";
      if (item.child.length!==0){
          childFlag = 1;
          var child = item.child;
          h1+=ul(child);
          childFlag =0;
      }
      h1+=(a2)+"</li>";
    })
    h1+="</ul>";
    return h1;
  }

这个递归函数升级了下,a1,a2都代表根据url是否生成a标签。ulCloseClass,ulCloseClass标记子文件ul,方便初始化时关闭子菜单。childFlag 是辅助标记为子文件的变量,初始为0,发动子文件递归调动时childFlag为1,结束复位为0.className确定确定是否为文件夹或者为文件,写上不同的图标(glyphicon glyphicon-folder-close和glyphicon glyphicon-file)制作好html后返回出去。


  /**
   * 开光
   */
  function closeAndOpen(){
    let _this;
    var $body = $("body");
    var $oprli = $(".opr li");
    $body.on("click contextmenu","li span",function (e) {
      var children = $(this).parent().children(".menu-ul");
      if (e.type==="click" ){
        children.toggle(500);
        e.stopPropagation();
        $(this).toggleClass(function (){
          if ($(this).is("glyphicon-folder-close")){
            return "glyphicon-folder-close";
          }
          return "glyphicon-folder-open";});
      }
      if (e.type==="contextmenu" && !($(this).hasClass("glyphicon-file")) &&!($(this).hasClass("opr-span"))){
        //console.log($(this).attr("class"))
        e.preventDefault();
        var position = $(this).offset();
        $opr.css({
             top:position.top+"px",
             left:(position.left*(1.1))+"px"
                }).fadeIn(100);
       // console.log(children.attr('class'));
        _this=$(this);
        $(document).one("click", function(){
          $opr.hide();
        });
        e.stopPropagation();
      }
    });

    $body.on("click","new-li-delete",function () {
      console.log($(this))
      $(this).parent("li").remove();
      alert($(this))
    });
  }
开关函数

委托函数on,监听对象li标签中的span模块,执行两个函数(click 和contextmenu)。鼠标左键(click)单击时出现文件的开启和闭合,toggle函数负责关闭和开启子文件夹和文件,toggleClass负责改变图标文件夹的样式(开合),如下图

鼠标右击(contextmenu)文件夹时,会出现新建文件和文件夹的图标

后面两个判断是为什么呢?那是因为文件不具有创建文件和文件夹的功能,这是文夹特有的功能。即鼠标右点击文件时,不会产生创建文件和文件夹的图标。还有一个是因为创造文件文件夹的span,不去判断这个span就会去偏移,对于位置问题,我觉得$(this).offset()比较好用,我看很多博主推荐event.target().left和top,我这里感觉不是很好用,因为这个事件点击span位置会不断变化,因为span标签是有一定的范围,不好控制,所以用了$(this).offset()确定位置。底下则是定位和执行一次解绑one函数,作用就是点击其他地方时,这个创建的图标就会消失。其他的函数上一篇也有说到,就不过多赘叙了。都看到这里了,不点个关注?

总结:

总体写起来还是挺麻烦的,还是一个动态dom确定。工作时我当然优先选择一些框架直接执行,但学习的话,感觉底层还是更好一点。好比说,隐藏在js中是display:none;而jquery直接hide()。有什么想法发表在评论区,大家一起探讨一下。

 打赏

创作不易,打赏鼓励(zfb)

转载请注明出处或者链接地址:https://www.qianduange.cn//article/5148.html
标签
评论
发布的文章

安装Nodejs后,npm无法使用

2024-11-30 11:11:38

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!