有简单菜单列表主题。 UL LI。 LI的宽度和数量是动态的。并且在悬停上有下拉类型的东西“更多”/点击它将显示剩余的LI,这将不适合可用空间。
我尝试使用jquery,而用户从右到左调整窗口大小,它将隐藏最后一个可见的菜单项。有什么方法可以执行此反转,并在“更多”链接中添加LI。
尝试了一些选项,因为宽度较小,当我们调整大小然后列表项移动到下面并增加UL的高度所以使用这种方法我能够隐藏最后可见。 代码
http://jsbin.com/flexmenu/2/edit
第1步
第2步
第3步
当用户重新调整大小(增加宽度)
时,这些步骤将相反标记
<div class="twelve columns filter-wrapper">
<ul class="nav-bar-filter" id="nav-bar-filter">
<li><a href="#">All</a></li>
<li><a href="#">Small</a></li>
<li><a href="#">Medium</a></li>
<li><a href="#">Extra large</a></li>
<li><a href="#">Text</a></li>
<li><a href="#">Small-1</a></li>
<li><a href="#">Medium-1</a></li>
<li><a href="#">Extra large text</a></li>
<li><a href="#">Large text</a></li>
<li><a href="#">Text</a></li>
</ul>
<ul id="more-nav">
<li><a href="#">More > </a>
<ul class="subfilter"><li><a href="#">Text</a></li></ul>
</li>
</ul>
</div>
基本上此菜单将用于响应式布局菜单。任何帮助都将有所帮助。 编辑1:添加标记
答案 0 :(得分:14)
好吧,我已经尝试构建一些脚本来实现它,这就是我所拥有的:
$().ready(function () {
//we reconstruct menu on window.resize
$(window).on("resize", function (e) {
var parentWidth = $("#nav-bar-filter").parent().width() - 40;
var ulWidth = $("#more-nav").outerWidth();
var menuLi = $("#nav-bar-filter > li");
var liForMoving = new Array();
//take all elements that can't fit parent width to array
menuLi.each(function () {
ulWidth += $(this).outerWidth();
if (ulWidth > parentWidth) {
console.log(ulWidth);
liForMoving.push($(this));
}
});
if (liForMoving.length > 0) { //if have any in array -> move them to "more" ul
e.preventDefault();
liForMoving.forEach(function (item) {
item.clone().appendTo(".subfilter");
item.remove();
});
}
else if (ulWidth < parentWidth) { //check if we can put some 'li' back to menu
liForMoving = new Array();
var moved = $(".subfilter > li");
for (var i = moved.length - 1; i >= 0; i--) { //reverse order
var tmpLi = $(moved[i]).clone();
tmpLi.appendTo($("#nav-bar-filter"));
ulWidth += $(moved[i]).outerWidth();
if (ulWidth < parentWidth) {
$(moved[i]).remove();
}
else {
ulWidth -= $(moved[i]).outerWidth();
tmpLi.remove();
}
}
}
if ($(".subfilter > li").length > 0) { //if we have elements in extended menu - show it
$("#more-nav").show();
}
else {
$("#more-nav").hide();
}
});
$(window).trigger("resize"); //call resize handler to build menu right
});
必须更改您的CSS样式才能使其正常工作。我们所做的是:
width
为零,但我们可能必须显示其他菜单,因此我们也可以获得它的大小。window.resize
上,我们遍历主菜单中的所有元素(水平),累积ulWidth
变量中的每个元素宽度。width
超过父容器的width
- &gt;我们需要将其余的菜单项移动到子菜单(垂直) - 所以我们将这些元素推送到数组liForMoving
。liForMoving
不是为空 - 我们克隆其元素,将它们附加到子菜单并从主菜单中删除它们。width
中所有元素的mainMenu
小于其容器的宽度,我们需要检查是否可以将子菜单中的某些元素移动到主要元素$(moved[i]).remove()
)中删除元素,如果它不是 - 我们会删除附加元素(tmpLi.remove()
)答案 1 :(得分:10)
$(document).ready(function () {
var menu = $("#nav-bar-filter"),
subMenu = $(".subfilter"),
more = $("#more-nav"),
parent = $(".filter-wrapper"),
ww = $(window).width(),
smw = more.outerWidth();
menu.children("li").each(function () {
var w = $(this).outerWidth();
if (w > smw) smw = w + 20;
return smw
});
more.css('width', smw);
function contract() {
var w = 0,
outerWidth = parent.width() - smw - 50;
for (i = 0; i < menu.children("li").size(); i++) {
w += menu.children("li").eq(i).outerWidth();
if (w > outerWidth) {
menu.children("li").eq(i - 1).nextAll()
.detach()
.css('opacity', 0)
.prependTo(".subfilter")
.stop().animate({
'opacity': 1
}, 300);
break;
}
}
}
function expand() {
var w = 0,
outerWidth = parent.width() - smw - 20;
menu.children("li").each(function () {
w += $(this).outerWidth();
return w;
});
for (i = 0; i < subMenu.children("li").size(); i++) {
w += subMenu.children("li").eq(i).outerWidth();
if (w > outerWidth) {
var a = 0;
while (a < i) {
subMenu.children("li").eq(a)
.css('opacity', 0)
.detach()
.appendTo("#nav-bar-filter")
.stop().animate({
'opacity': 1
}, 300);
a++;
}
break;
}
}
}
contract();
$(window).on("resize", function (e) {
($(window).width() > ww) ? expand() : contract();
ww = $(window).width();
});
});
必须修改CSS才能使其正常工作。 我没有为任何元素提供静态尺寸,因此无论内容如何,菜单都会响应。
工作原理:
只有2个函数contract()
和expand()
,当调用页面加载contract()
以将其他项目移动到子菜单时,如果调整窗口大小expand()
将被调用如果它的合同contract()
将被调用。
更新: 在右侧添加了动画和固定子菜单位置,请参阅演示。
答案 2 :(得分:1)
试试这个:让你的jQuery检测nav
栏中必须截断多少个术语。然后,根据截断的术语数量,使用li
JavaScript方法将ul
元素添加到document.createElement()
。例如,如果您的jQuery检测到5个术语已被截断,则使用以下代码:
var truncated_elements = 5;
for (i=1; i<truncated_elements; i++){
var new_li = document.createElement('li');
new_li.innerHTML = "truncated_term";
document.getElementsByTagName('ul')[0].appendChild(new_li);
}
在上面的代码中,jQuery会发现需要截断5个元素,并运行for
循环,在其中为每个截断元素创建li
s。 innerHTML
的{{1}}将设置为截断元素的内容(可能使用数组),然后new_li
将附加到new_li
中“更多”子菜单。
如果需要,我可以提供JSFiddle / JSBin。
答案 3 :(得分:1)
我认为应该反转下拉菜单以使标签序列保持在可聚焦项目中的顺序相同。
对于辅助功能,您还可以设置setize和集合中的位置。 出于可访问性原因,当移动的元素具有焦点时,我将焦点重置为克隆项目,并添加setWaiAria以设置setsize和set position。当焦点越多,消失时,将焦点设置为最后一项。见fiddle
$().ready(function () {
var setWaiAria = function(menuLi){
menuLi.each(function (i,el) {
var $el = $(el);
$el.attr('aria-setsize',menuLi.length);
$el.attr('aria-posinset',i+1);
});
}
// set wai aria aria-setsize and aria-posinset before cloning elements in other list
setWaiAria($("#nav-bar-filter > li"));
//we reconstruct menu on window.resize
$(window).on("resize", function (e) {
var parentWidth = $("#nav-bar-filter").parent().width() - 40;
var ulWidth = $("#more-nav").outerWidth();
var menuLi = $("#nav-bar-filter > li");
var liForMoving = new Array();
var activeElement = $(document.activeElement)[0];
// before remove item check if you have to reset the focus
var removeOriginal = function(item,clone){
// check focused element
if(item.find('a')[0] === activeElement){
activeElement = clone.find('a')[0];
}
item.remove();
}
//take all elements that can't fit parent width to array
menuLi.each(function () {
var $el = $(this);
ulWidth += $el.outerWidth();
if (ulWidth > parentWidth) {
liForMoving.unshift($el);
}
});
if (liForMoving.length > 0) { //if have any in array -> move em to "more" ul
e.preventDefault();
liForMoving.forEach(function (item) {
var clone = item.clone();
clone.prependTo(".subfilter");
removeOriginal(item, clone);
});
}
else if (ulWidth < parentWidth) { //check if we can put some 'li' back to menu
liForMoving = new Array();
var moved = $(".subfilter > li");
for (var i=0, j = moved.length ; i < j; i++) {
var movedItem = $(moved[i]);
var tmpLi = movedItem.clone();
tmpLi.appendTo($("#nav-bar-filter"));
ulWidth += movedItem.outerWidth();
if (ulWidth < parentWidth) {
removeOriginal(movedItem, tmpLi);
}
else {
// dont move back
ulWidth -= movedItem.outerWidth();
tmpLi.remove();
}
}
}
if ($(".subfilter > li").length > 0) { //if we have elements in extended menu - show it
$("#more-nav").show();
}
else {
// check if 'more' link has focus then set focus to last item in list
if($('#more-nav').find('a')[0] === $(document.activeElement)[0]){
activeElement = $("#nav-bar-filter > li:last-child a")[0];
}
$("#more-nav").hide();
}
// reset focus
activeElement.focus();
});
$(window).trigger("resize"); //call resize handler to build menu right
});