【问题标题】:How to detect whether a link is hidden in a collapsed twitter bootstrap nav bar with jQuery or vanilla JS如何使用 jQuery 或 vanilla JS 检测链接是否隐藏在折叠的 twitter 引导导航栏中
【发布时间】:2012-08-28 14:11:24
【问题描述】:

当 twitter 引导响应导航栏处于折叠状态时,我在检测导航链接的可见性时遇到问题。

问题的根源在于 .collapsed div 设置了溢出:隐藏规则。这意味着虽然导航ul的维度不为零,但它仍然是隐藏的,因为.collapse容器的高度为零(在关闭状态下设置在style属性中)。

问题在于,如果#some-nav-link 是 .nav ul 中的 li 项之一,它将与 $('#some-nav-link :visible') 匹配,因为它不知道该元素被溢出隐藏。

是否有一种万无一失的方法来检查可能导致此问题的元素的可见性?

我尝试使用 li $.fn.offset() 方法依赖 elementFromPoint,但在 li 有一些填充的情况下它不够好,例如,在这种情况下 elementFromPoint 返回的父级之一李。

注意 - 我的代码是相关网站上的第三方代码,因此我无法更改导航栏的工作方式。

重要更新 我正在寻找一种独立于 twitter bootstrap crash 工作机制的解决方案。这是确定元素可见性问题的一般解决方案,该元素位于溢出:隐藏元素的子元素的溢出部分。我觉得最好将其与引发此问题的具体问题联系起来,但如果当前问题将被视为令人困惑,我愿意相应地对其进行修改。我希望这次更新就足够了。

感谢阅读,我期待一些聪明的解决方案!

这是一个小提琴,显示了检查 :visible 在折叠时返回 true- http://jsfiddle.net/VDR3Y/

【问题讨论】:

    标签: jquery twitter-bootstrap overflow hidden nav


    【解决方案1】:

    选择器 :visible 的 jQuery 实现要求在任何祖先中将 heightwidth 都设置为 0 才能失败。否则你的原始代码会起作用。

    AFAIK 没有选择器可以直接执行此操作,因此可能需要自定义函数:

    (function () {
    
      function isCollapsed(element) {
        var $e = $(element);
    
        return $e.width()*$e.height() === 0;
      }
    
      $.fn.isReallyVisible = function () {
        var $this = $(this).filter(':visible');
    
        // if jQuery says its not visible, trust it, otherwise
        // check if any of the parents are collapsed
        return $this ? !$this.parents().toArray().some(isCollapsed) : false;
      };
    })();
    

    这将处理您的父母崩溃的情况。

    $('#some-nav-link').isReallyVisible();
    

    JSFiddle

    您可能需要添加更多来处理溢出,但由于 OP 中没有,我认为这暂时可行。

    【讨论】:

    • 这似乎就是问题所在!非常感谢,也感谢新的小提琴。我不仅学会了如何解决我的问题,而且还了解了我以前从未遇到过的 Array.some()。根据我的阅读,它没有在 oldIE 中实现,但很容易修复。
    • 我更新了你的小提琴 - jsfiddle.net/mUeay/3 以使用 .filter 而不是 .toArray().some,所以我想它现在应该是 oldIE 安全的。再次感谢!
    • @odedbd 我从使用 ActionScript 的经验中了解了 Array.some()。这是一个超级有用的方法,不仅因为它的效率,而且因为它的语义价值。无论如何,MDN 在Compatibility section of the Array.some() page 中有一个针对旧版IE 的补丁。我建议使用该补丁而不是filter()。很高兴为您提供帮助!
    • 感谢此次更新。假设我已经在使用 jQuery,为什么你建议不要使用过滤器?语义价值?还是有其他重要因素?由于我的代码在其他人的网站上作为第三方代码运行,我认为我不能按照 MDN 的建议修补数组原型。无论如何,感谢您的大力帮助以及对此类 cmets 的跟进。我很感激。
    • @odedbd 我的建议主要是出于性能原因。尽管理论上filter()some() 都是O(n) 算法,但在实际 方面filter()总是 执行在每个项目上,而在折叠的情况下,some() 只会执行直到找到真正的情况。如果要检查的元素有很多祖先,那么实际差异代表了一种有用的优化。几乎可以消除差异的另一种选择是将父母限制为parents('.collapse'),或类似的窄选择器。但是,这与 Bootstrap 无关。
    【解决方案2】:

    把这张支票放上去

    $('div.nav-collapse.in').length > 0 ? 'links are visible' : 'links are not visible'
    

    【讨论】:

    • 嗨,谢谢你的回答,这当然是我的问题的重点。但是,我现在意识到我没有在我的问题中说明我正在寻找一个不依赖于引导程序实现的通用解决方案。这是我的错,我会在问题中及时解决。抱歉不清楚。
    • 你可以用'hasClass'函数来做到这一点。
    【解决方案3】:

    对于任何感兴趣的人 - 我最终选择了基于 document.elementFromPoint 的不同解决方案。

    (function($) {
    
        function checkFromPoint(index) {
            var $e = $(this);
            var fromPoint = document.elementFromPoint($e.offset().left + $e.width() / 2, $e.offset().top + $e.height() / 2);
    
            return $e.get(0) == fromPoint || $e.has(fromPoint).length;
        }
    
        $.fn.isReallyVisible = function() {
            var $this = $(this).filter(':visible');    
    
            return $this.length ? !!$this.filter(checkFromPoint).length : false;
        };
    }(jQuery));
    

    我更新了jsfiddle,您可以在其中看到它在工作中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-17
      • 2016-05-09
      • 2015-01-04
      • 1970-01-01
      • 2020-09-02
      • 2015-01-26
      • 2013-05-16
      相关资源
      最近更新 更多