discourse/app/assets/javascripts/discourse/lib/eyeline.js.es6
2015-08-13 12:42:57 +02:00

72 lines
2.1 KiB
JavaScript

// Track visible elemnts on the screen.
const Eyeline = function Eyeline(selector) {
this.selector = selector;
};
Eyeline.prototype.update = function() {
if (Ember.testing) { return; }
const docViewTop = $(window).scrollTop(),
windowHeight = $(window).height(),
docViewBottom = docViewTop + windowHeight,
$elements = $(this.selector),
bottomOffset = $elements.last().offset(),
self = this;
let atBottom = false;
if (bottomOffset) {
atBottom = (bottomOffset.top <= docViewBottom) && (bottomOffset.top >= docViewTop);
}
return $elements.each(function(i, elem) {
const $elem = $(elem),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
let markSeen = false;
// Make sure the element is visible
if (!$elem.is(':visible')) return true;
// It's seen if...
// ...the element is vertically within the top and botom
if ((elemTop <= docViewBottom) && (elemTop >= docViewTop)) markSeen = true;
// ...the element top is above the top and the bottom is below the bottom (large elements)
if ((elemTop <= docViewTop) && (elemBottom >= docViewBottom)) markSeen = true;
// ...we're at the bottom and the bottom of the element is visible (large bottom elements)
if (atBottom && (elemBottom >= docViewTop)) markSeen = true;
if (!markSeen) return true;
// If you hit the bottom we mark all the elements as seen. Otherwise, just the first one
if (!atBottom) {
self.trigger('saw', { detail: $elem });
if (i === 0) {
self.trigger('sawTop', { detail: $elem });
}
return false;
}
if (i === 0) {
self.trigger('sawTop', { detail: $elem });
}
if (i === ($elements.length - 1)) {
return self.trigger('sawBottom', { detail: $elem });
}
});
};
// Call this when we know aren't loading any more elements. Mark the rest as seen
Eyeline.prototype.flushRest = function() {
if (Ember.testing) { return; }
const self = this;
$(this.selector).each(function(i, elem) {
return self.trigger('saw', { detail: $(elem) });
});
};
RSVP.EventTarget.mixin(Eyeline.prototype);
export default Eyeline;