ui.bootstrap.affix
HTML
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.3/angular.js"></script>
<div class="page-header container">
<h2>Affix bootstrap directive example. </h2>
<b>Features</b>:<br>
<ul>
<li>flexible classes and naming convention</li>
<li>no jquery dependancy, only Angular js. <code>$scope.$root.isIE</code> should be defined for default IE compatibility</li>
<li>vertical affix, Top only currently</li>
<li>offset scroll containers from the root document scroll</li>
</ul>
</br><b>HTML:</b><br>
<code>
<div id="affixMe" affix="" ng-class="{affix:affixed}" ng-style="offset" relative-to="affix-demo" ></div>
</code>
</br><i>Check html window for full example code</i></br>
</br></br><b>Usage:</b><br>
<ul>
<li> 'ng-class="{affix:affixed}"': bind a class to the affixed boolean </li>
<li> 'ng-style="offset"' used to set the top offset of the affixed element </li>
<li> 'relative-to': specify the id of an element you want affix to be relative to </li>
</ul>
</div>
<!-- BEGIN EXAMPLE -->
<div class="container" id="affix-demo">
<!-- Filler top -->
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>...</p>
<p><a class="btn btn-primary btn-lg" role="button">Learn more</a></p>
</div>
<!-- Affix directive -->
<div id="affixMe" affix="" ng-class="{affix:affixed}" ng-style="offset" relative-to="affix-demo">
<div class="well">
Am I affixed? {{affixed ? 'yes' : 'no'}}
</div>
</div>
<!-- Filler bottom -->
<div id="stretch"></div>
</div>
<!-- END EXAMPLE -->
CSS
#affix-demo {
-margin-top:30px;
height: 200px;
overflow-y:scroll;
background: lightblue;
}
#affixMe{
width: 200px;
}
#affixMe.affix {
top: 0px;
}
#stretch {
height: 500px;
}
JavaScript
myApp = {};
angular.module('myApp', ['ui.bootstrap.affix']);
console.log('find me');
angular.module('ui.bootstrap.affix', [])
.directive('affix', ['$window', function ($window) {
return {
$scope: true,
link: function ($scope, $element, $attrs) {
var relativeTo = // overide or use default: body (html for IE) element
!!$attrs.relativeTo ? angular.element(window.document.getElementById($attrs.relativeTo)) :
!$scope.$root.isIE ? // specify your own isIE check will default to body element
angular.element(window.document.getElementsByTagName('body')) :
angular.element(window.document.getElementsByTagName('html')), // required by IE
win = !!$attrs.relativeTo ? relativeTo : angular.element($window),
// if a relativeTo other than the default is set we will
// offset the affixed position by it's offset
relativeToOffset = null,
fixedAt = null;
// boolean
$scope.affixed = true;
$scope.offset = 0;
// Obviously, whenever a scroll occurs, we need to check and possibly
// adjust the position of the affixed $element.
win.bind('scroll', checkPosition);
// on resize recalculate fixedAt position
win.bind('resize', function () {
$scope.$apply(function () {
$scope.affixed = false;
});
relativeToOffset = null;
fixedAt = null;
checkPosition();
});
// calculate if we need to affix element
function checkPosition() {
relativeToOffset = relativeToOffset || win[0].offsetTop;
fixedAt = fixedAt || $element[0].offsetTop - relativeToOffset;
$scope.$apply(function () {
...