Now the mobile project is in the refactoring phase, replacing all jQuery with Zepto. Due to the simplification of Zepto, the jQuery code that was placed before won’t run, where the Visible selector is one of them. Now that you’ve chosen Zepto, add Visible to Zepto.

Analysis of the

The first reaction is to think about judging by the attributes of the element, and then try to use display and visibility to judge. But after a small test, is I think simple!

Display cannot inherit from the parent element. Visibility can inherit from the parent element, but the parent element is displayed and hidden by display.

Reference Address 1 Reference address 2

A piece of my mind

Since the root element of the module is shown and hidden with display, I will select the element through the class selector first. We then recursively judge the parent element display, up to the body element.

; (function($) { var _filter = $.fn.filter; function visible(elem) { var $elem = $(elem); if($elem.css('display') === 'none') { return false; }else { if($elem.is('body')) { return true; }else { if(visible($elem.parent())) { return true; }else { return false; } } } } $.fn.filter = function(sel) { if (sel === ":visible") { return $([].filter.call(this, visible)); } return _filter.call(this, sel); }; })(window.Zepto);Copy the code

My own realization is ok, but I feel a little rao, see if I can solve it through other ways.

JQuery implementation

Check the internal implementation of jQuery3.0, final call is jQuery. The expr. Filters. The visible

jQuery.expr.filters.visible = function( elem ) { return !! ( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); };Copy the code

JQuery first determines the offsetWidth and offsetHeight of elements. Because the root element is hidden, the width and height of its children are 0. It doesn’t take up the document flow, which makes sense.

GetClientRects: Gets all rectangular areas of the page occupied by the element. Related to getBoundingClientRect is the getBoundingClientRect used to get all rectangular areas of the page occupied by the element. GetBoundingClientRect: Used to get the left, top, right, and bottom positions of an element on the page relative to the browser window

And why use this? Find the answer on the official website.

Breaking change: Behavior of :hidden and :visible An element is considered now visible if it has a layout box returned from the DOM getClientRects() method,even if that box has a height and/or width of zero. This means that elements such as or an empty element that don’t have height are considered to be visible.

An element that itself is zero in width and height but occupies a steady flow can be considered visible. Such as a newline BR, an empty SPAN tag.

Other implementation

You can also find ways to add Visible to Zepto on Github.

; (function($){ var _is = $.fn.is, _filter = $.fn.filter; function visible(elem){ elem = $(elem); return !! (elem.width() || elem.height()) && elem.css("display") ! == "none"; } $.fn.is = function(sel){ if(sel === ":visible"){ return visible(this); } if(sel === ":hidden"){ return ! visible(this); } return _is.call(this, sel); } $.fn.filter = function(sel){ if(sel === ":visible"){ return $([].filter.call(this, visible)); } if(sel === ":hidden"){ return $([].filter.call(this, function(elem){ return ! visible(elem); })); } return _filter.call(this, sel); } })(Zepto);Copy the code

conclusion

In the end, I chose the last one, which was functional enough to meet existing needs.

Sizzle is powerful, and the Visible selector is just a drop in the bucket. You can learn more about the idea later.

This paper addresses xiaoqiang730730. Making. IO / 2016/07/16 /…