StackOverflow_25839711: how-to-know-which-is-the-top-element-showing-in-div
Illustration of answer to http://stackoverflow.com/questions/25839711/how-to-know-which-is-the-top-element-showing-in-div.
by ExpertSystem
HTML
<script src="http://code.angularjs.org/1.2.24/angular.min.js"></script>
<div ng-controller="mainCtrl">
<pre>Closest to .inner-div's top: {{closestToTop}}</pre>
<hr />
<div class="outer-div">
<div class="inner-div" detect-closest-to-top="true">
<div class="item" ng-repeat="item in [1,2,3,4,5,6,7,8,9,10]">
Item {{item}}
</div>
</div>
</div>
</div>
<!-- -=-=-=-=- -=[IGNORE BELOW THIS LINE]=- -=-=-=-=- -->
<!-- Page Footer -->
<small class="footer" ng-controller="footerCtrl">
<b>Angular v{{version.full}}</b> ({{version.codeName}})
<span class="right">
©
<a ng-href="{{author.url}}" target="_blank">{{author.name}}</a>
</span>
</small>
CSS
body {
padding: 10px;
}
.outer-div {
border: 2px dotted ForestGreen;
height: 100px;
overflow-y: scroll;
padding: 10px;
}
.inner-div {
border: 2px dotted DarkOrchid;
height: 300px;
overflow-y: scroll;
padding: 10px;
}
.item {
border: 1px dashed LimeGreen;
height: 50px;
margin: 5px;
}
/* -=-=-=-=- -=[IGNORE BELOW THIS LINE]=- -=-=-=-=- */
/* Page Footer */
body { padding-bottom: 22px; }
.footer { background-color: White; border-top: 1px solid rgba(100, 100, 100, 0.33); bottom: 0; display: block; font-size: 0.75em; height: 20px; left: 0; margin: 0 5px; overflow: auto; padding: 5px; position: fixed; right: 0; }
.right { float: right; }
JavaScript
var app = angular.module('myApp', []);
app.controller('mainCtrl', function ($scope) {
});
app.directive('detectClosestToTop', function ($timeout) {
function findClosest(root, verbose) {
var log = verbose ? console.log.bind(console) : function () {};
var closestElem;
var closestTop = root.scrollHeight;
var minTop = root.offsetTop + root.scrollTop;
log('Min top:', minTop);
[].forEach.call(root.children, function (child) {
var childTop = child.offsetTop;
if ((childTop >= minTop) && (childTop < closestTop)) {
closestElem = child;
closestTop = childTop;
}
log(childTop, child.textContent.trim());
});
log('Closest:', closestTop, ((closestElem || {}).textContent || '').trim());
return closestElem;
}
return {
restrict: 'A',
link: function (scope, elem, attrs) {
var verboseVal = angular.lowercase(attrs.detectClosestToTop);
var verbose = ['true', '1', 'yes', 'on'].indexOf(verboseVal) !== -1;
function detectClosest() {
var closestToTop = findClosest(elem[0], verbose) || {};
scope.closestToTop = (closestToTop.textContent || '').trim();
}
function onScroll() {
scope.$apply(detectClosest);
}
elem.on('scroll', onScroll);
scope.$on('$destroy', function () {
elem.off('scroll', onScroll);
});
$timeout(detectClosest);
}
};
});
/* -=-=-=-=- -=[IGNORE BELOW THIS LINE]=- -=-=-=-=- */
/* Page Footer */
app.controller('footerCtrl', function ($scope) {
$scope.version = angular.version;
$scope.author = {
name: 'ExpertSystem',
url: '//stackoverflow.com/users/2341938/expertsystem'
};
});