<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.gitcdn.xyz/cdn/angular/bower-material/v1.0.0-rc6-master-f73ef23/angular-material.css" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
<link rel="stylesheet" href="style.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-messages.min.js"></script>
<script src="https://cdn.gitcdn.xyz/cdn/angular/bower-material/v1.0.0-rc6-master-f73ef23/angular-material.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="AppCtrl as ctrl"
ng-cloak=""
class="virtualRepeatdemoVerticalUsage"
ng-app="MyApp"
>
<md-content layout="column">
<md-button ng-click="ctrl.handleInterval()">
{{ctrl.intervalActive?"Stop Data Injection":"Inject Data"}}
</md-button>
<md-virtual-repeat-container
md-virtual-repeat-sticky-row=""
id="vertical-container">
<div>Selected Item: {{vpCtrl.selectedItem.item}}</div>
<div ng-click="vpCtrl.selectItem(item)"
ng-class="{selected: (item == vpCtrl.selectedItem.item)}"
md-virtual-repeat="item in ctrl.items"
class="repeated-item" flex="">
{{item}}
</div>
</md-virtual-repeat-container>
</md-content>
</div>
</body>
</html>
// Code goes here
(function () {
'use strict';
angular
.module('MyApp', ['ngMaterial'])
.directive('mdVirtualRepeatStickyRow', function(){
return {
restrict: "A",
controllerAs: "vpCtrl",
controller: function($scope){
},
link: function(scope, element, attr, ctrl){
ctrl.scrollTracking = {};
ctrl.selectItem = function (item){
console.log('Here I am');
ctrl.selectedItem = {
item: item,
index: scope.ctrl.items.indexOf(item)
};
};
scope.ctrl.dataBinding = function(){
if (angular.isUndefined(ctrl.selectedItem)){
return;
}
scope.$evalAsync(function(){
dataBound();
})
}
var dataBound = function(){
// the height + padding top + padding bottom + border top + border bottom
var elementHeight = element.find('.selected').height() + 10 + 0 + 0 + 1;
var currIndex = scope.ctrl.items.indexOf(ctrl.selectedItem.item);
var currentHeight = angular.element(ctrl.scrollTracking.offsetter).height();
var scrollTop = angular.element(ctrl.scrollTracking.viewPort).scrollTop();
scrollTop -= (ctrl.selectedItem.index - currIndex)*elementHeight;
ctrl.selectedItem.index = currIndex;
if (scrollTop > currentHeight){
scrollTop = currentHeight;
}
if (scrollTop < 0){
scrollTop = 0;
}
angular.element(ctrl.scrollTracking.viewPort).scrollTop(scrollTop);
}
var watchStartup = scope.$watch(function(){return element.children().length;}, function(val){
if (val){
ctrl.scrollTracking.viewPort = element.children()[0];
ctrl.scrollTracking.offsetter = element.children().children()[0];
watchStartup();
}
})
}
};
})
.controller('AppCtrl', function($interval) {
var that = this;
this.items = [];
for (var i = 0; i < 20; i++) {
this.items.push(i);
}
that.intervalActive = false;
that.handleInterval = function(){
if (that.intervalActive === false){
that.currInterval = $interval(function(){
that.addData();
}, 500) ;
that.intervalActive = true;
}else{
that.intervalActive = false;
$interval.cancel(that.currInterval);
}
};
this.addData = function(){
for (var i = 0; i < Math.round(Math.random()*10); i++){
that.items.splice(Math.ceil(Math.random()*that.items.length)-1, 0, that.items.length);
}
that.dataBinding();
};
});
})();
/* Styles go here */
.virtualRepeatdemoVerticalUsage #vertical-container {
height: 292px;
width: 400px; }
.selected{
background: gray;
}
.virtualRepeatdemoVerticalUsage .repeated-item {
border-bottom: 1px solid #ddd;
box-sizing: border-box;
height: 40px;
padding-top: 10px; }
.virtualRepeatdemoVerticalUsage md-content {
margin: 16px; }
.virtualRepeatdemoVerticalUsage md-virtual-repeat-container {
border: solid 1px grey; }
.virtualRepeatdemoVerticalUsage .md-virtual-repeat-container .md-virtual-repeat-offsetter {
padding-left: 16px; }