Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored and added getFullOffsets() / visibleFromParentAndOffset() #27

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 103 additions & 56 deletions jquery.visible.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,115 @@
(function($){

/**
* Copyright 2012, Digital Fusion
* Licensed under the MIT license.
* http://teamdf.com/jquery-plugins/license/
*
* @author Sam Sehnert
* @desc A small plugin that checks whether elements are within
* the user visible viewport of a web browser.
* only accounts for vertical position, not horizontal.
*/
var $w = $(window);
$.fn.visible = function(partial,hidden,direction){
* Copyright 2012, Digital Fusion
* Copyright 2015, picoded.com
*
* Licensed under the MIT license.
* http://teamdf.com/jquery-plugins/license/
*
* @author (original) Sam Sehnert
* @author (refactored by) Eugene Cheah ([email protected])
*
* @desc A small plugin that checks whether elements are within
* the user visible viewport of a web browser. Adds the following functions
*
* + getFullOffsets : gets the full top,left,bottom,right offsets relative to
* the top,left corner of the browser. With an optional delta
* adjustment of results. Also returns object width / height.
*
* + visibleFromParentAndOffset : Extends the original visible function, to check
* relative to a parent view box, and its offsets
*
* + visible : original visible functionality by Sam Sehnert
*/

/// gets the full top,left,bottom,right offsets relative to the top,left corner of the browser.
$.fn.getFullOffsets = function( delta ) {
if (this.length < 1)
return;
return false;

delta = (delta)? delta : {};

var $t = this.length > 1 ? this.eq(0) : this,
_t = $t.get(0),
offset, width, height;

var $t = this.length > 1 ? this.eq(0) : this,
t = $t.get(0),
vpWidth = $w.width(),
vpHeight = $w.height(),
direction = (direction) ? direction : 'both',
clientSize = hidden === true ? t.offsetWidth * t.offsetHeight : true;

if (typeof t.getBoundingClientRect === 'function'){

// Use this native browser method, if available.
var rec = t.getBoundingClientRect(),
tViz = rec.top >= 0 && rec.top < vpHeight,
bViz = rec.bottom > 0 && rec.bottom <= vpHeight,
lViz = rec.left >= 0 && rec.left < vpWidth,
rViz = rec.right > 0 && rec.right <= vpWidth,
vVisible = partial ? tViz || bViz : tViz && bViz,
hVisible = partial ? lViz || rViz : lViz && rViz;

if(direction === 'both')
return clientSize && vVisible && hVisible;
else if(direction === 'vertical')
return clientSize && vVisible;
else if(direction === 'horizontal')
return clientSize && hVisible;
if (typeof _t.getBoundingClientRect === 'function') {
offset = _t.getBoundingClientRect();
width = offset.width;
height = offset.height;
} else {
offset = offset = $t.offset();
width = $t.width();
height = $t.height();
}

return {
top: offset.top + (isNaN(delta.top)? 0 : parseFloat(delta.top) ),
left: offset.left + (isNaN(delta.left)? 0 : parseFloat(delta.left) ),
bottom: offset.top + height + (isNaN(delta.bottom)? 0 : parseFloat(delta.bottom) ),
right: offset.left + width + (isNaN(delta.right)? 0 : parseFloat(delta.right) ),

width: width + (isNaN(delta.width)? 0 : parseFloat(delta.width) ),
height: height + (isNaN(delta.height)? 0 : parseFloat(delta.height) )
};
}

/// Does a visibility check within the parent object, and given offset.
$.fn.visibleFromParentAndOffset = function(parent,offset,partial,hidden,direction){
if (this.length < 1)
return;

var $t = this.length > 1 ? this.eq(0) : this,
_t = $t.get(0);

var viewTop = $w.scrollTop(),
viewBottom = viewTop + vpHeight,
viewLeft = $w.scrollLeft(),
viewRight = viewLeft + vpWidth,
offset = $t.offset(),
_top = offset.top,
_bottom = _top + $t.height(),
_left = offset.left,
_right = _left + $t.width(),
compareTop = partial === true ? _bottom : _top,
compareBottom = partial === true ? _top : _bottom,
compareLeft = partial === true ? _right : _left,
compareRight = partial === true ? _left : _right;

if(direction === 'both')
return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)) && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
else if(direction === 'vertical')
return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop));
else if(direction === 'horizontal')
return !!clientSize && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
/// Does visibility check is needed?
if( !(hidden === true ? (_t.offsetWidth * _t.offsetHeight) > 0 : true) ) {
return false;
}

offset = (offset)? offset : {};
direction = (direction) ? direction : 'both';

var $p = parent.length > 1 ? parent.eq(0) : parent,
tFullOffsets = $t.getFullOffsets(),
pFullOffsets = $p.getFullOffsets( offset );

if( !tFullOffsets || !pFullOffsets ) {
return false;
}

var tViz = tFullOffsets.top >= pFullOffsets.top && tFullOffsets.top < pFullOffsets.bottom,
bViz = tFullOffsets.bottom >= pFullOffsets.top && tFullOffsets.bottom < pFullOffsets.bottom,
//
// partial matching for dom, larger then the parent dom
//
vVisible_large = tFullOffsets.top <= pFullOffsets.top && tFullOffsets.bottom >= pFullOffsets.bottom,
vVisible = partial? tViz || bViz || vVisible_large : tViz && bViz;

if(direction === 'vertical') { //only checks vertical
return vVisible;
}

var lViz = tFullOffsets.left >= pFullOffsets.left && tFullOffsets.left < pFullOffsets.right,
rViz = tFullOffsets.right >= pFullOffsets.right && tFullOffsets.right < pFullOffsets.right,
//
// partial matching for dom, larger then the parent dom
//
hVisible_large = tFullOffsets.left <= pFullOffsets.left && tFullOffsets.right >= pFullOffsets.right,
hVisible = partial? lViz || rViz || hVisible_large : lViz && rViz;

if(direction === 'horizontal') { //only check horizontal
return hVisible;
}

// Assumes check both
return vVisible && hVisible;
};

/// Original syntax support
$.fn.visible = function(partial,hidden,direction){
return this.visibleFromParentAndOffset($("body"), null, partial,hidden,direction);
};

})(jQuery);