Skip to content

Instantly share code, notes, and snippets.

@lperrin
Created November 24, 2013 15:06
Show Gist options
  • Save lperrin/7628223 to your computer and use it in GitHub Desktop.
Save lperrin/7628223 to your computer and use it in GitHub Desktop.
frontApp.directive('fastScroll', ['$parse', function ($parse) {
var Interval = function(min, max) {
this.min = min || 0;
this.max = max || 0;
};
Interval.prototype.clip = function(min, max) {
if(this.max <= min || this.min >= max) {
this.min = this.max = 0;
return;
}
this.min = Math.max(this.min, min);
this.max = Math.min(this.max, max);
};
Interval.prototype.expand = function(i) {
this.min -= i;
this.max += i;
};
return {
link: function (scope, element, attrs) {
var cellHeight = parseInt(attrs.cellHeight, 10),
getter = $parse(attrs.faFastScroll);
function getVisibles(collection) {
var offset = element.scrollTop(),
range = element.height();
// strictly visible bounds
var visibles = new Interval(
Math.floor(offset / cellHeight) - 1,
Math.floor((offset + range - 1) / cellHeight)
);
// expand a bit to avoid flickers
visibles.expand(15);
visibles.clip(0, collection.length);
return visibles;
}
function updatePartialView(needDigest) {
var collection = getter(scope);
if (!collection) {
scope.partial = [];
return;
}
var visibles = getVisibles(collection);
scope.partial = collection.slice(visibles.min, visibles.max);
scope.top = visibles.min * cellHeight;
scope.bottom = (collection.length - visibles.max) * cellHeight;
// updatePartialView will be called a lot when scrolling.
// prevent $digest from propagating to individual items to save time.
if (needDigest) {
scope.$broadcast('suspend');
scope.$digest();
scope.$broadcast('resume');
}
}
element.on('scroll', function () {
updatePartialView(true);
});
scope.$watchCollection(attrs.faFastScroll, function () {
// we're already in a $digest
updatePartialView(false);
});
}
};
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment