Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 检测下拉式导航是否会离开屏幕并重新定位_Javascript_Jquery_Html_Css - Fatal编程技术网

Javascript 检测下拉式导航是否会离开屏幕并重新定位

Javascript 检测下拉式导航是否会离开屏幕并重新定位,javascript,jquery,html,css,Javascript,Jquery,Html,Css,我有您典型的下拉式导航,我正在努力确保下拉菜单链接始终可访问且可见: <li><a href="#">Link 1</a> <ul> <li><a href="#">Link 1</a></li> <li><a href="#">Link 2</a></li> <li><a hre

我有您典型的下拉式导航,我正在努力确保下拉菜单链接始终可访问且可见:

<li><a href="#">Link 1</a>
    <ul>
        <li><a href="#">Link 1</a></li>
        <li><a href="#">Link 2</a></li>
        <li><a href="#">Link 3</a></li>
    </ul>
</li>
<li><a href="#">Link 2</a>
    <ul>
        <li><a href="#">Link 1</a></li>
        <li><a href="#">Link 2</a></li>
        <li><a href="#">Link 3</a></li>
    </ul>
</li>
<!-- etc. -->
</ul>
存在未知数量的顶级链接(它们是由用户创建的)。我遇到的问题是,如果顶层链接离右边太远,有时下拉菜单(向右)会离开屏幕。我添加了这一点CSS来补偿:

.dropdown > li:last-child ul { /* ...or use a class on the last link for IE */
    right:0;
}
现在,最后一个将转到左侧,而不是屏幕外,这很好,但有几个问题:

  • 我并不总是需要这些风格的最后一个链接,因为它并不总是在屏幕的边缘(就像如果只有3个链接)
  • 调整浏览器窗口的大小时,链接堆叠在彼此的顶部(按设计)。有时序列中间的链接最终在右边,它们的下落被切断。
  • 有时,“下一个到最后一个”链接的菜单也会超出边界
  • 调整此演示中的面板大小以了解我的意思(红色区域被视为“屏幕外”)

    多年来,我一直在努力解决这个令人烦恼的常见问题,但从未找到令人满意的解决方案。有没有办法检查下拉菜单是否会脱离屏幕,如果有,添加/删除
    名称或其他内容,以便我可以使用CSS将其保留在屏幕上

    我可能会使用的一个线索是,如果菜单离开屏幕,它总是在窗口底部产生一个垂直滚动条,但我不知道如何使用这些知识。我尝试了关于检测垂直滚动条的公认答案,但出于某种原因,它总是返回
    true
    ,并且总是添加“edge”类(可能时间有问题?)

    使用javascript进行演示:

    真的,我不想看到一个垂直的滚动条,即使是在一瞬间,所以我不确定这是一种方式去,加上可能有误报(滚动条的其他原因)

    我也尝试过这个解决方案,我承认,我不太明白,也无法让它发挥作用:

    $(“.dropdown li”).on('mouseenter mouseleave',函数(e){
    var elm=$('ul:first',this);
    var off=elm.offset();
    var t=关闭顶部;
    var l=关闭。左侧;
    var h=榆树高度();
    var w=榆树宽度();
    var docH=$(窗口).height();
    var docW=$(window.width();
    var isEntirelyVisible=(t>0&&l>0&&t+h

    我假设解决方案需要javascript,我使用的是jQuery,但我不知道如何解决这个问题。有什么想法吗?

    我想你就快到了

    你应该只对宽度的计算感兴趣。如果下拉元素的宽度和该元素的偏移量大于容器的宽度,则需要切换菜单

    $(function () {
        $(".dropdown li").on('mouseenter mouseleave', function (e) {
            if ($('ul', this).length) {
                var elm = $('ul:first', this);
                var off = elm.offset();
                var l = off.left;
                var w = elm.width();
                var docH = $(".container").height();
                var docW = $(".container").width();
    
                var isEntirelyVisible = (l + w <= docW);
    
                if (!isEntirelyVisible) {
                    $(this).addClass('edge');
                } else {
                    $(this).removeClass('edge');
                }
            }
        });
    });
    
    $(函数(){
    $(“.dropdown li”).on('mouseenter mouseleave',函数(e){
    如果($('ul',此).length){
    var elm=$('ul:first',this);
    var off=elm.offset();
    var l=关闭。左侧;
    var w=榆树宽度();
    var docH=$(“.container”).height();
    var docW=$(“.container”).width();
    
    var isEntrelyVisible=(l+w这里有一个函数,可用于向右或向下弹出的菜单(基于@r0m4n的代码):

    函数固定弹出按钮(containerElement、parentElement、flyoutElement、flyoutDirection){
    $(parentElement).on('mouseenter mouseleave',函数(e){
    var元素=$(flyoteElement,this);
    var offset=element.offset();
    开关(弹出方向){
    案例“关闭”:
    var top=offset.top;
    var height=element.height();
    var windowHeight=$(containerElement).height();
    
    var IsEntireyVisible=(顶部+高度我无法使addClass(“edge”)正常工作,但我能够修改相关元素的CSS以实现该行为。(仅从r0m4n略微修改):


    这可能会有帮助。我会看一看并更新我的结果,谢谢。再想一想,“滚动条检测”方法不是很好,如果它起作用可能会导致误报(滚动条出于另一个原因)。类似这样的东西?是的,非常类似这样的东西,除了在顶层下拉菜单上,还有可堆叠的导航项目(如果视口很小)。我会看看我是否能把这些代码拆开并找到有用的东西,谢谢你理解我的问题。@WesleyMurch-它有点旧。不久前写了它,但最终没有使用它。我确信有足够的空间进行更新和改进。希望它能帮上忙。你搞定了!我的大部分想法都是在我实际发布问题之前产生的(当然),我的大脑被它炸得焦头烂额,我没有意识到我的错误。我衷心感谢你,这段代码肯定会在工具箱中。这似乎给出了一个错误“Uncaught TypeError:无法读取未定义的“left”属性”即使是在你的JSFIDLE中。有人知道如何解决这个问题吗?@Aaron啊,是的,很好的捕获…请参阅更新。错误是由于处理程序试图在子嵌套项不存在时重新定位子嵌套项造成的!您好@r0m4n谢谢您的出色回答。但是我有一个小问题,我想在第二级中使用,但它不起作用。@r0m4n这是否可以工作是否有多级下拉列表?我有一个两级的下拉列表,需要能够将第二个列表从第一个列表中偏移。您是否能够添加一个小提琴来显示正在使用该列表?我希望能够将嵌套列表放在嵌套列表中,以便将右侧或左侧的多级下拉列表显示为键入错误“right”变量IsEntrelyVisible应为left+width,是吗?
    $(".dropdown li").on('mouseenter mouseleave', function (e) {
    
        // Get the computed style of the body element
        var cStyle = document.body.currentStyle||window.getComputedStyle(document.body, "");
    
        // Check the overflow and overflowY properties for "auto" and "visible" values
        hasVScroll = cStyle.overflow == "visible" 
                 || cStyle.overflowY == "visible"
                 || (hasVScroll && cStyle.overflow == "auto")
                 || (hasVScroll && cStyle.overflowY == "auto");
    
        if (hasVScroll) {
            $(this).addClass('edge');
        } else {
            $(this).removeClass('edge');
        }
    });​
    
    $(".dropdown li").on('mouseenter mouseleave', function (e) {
    
        var elm = $('ul:first', this);
        var off = elm .offset();
        var t = off.top;
        var l = off.left;
        var h = elm.height();
        var w = elm.width();
        var docH = $(window).height();
        var docW = $(window).width();
    
        var isEntirelyVisible = (t > 0 && l > 0 && t + h < docH && l+ w < docW);
    
        if ( ! isEntirelyVisible ) {
            $(this).addClass('edge');
        } else {
            $(this).removeClass('edge');
        }
    });​
    
    $(function () {
        $(".dropdown li").on('mouseenter mouseleave', function (e) {
            if ($('ul', this).length) {
                var elm = $('ul:first', this);
                var off = elm.offset();
                var l = off.left;
                var w = elm.width();
                var docH = $(".container").height();
                var docW = $(".container").width();
    
                var isEntirelyVisible = (l + w <= docW);
    
                if (!isEntirelyVisible) {
                    $(this).addClass('edge');
                } else {
                    $(this).removeClass('edge');
                }
            }
        });
    });
    
    function fixFlyout (containerElement, parentElement,flyoutElement,flyoutDirection) {
        $(parentElement).on('mouseenter mouseleave', function (e) {
            var element = $(flyoutElement, this);
            var offset = element .offset();
            switch(flyoutDirection) {
                case 'down':
                    var top = offset.top;
                    var height = element.height();
                    var windowHeight = $(containerElement).height();
                    var isEntirelyVisible = (top + height <= windowHeight);
                    break;
                case 'right':
                    var left = offset.left;
                    var width = element.width();
                    var windowWidth = $(containerElement).width();
                    var isEntirelyVisible = (top + width <= windowWidth);
                    break;
            }
            if (!isEntirelyVisible ) {
                $(element).addClass('edge');
            } else {
                $(element).removeClass('edge');
            }
        });
    }
    //Level 1 Flyout
    fixFlyout(containerElement = '.header',parentElement = '.header .navigation>.menu>.expanded',flyoutElement = '.menu:first',flyoutDirection = 'down');
    
            //Align submenu to right if cut-off from window
            $(function () {
                $(".dropdown").on('mouseenter mouseleave', function (e) {
                    if ($('.dropdown-content', this).length) {
                        var dropdownElement = $('.dropdown-content:first', this);
                        var elementOffset = dropdownElement.offset();
                        var elementOffsetLeft = elementOffset.left;
                        var elementWidth = dropdownElement.width();
                        var pageHeigth = $(".show-on-scroll-wrapper").height();
                        var pageWidth = $(".show-on-scroll-wrapper").width();
                        //if left offset + width of dropdown is bigger than container width then it is cut-off
                        if ((elementOffsetLeft + elementWidth) > pageWidth) {
                            //Align Right
                            $(".dropdown-content").css({ "left":"auto", "right":"0", "margin-right":"-10px;"});
                        } else {
                            //Align Left
                            $(".dropdown-content").css({ "left":"0", "right":"auto", "margin-left": "-10px;" });
                        }
                    }
                });
            });