jQuery菜单如何将子菜单包含在Div中

3
我正在尝试在网页上创建一个包含在div中的“应用程序”。 它的大小不能超过一定的尺寸(比如:550px乘以280px)。 我有一个菜单,并且每个项目至少有1-3个子菜单。 问题是,虽然我知道子菜单的高度不超过280px,但子菜单经常超出父div的边界(除了最后一个菜单项外,它总是向上延伸而不是向下)。
是否有办法使菜单根据需要向上或向下增长,取决于它是否会超出div的边界?
这是一个JSFiddle:http://jsfiddle.net/3FqcG/ 请注意,“Salzburg”子菜单如何向下延伸超出黑色DIV的边界?如果太长,我希望它向上增长,如果有足够的空间,则向下增长。
目前,我只是使用基本初始化:$( "#menu" ).menu(); 谢谢!
2个回答

1

我不相信你可以用CSS做到这一点。

因此,我们只能使用javascript。基本思路是:

  1. 计算菜单的基线
  2. 如果它在边界之外
    1. 将菜单向上移动以纠正位置
  3. 几乎快乐地生活在一起

但是,我们有一个主要问题:

虽然我们捕捉了元素的焦点,但我们不知道它的子菜单何时显示和定位。因此,虽然您的问题在技术上得到解决,但远非理想的解决方案。

更新

我能想到的最好的解决方法是:

  1. 关闭动画(避免丑陋的故障)
  2. 添加一个监视器,不断监视即将打开的元素
  3. 如果打开,则应用位置修正
无论如何,如果您考虑到这一点,您可能会覆盖jquery ui组件的默认定位,但需要注意,您将无法轻松更新库。 更新:或者尝试 Rudy Garcia的版本(如果它有效)

演示

演示的代码:

var BASE_OFFSET = $('#menuContainer').offset().top;
var MAX_OFFSET = $('#menuContainer').height(); // get the offset of the container
var whenVisible = function($el, callback){ //executes callback when $el is visible
    if($el.is(':visible')){ // if visible
        callback(); // execute callback
    }else{ // otherwise
        setTimeout(function(){whenVisible($el, callback);},10); // do the same check in 10 ms
    }
};
var fixPosition = function($menu){ // correct the position of the menu in respect to #menuContainer
    var h = $menu.outerHeight(true); // take the height of the menu
    var menuBottom = $menu.offset().top + h - BASE_OFFSET; // the baseline of the menu (taking into consideration the BASE_OFFSET)
    if(menuBottom > MAX_OFFSET){ // if this is outside the MAX height
        var diff = MAX_OFFSET - menuBottom; // calculate the difference
        var newTop = $menu.position().top + diff; // modify current positioning with the calculated diff value
        $menu.css('top', newTop + 'px'); // apply it to top (which is also used by jquery to position submenus
    }
    $.fx.off = false; // switch animations back on
};
$( "#menu" ).menu().on('menufocus', function(ev, ui){ // on the event menufocus
    var $ui = $(ui.item); //take the focused element
    var $menu = $ui.children('ul'); // take its related submenu
    if($menu.length === 0){ // if there is none 
        return; // just terminate
    }
    $.fx.off = true; // switch off jQuery effects (otherwise you'll have glitches)
    whenVisible($menu, function(){fixPosition($menu);}); // execute fixPosition when $menu is visible
});

1
哇,非常感谢你在解决方案上花费了这么多的时间和精力!看起来它完美地运作了。我选择了你的答案,因为它是最清晰的解释,运作得非常好,并且有演示和代码进行说明。我非常感激! - Kivak Wolf

1
您也可以查看此小部件的API:

http://api.jqueryui.com/menu/

您可以使用位置选项来按照您的意愿定位元素。
这将更改位置,使它们在框内,但是您需要动态访问最后一个以给它所需的位置,因为下面的代码将更改所有菜单项以向上移动50个单位。
$( "#menu" ).menu({ position: { my: "left top", at: "right+5 top-50" } });

这里也可以找到完整的定位选项列表:http://api.jqueryui.com/position/

显然,jQuery UI 已经考虑到了这一点,并提供了“within”选项,以确保您的元素留在您选择的另一个元素内。

因此,您的解决方案应该是这样的:

$( "#menu" ).menu({ position: {within: '#menuContainer' } });

非常感谢,这个也可以工作,并且已经内置到了jQuery中。它是一个完全可行的解决方案!谢谢! :) - Kivak Wolf
没问题,很高兴能帮忙。通常最好使用它们内置的解决方案,以避免任何黑客行为。我建议在决定使用任何库或插件之前先探索提供的选项。 - Rudy Garcia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接