Skip to content

Instantly share code, notes, and snippets.

@albulescu
Last active August 29, 2015 14:11
Show Gist options
  • Save albulescu/5a236ed7480c5ecd709a to your computer and use it in GitHub Desktop.
Save albulescu/5a236ed7480c5ecd709a to your computer and use it in GitHub Desktop.
Angular AutoScroll Directive
/*
$scope.autoScrollEnabled = true;
$scope.onSendMessage = function() {
// enable autoscrolling in case is disabled by user scroll up
$scope.$emit('$enableAutoScroll');
};
$scope.onAutoScroll = function( event ) {
// Use this callback if you want to update
// async or if you have custom scroll
if(!customScrollLoaded)
{
var deferer = $q.defer();
//when custom scroll loaded satisfy the promise
customScroll.on('load', function(){
deferer.resolve();
});
//wait until custom scroll loaded
event.preventDefault();
return deferer.promise;
}
};
...
<div auto-scroll="autoScrollEnabled" auto-scroll-trigger="onAutoScroll($event)"></div>
*/
angular.module('YourModule').directive('autoScroll', function( $timeout, $q, $parse, $log ){
return {
restrict : 'A',
link : function(scope, element, attributes) {
if( element.css('overflow') !== 'auto' ) {
return $log.warn('Element is not scrollable. Auto scroll has no sense!');
}
var externalAutoScroll = scope.$eval(attributes.autoScroll);
var autoscroll = externalAutoScroll || true;
var updateTimeout;
var AutoScrollEvent = function(element) {
var defaultPrevented = false;
this.target = element;
this.preventDefault = function(){
defaultPrevented = true;
};
this.isDefaultPrevented = function() {
return defaultPrevented;
};
};
scope.$on('$enableAutoScroll', function(){
if(!autoscroll) {
$log.info('Enable autoscroll');
}
autoscroll=true;
});
scope.$on('$disableAutoScroll', function(){
if(autoscroll) {
$log.info('Disable autoscroll');
}
autoscroll=false;
});
element.on('wheel', function(event){
var delta = event.originalEvent.detail?
event.originalEvent.detail*(-120) :
event.originalEvent.wheelDelta;
if( delta > 0 ) {
if( autoscroll ) {
$log.info('Disable autoscroll');
}
autoscroll = false;
return;
}
if( element.get(0).scrollTop >= element.get(0).scrollHeight - element.height()) {
if(!autoscroll) {
$log.info('Enable autoscroll');
}
autoscroll = true;
}
});
element.on('DOMNodeInserted', function( event ){
var whatsNew = event.srcElement||event.target/*firefox*/;
var container = event.delegateTarget;
if( whatsNew.nodeType === 1 &&
autoscroll === true &&
externalAutoScroll === true)
{
//cancel last update scroll position timeout
$timeout.cancel(updateTimeout);
//create new update scroll position timeout
updateTimeout = $timeout(function(){
//create event for auto-scroll-trigger parameter
var event = new AutoScrollEvent(element);
var locals = { $event : event };
// fire callback
var fn = $parse(attributes.autoScrollTrigger)||angular.noop;
var promise = fn(scope, locals);
if( promise ) {
$q.when(promise).then(function(){
$log.info('Auto scroll to down');
container.scrollTop = container.scrollHeight;
});
}
if(!event.isDefaultPrevented()) {
$log.info('Auto scroll to down');
container.scrollTop = container.scrollHeight;
}
});
}
});
}
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment