angular is scrollable
by abenrob
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<div ng-app="MyApp">
<div show-scrollable class="outer">
<ul>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>lovely spam</li>
<li>wonderful spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>lovely spam</li>
<li>wonderful spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>lovely spam</li>
<li>wonderful spam</li>
</ul>
</div>
<div show-scrollable class="outer">
<ul>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>spam</li>
<li>lovely spam</li>
<li>wonderful spam</li>
</ul>
</div>
</div>
CSS
.outer {
margin: 20px;
height: 200px;
width: 200px;
}
.scrollableWrapper {
position: relative;
height: inherit;
width: inherit;
overflow: hidden;
border: 1px solid black;
}
.scrollableParentDiv {
padding: 5px 30px 5px 5px;
height: calc(100% - 10px);
width: calc(100% - 10px);
overflow-y: auto;
}
.scrollableArea {
width: 100%;
}
.scrollableMsgPadding {
padding-bottom: 30px;
}
.scrollableScrollMe {
position: absolute;
bottom: -1px;
right: 0px;
left: 0px;
height: 30px;
background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 40%, rgba(255,255,255,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0)), color-stop(40%,rgba(255,255,255,1)), color-stop(100%,rgba(255,255,255,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 40%,rgba(255,255,255,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 40%,rgba(255,255,255,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 40%,rgba(255,255,255,1) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 40%,rgba(255,255,255,1) 100%); /* W3C */
}
.scrollableScrollMe .scrollText {
color: #000;
text-align: center;
font-size: 14px;
font-weight: 600;
font-family: Sans-Serif;
position: absolute;
bottom: 2px;
right: 0;
left: 0;
}
.scrollableScrollMe .scrollText span {
font-size: 10px;
vertical-align: 1px;
}
JavaScript
var scrollDir = angular.module('ScrollDir', []);
// for inserting html in template
scrollDir.filter('unsafe', function($sce) {
return function(val) {
return $sce.trustAsHtml(val);
};
});
scrollDir.constant('directionClasses', {
down: 'fa fa-long-arrow-down',
updown: 'fa fa-arrows-v',
up: 'fa fa-long-arrow-up'
});
scrollDir.directive('showScrollable',['$compile','$timeout','directionClasses', function ($compile,$timeout,directionClasses) {
var template = '<div class="scrollableWrapper">'+
'<div class="scrollableParentDiv">'+
'<div class="scrollableArea" ng-class="{\'scrollableMsgPadding\': scrollable}"'+
'ng-bind-html="content | unsafe"></div>'+
'<div ng-show="scrollable" class="scrollableScrollMe"><div class="scrollText">scroll <span class="{{scrollDir}}"></span></div></div>'+
'</div>'+
'</div>'
function link(scope, element, attrs) {
scope.scrollable = false;
scope.scrollDir = directionClasses.down;
scope.content = element.html();
element.html(template);
$compile(element.contents())(scope);
$timeout(function(){
var scrollContainer = angular.element(element[0].querySelector('.scrollableParentDiv'));
var scrollContainerHeight = scrollContainer[0].offsetHeight;
var scrollContent = angular.element(element[0].querySelector('.scrollableArea'));
var scrollHeight = scrollContent[0].offsetHeight;
if (scrollHeight > scrollContainerHeight){
scope.scrollable = true;
}
scrollContainer.bind("scroll", function () {
if (this.scrollTop + this.offsetHeight >= this.scrollHeight) {
//scroll has reached the bottom
scope.scrollDir = directionClasses.up;
} else if (this.scrollTop == 0) {
//scroll has reached the top
...