/** * Author: Jason Farrell * Author URI: http://useallfive.com/ * * Description: Checks if a DOM element is truly visible. * Package URL: https://github.com/UseAllFive/true-visibility */ Element.prototype.isVisible = function() { 'use strict'; /** * Checks if a DOM element is visible. Takes into * consideration its parents and overflow. * * @param (el) the DOM element to check if is visible * * These params are optional that are sent in recursively, * you typically won't use these: * * @param (t) Top corner position number * @param (r) Right corner position number * @param (b) Bottom corner position number * @param (l) Left corner position number * @param (w) Element width number * @param (h) Element height number */ function _isVisible(el, t, r, b, l, w, h) { var p = el.parentNode, VISIBLE_PADDING = 2; if ( !_elementInDocument(el) ) { return false; } //-- Return true for document node if ( 9 === p.nodeType ) { return true; } //-- Return false if our element is invisible if ( '0' === _getStyle(el, 'opacity') || 'none' === _getStyle(el, 'display') || 'hidden' === _getStyle(el, 'visibility') ) { return false; } if ( 'undefined' === typeof(t) || 'undefined' === typeof(r) || 'undefined' === typeof(b) || 'undefined' === typeof(l) || 'undefined' === typeof(w) || 'undefined' === typeof(h) ) { t = el.offsetTop; l = el.offsetLeft; b = t + el.offsetHeight; r = l + el.offsetWidth; w = el.offsetWidth; h = el.offsetHeight; } //-- If we have a parent, let's continue: if ( p ) { //-- Check if the parent can hide its children. if ( ('hidden' === _getStyle(p, 'overflow') || 'scroll' === _getStyle(p, 'overflow')) ) { //-- Only check if the offset is different for the parent if ( //-- If the target element is to the right of the parent elm l + VISIBLE_PADDING > p.offsetWidth + p.scrollLeft || //-- If the target element is to the left of the parent elm l + w - VISIBLE_PADDING < p.scrollLeft || //-- If the target element is under the parent elm t + VISIBLE_PADDING > p.offsetHeight + p.scrollTop || //-- If the target element is above the parent elm t + h - VISIBLE_PADDING < p.scrollTop ) { //-- Our target element is out of bounds: return false; } } //-- Add the offset parent's left/top coords to our element's offset: if ( el.offsetParent === p ) { l += p.offsetLeft; t += p.offsetTop; } //-- Let's recursively check upwards: return _isVisible(p, t, r, b, l, w, h); } return true; } //-- Cross browser method to get style properties: function _getStyle(el, property) { if ( window.getComputedStyle ) { return document.defaultView.getComputedStyle(el,null)[property]; } if ( el.currentStyle ) { return el.currentStyle[property]; } } function _elementInDocument(element) { while (element = element.parentNode) { if (element == document) { return true; } } return false; } return _isVisible(this); };