2 changed files with 135 additions and 2 deletions
@ -0,0 +1,134 @@ |
|||
/** |
|||
* author Christopher Blum |
|||
* - based on the idea of Remy Sharp, http://remysharp.com/2009/01/26/element-in-view-event-plugin/
|
|||
* - forked from http://github.com/zuk/jquery.inview/
|
|||
*/ |
|||
(function ($) { |
|||
var inviewObjects = {}, viewportSize, viewportOffset, |
|||
d = document, w = window, documentElement = d.documentElement, expando = $.expando, isFiring = false, $elements = {}; |
|||
|
|||
$.event.special.inview = { |
|||
add: function(data) { |
|||
var inviewObject = { data: data, $element: $(this) } |
|||
inviewObjects[data.guid + "-" + this[expando]] = inviewObject; |
|||
var selector = inviewObject.data.selector, |
|||
$element = inviewObject.$element; |
|||
var hash = parseInt(getHash( data.guid + this[expando])); |
|||
$elements[hash] = selector ? $element.find(selector) : $element; |
|||
}, |
|||
|
|||
remove: function(data) { |
|||
try { delete inviewObjects[data.guid + "-" + this[expando]]; } catch(e) {} |
|||
try { |
|||
var hash = parseInt(getHash(data.guid + this[expando])); |
|||
delete($elements[hash]); |
|||
} catch (e){} |
|||
} |
|||
}; |
|||
|
|||
|
|||
function getHash(str){ |
|||
str = str+''; |
|||
var hash = 0; |
|||
if (str.length == 0) return hash; |
|||
for (i = 0; i < str.length; i++) { |
|||
char = str.charCodeAt(i); |
|||
hash = ((hash<<5)-hash)+char; |
|||
hash = hash & hash; // Convert to 32bit integer
|
|||
} |
|||
return Math.abs(hash); |
|||
} |
|||
|
|||
function getViewportSize() { |
|||
var mode, domObject, size = { height: w.innerHeight, width: w.innerWidth }; |
|||
|
|||
// if this is correct then return it. iPad has compat Mode, so will
|
|||
// go into check clientHeight/clientWidth (which has the wrong value).
|
|||
if (!size.height) { |
|||
mode = d.compatMode; |
|||
if (mode || !$.support.boxModel) { // IE, Gecko
|
|||
domObject = mode === 'CSS1Compat' ? |
|||
documentElement : // Standards
|
|||
d.body; // Quirks
|
|||
size = { |
|||
height: domObject.clientHeight, |
|||
width: domObject.clientWidth |
|||
}; |
|||
} |
|||
} |
|||
|
|||
return size; |
|||
} |
|||
|
|||
function getViewportOffset() { |
|||
return { |
|||
top: w.pageYOffset || documentElement.scrollTop || (d.body?d.body.scrollTop:0), |
|||
left: w.pageXOffset || documentElement.scrollLeft || (d.body?d.body.scrollLeft:0) |
|||
}; |
|||
} |
|||
|
|||
function checkInView() { |
|||
if (isFiring){ |
|||
return; |
|||
} |
|||
isFiring = true; |
|||
viewportSize = viewportSize || getViewportSize(); |
|||
viewportOffset = viewportOffset || getViewportOffset(); |
|||
|
|||
for (var i in $elements) { |
|||
if (isNaN(parseInt(i))) { |
|||
continue; |
|||
} |
|||
|
|||
var $element = $($elements[i]), |
|||
elementSize = { height: $element.height(), width: $element.width() }, |
|||
elementOffset = $element.offset(), |
|||
inView = $element.data('inview'), |
|||
visiblePartX, |
|||
visiblePartY, |
|||
visiblePartsMerged; |
|||
|
|||
// Don't ask me why because I haven't figured out yet:
|
|||
// viewportOffset and viewportSize are sometimes suddenly null in Firefox 5.
|
|||
// Even though it sounds weird:
|
|||
// It seems that the execution of this function is interferred by the onresize/onscroll event
|
|||
// where viewportOffset and viewportSize are unset
|
|||
if (!viewportOffset || !viewportSize) { |
|||
isFiring = false; |
|||
return; |
|||
} |
|||
|
|||
if (elementOffset.top + elementSize.height > viewportOffset.top && |
|||
elementOffset.top < viewportOffset.top + viewportSize.height && |
|||
elementOffset.left + elementSize.width > viewportOffset.left && |
|||
elementOffset.left < viewportOffset.left + viewportSize.width) { |
|||
visiblePartX = (viewportOffset.left > elementOffset.left ? |
|||
'right' : (viewportOffset.left + viewportSize.width) < (elementOffset.left + elementSize.width) ? |
|||
'left' : 'both'); |
|||
visiblePartY = (viewportOffset.top > elementOffset.top ? |
|||
'bottom' : (viewportOffset.top + viewportSize.height) < (elementOffset.top + elementSize.height) ? |
|||
'top' : 'both'); |
|||
visiblePartsMerged = visiblePartX + "-" + visiblePartY; |
|||
if (!inView || inView !== visiblePartsMerged) { |
|||
$element.data('inview', visiblePartsMerged).trigger('inview', [true, visiblePartX, visiblePartY]); |
|||
} |
|||
} else if (inView) { |
|||
$element.data('inview', false).trigger('inview', [false]); |
|||
} |
|||
} |
|||
isFiring = false; |
|||
} |
|||
|
|||
$(w).bind("scroll resize", function() { |
|||
viewportSize = viewportOffset = null; |
|||
}); |
|||
|
|||
// Use setInterval in order to also make sure this captures elements within
|
|||
// "overflow:scroll" elements or elements that appeared in the dom tree due to
|
|||
// dom manipulation and reflow
|
|||
// old: $(window).scroll(checkInView);
|
|||
//
|
|||
// By the way, iOS (iPad, iPhone, ...) seems to not execute, or at least delays
|
|||
// intervals while the user scrolls. Therefore the inview event might fire a bit late there
|
|||
setInterval(checkInView, 250); |
|||
})(jQuery); |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue