jQuery 中的visible

今天使用jQuery的判断元素是不是隐藏,由于不太清楚jQuery判断的逻辑,遇到一个坑,分享分享踩坑心得。

项目中用到的校验插件只会对页面可见的元素有效,如果元素是隐藏的,自动忽略验证。

校验插件是这样处理的:

function checkVisible($el, callback) {
    if (!$el.is(":visible")) {
        return true;
    } else {
        return callback();
    }
}

其原理是通过jQuery的visible方法判断的,这让我多了解了一种jQuery选择器:visible、:hidden。

但是后面在改一个富文本框的需求的时候,由于富文本会先隐藏输入框,然后自己模拟出一个输入框供用户输入信息。这时候就出现了问题了,由于隐藏元素会被校验规则忽略,就没办法校验用户是否输入信息。

于是尝试强制把被隐藏的元素强制设置成显示,并把宽高都设置成0,这样子就能通过$el.is(“:visible”)的校验。

但是仔细看的话,你会发现即使我们把输入框的宽高都设置为0后,还是有一个小黑点,这个是输入框自带的边框。继续把边框去掉,再次测试,居然又被校验规则给忽略了。WHY!!!!

扒拉了一下源码,原来visible、:hidden这个两个选择器是一样的判断方式

jQuery.expr.filters.hidden = function( elem ) {
    // Support: Opera <= 12.12
    // Opera reports offsetWidths and offsetHeights less than zero on some elements
    return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
};
jQuery.expr.filters.visible = function( elem ) {
    return !jQuery.expr.filters.hidden( elem );
};

归根到底还是通过offsetWidth和offsetHeight来判断元素是否可见

offsetWidth = border-left + padding-left + content + padding-right + border-right;

这样子看上去似乎就很合理了。

关于offsetWidth的延伸阅读:
http://www.w3schools.com/jsref/prop_element_offsetwidth.asp
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth