100%宽度滑动多级UL

时间:2017-03-14 16:05:26

标签: jquery html css

我正在开发一个导航系统,我希望家长ul和所有孩子uls的宽度达到100%,当您点击带有li的{​​{1}}时父母向左滑动,孩子从右侧滑入。这是我到目前为止所做的:

ul
$(function() {

  $('.list-container ul > li.has-child').each(function() {
    $(this).find('ul').prepend('<li class="back">< Back</li>');
  });

  $(document).on('click', '.list-container ul > li', function(e) {
    e.stopPropagation();
    var children = $(this).find('ul');
    if (!$(this).hasClass('back')) {
      if (children.length > 0) {
        $(this).parent().css('left','-100%');
        $(this).find('ul > li').css('display','block');
        $(this).find('ul').css('left','100%');
      }
    }
  });

  $(document).on('click','li.back', function(e) {
    e.stopPropagation();
    $(this).parent().parent().parent().css('left','0');
    $(this).parent().css('left','200%');
  });
});
html,body {
  height:100%;
  margin:0;
}
.list-container {
  overflow:hidden;
  width:100%;
}
ul {
  width:100%;
  list-style-type:none;
  padding:0;
  margin:0;
  position:absolute;
  transition: all 0.5s ease;
}

li {
  padding:10px 0 10px 15px;
  border-bottom:1px solid black;
}
  li.has-child:after {
    display:inline-block;
    content:">";
    float:right;
    margin-right:15px;
  }
li > ul {
  display:block;
  left:200%;
  top:0;
}
li > ul > li {
  display:none;
}

此代码按照预期用于第一级/第二级项目,但是一旦您尝试点击进入第3级(即“测试1子菜单”),它就会搞砸了。我现在意识到使用<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="list-container"> <ul> <li class="has-child">Test 1 <ul> <li class="has-child">Test 1 sub-menu <ul> <li>Test 1 sub-sub-menu</li> </ul> </li> <li>Test 1 sub-menu a</li> </ul> </li> <li class="has-child">Test 2 <ul> <li>Test 2 sub-menu</li> <li class="has-child">Test 2 sub-menu a <ul> <li>Test 2 sub-sub-menu</li> </ul> </li> </ul> </li> <li class="has-child">Test 3 <ul> <li>Test 3 sub-menu</li> <li class="has-child">Test 3 sub-menu a <ul> <li>Test 3 sub-sub-menu</li> </ul> </li> </ul> </li> </ul> </div>而不是divs可能会更好,但是有人可以建议如何在不修改HTML结构的情况下使其工作吗?如果有更好的方法来完成此功能,请打开以完全更改jQuery / CSS。

1 个答案:

答案 0 :(得分:1)

  

此代码适用于第一/第二级项目,   但是一旦你尝试点击进入第3级(即“测试1”   子菜单“)它搞砸了。

这是因为,您将ul移动常数200%,而子ul移动常数+/-100%。同时,您在ul处重置了主0。除此之外,当您使用显示块显示菜单时,您不会隐藏它们。虽然这适用于第一级,但它从第二级开始分离。

  

我现在意识到使用div可能会更好   这不是uls

是的,使用div可能会更好一些,因为对于分层ul来说,处理这些更容易。但是,ul对于层次结构来说更具语义性。

如果您不想更改HTML结构,那么最简单和最好的选择是指定每个子菜单所在的level。这可以通过简单地添加{{1}来完成每个data-上包含更多子项的属性,您可以摆脱li类。获得.has-child属性中定义的级别后,您可以使用这些级别将每个级别移动相应的因子。

以下是粗略的演示。请注意,虽然您已使用data-标记了此内容,但我使用普通的旧版vanila JavaScript创建了此演示,因为这对我来说更简单,更快捷。如果您愿意,可以将其转换为jQuery,但除此之外,这应该可以正常工作。

演示小提琴:https://jsfiddle.net/abhitalks/euLzo2dg/

演示代码段

jQuery
// keep things outside the global scope
(function (window, document) {
  var attachTo = document.getElementsByClassName('list-container')[0];
  prepareNav(attachTo); // attach nav to the div

  function prepareNav(nav) { 
    // prepare nav by creating back links, setting styles, and click handler
    var 
      navBar = nav.firstElementChild, 
      navElems = nav.querySelectorAll('li[data-level] > ul')
    ;
    for (i=0; i < navElems.length; i++) { 
      var backLink = document.createElement('li');
      backLink.className = 'back';
      backLink.textContent = '\u3008' + ' Back';
      navElems[i].insertBefore(backLink, navElems[i].firstElementChild);
    } 
    navBar.style.left = '0%';
    nav.addEventListener('click', function(e) {
      startNav(e, navBar, navElems);
    }, false);
  }

  function startNav(e, navBar, navElems) { 
    // click handler
    if (e.target.dataset && e.target.dataset.level) { 
      // move main ul by negative multiples of level
      navBar.style.left = -(e.target.dataset.level * 100) + '%';
      // reset all menus by hiding those
      [].forEach.call(navElems, function(ne) { ne.classList.remove('show'); }); 
      // show the parent menu
      e.target.parentNode.classList.add('show');
      // show the current menu
      e.target.firstElementChild.classList.add('show');
    }
    if (e.target.className === 'back') { 
      // move back the main ul by 100 (not to 100)
      var leftPos = parseInt(navBar.style.left);
      navBar.style.left = (leftPos + 100) + '%';
    }
  }	
	
})(window, document);
* { box-sizing: border-box; margin: 0; padding: 0; font-family: sans-serif; }
html, body { height:100%; }
.list-container { 
  overflow: hidden; position: relative; 
  width: 100%; min-height: 128px; 
}
.list-container ul {
  width: 100%; background-color: #eee;
  list-style-type: none; 
  position: absolute; left: 0%; top: 0%;
  transition: all .5s ease;
}
.list-container li {
  padding: 10px 0 10px 15px; 
  cursor: pointer; border: 1px solid #aaa; 
}
.list-container li:first-child { border-bottom: none; }
.list-container li:last-child { border-top: none; }
.list-container li.back + li:last-child { border-top: 1px solid #aaa;  }
.list-container li[data-level]::after {
  display: inline-block; content: '\003009';
  float: right; margin-right: 15px;
}
.list-container li[data-level]:hover, 
.list-container li.back:hover { background-color: #ddd; }
.list-container li[data-level] > ul { left: 100%; top: 0; display: none; }
.list-container li[data-level] > ul.show { display: block; }