Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 3a86605

Browse files
committed
ANCHOR SCROLL: WIP - feat($anchorScroll): add support for configurable
scroll offset Updated the docs and implemented the dynamic scroll offset in the docs app in a more proper way (introduced the `scrollOffset` module as well). There seems to be an issue with the current implementation, as `window.scrollBy()` does not work when the "scrolled" element is lower in the DOM hierarchy.
1 parent 5da40bd commit 3a86605

File tree

5 files changed

+112
-18
lines changed

5 files changed

+112
-18
lines changed

docs/app/src/app.js

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,11 @@ angular.module('docsApp', [
1313
'search',
1414
'tutorials',
1515
'versions',
16+
'scrollOffset',
1617
'bootstrap',
1718
'ui.bootstrap.dropdown'
1819
])
1920

2021
.config(['$locationProvider', function($locationProvider) {
2122
$locationProvider.html5Mode(true).hashPrefix('!');
22-
}])
23-
24-
.config(['$anchorScrollProvider', function($anchorScrollProvider) {
25-
var header;
26-
$anchorScrollProvider.setScrollOffset(function () {
27-
header = header || window.document.querySelector('header');
28-
if (!header) return 0;
29-
30-
var style = window.getComputedStyle(header);
31-
return (style.position === 'fixed') ? header.offsetHeight : 0;
32-
});
3323
}]);

docs/app/src/directives.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,3 @@ angular.module('directives', [])
2929
}
3030
};
3131
});
32-

docs/app/src/scroll-offset.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
angular.module('scrollOffset', [])
2+
3+
/**
4+
* scrollOffsetElement Directive
5+
*
6+
* @description Store the element whose height should be used to determine the scroll offset and its
7+
* computed style.
8+
*/
9+
.directive('scrollOffsetElement', ['$window', 'SCROLL_OFFSET_ELEMENT',
10+
function scrollOffsetElementDirective($window, SCROLL_OFFSET_ELEMENT) {
11+
return {
12+
restrict: 'A',
13+
link: function scrollOffsetElementPostLink(scope, elem) {
14+
elem = elem[0];
15+
SCROLL_OFFSET_ELEMENT.element = elem;
16+
SCROLL_OFFSET_ELEMENT.computedStyle = $window.getComputedStyle(elem);
17+
// README: Using `getComputedStyle()` renders this approach incompatible with IE8.
18+
}
19+
};
20+
}
21+
])
22+
23+
.constant('SCROLL_OFFSET_ELEMENT', {
24+
element: null, // README: This is not used, but keeping it here just in case...
25+
computedStyle: null
26+
})
27+
28+
.config(['$anchorScrollProvider', 'SCROLL_OFFSET_ELEMENT',
29+
function($anchorScrollProvider, SCROLL_OFFSET_ELEMENT) {
30+
var extraTopSpace = 15;
31+
$anchorScrollProvider.setScrollOffset(function () {
32+
var computedStyle = SCROLL_OFFSET_ELEMENT.computedStyle;
33+
34+
if (!computedStyle || (computedStyle.position !== 'fixed')) return 0;
35+
36+
return parseInt(computedStyle.height, 10) + extraTopSpace;
37+
});
38+
}
39+
]);

docs/config/templates/indexPage.template.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
</head>
7171
<body>
7272
<div id="wrapper">
73-
<header class="header header-fixed">
73+
<header class="header header-fixed" scroll-offset-element>
7474
<section class="navbar navbar-inverse docs-navbar-primary" ng-controller="DocsSearchCtrl">
7575
<div class="container">
7676
<div class="row">

src/ng/anchorScroll.js

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
* It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
1717
* This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
1818
*
19+
* Additionally, you can specify a scroll offset (in pixels) during the configuration phase by
20+
* calling `$anchorScrollProvider.setScrollOffset(<valueOrGetter>)`. The offset can be either a
21+
* fixed value or a getter function that returns a value dynamically.
22+
*
1923
* @example
2024
<example module="anchorScrollExample">
2125
<file name="index.html">
@@ -50,8 +54,71 @@
5054
}
5155
</file>
5256
</example>
57+
*
58+
* <hr />
59+
* The example below illustrates the use of scroll offset (specified as a fixed value).
60+
*
61+
* @example
62+
<example module="anchorScrollOffsetExample">
63+
<file name="index.html">
64+
<div class="scroll-area">
65+
<div class="fixed-header" ng-controller="headerCtrl">
66+
<a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
67+
Go to anchor {{x}}
68+
</a>
69+
</div>
70+
<div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
71+
Anchor {{x}} of 5
72+
</div>
73+
</div>
74+
</file>
75+
<file name="script.js">
76+
angular.module('anchorScrollOffsetExample', [])
77+
.config(['$anchorScrollProvider', function($anchorScrollProvider) {
78+
$anchorScrollProvider.setScrollOffset(50); // always scroll by 50 extra pixels
79+
}])
80+
.controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
81+
function ($anchorScroll, $location, $scope) {
82+
$scope.gotoAnchor = function(x) {
83+
// Set the location.hash to the id of
84+
// the element you wish to scroll to.
85+
$location.hash('anchor' + x);
86+
87+
// Call $anchorScroll()
88+
$anchorScroll();
89+
};
90+
}
91+
]);
92+
</file>
93+
<file name="style.css">
94+
.anchor {
95+
border: 2px dashed DarkOrchid;
96+
padding-bottom: 200px;
97+
}
98+
99+
.fixed-header {
100+
background-color: rgba(0, 0, 0, 0.2);
101+
height: 50px;
102+
position: fixed;
103+
top: 0; left: 0; right: 0;
104+
}
105+
106+
.fixed-header > a {
107+
display: inline-block;
108+
margin: 5px 15px;
109+
}
110+
111+
.scroll-area {
112+
height: 230px;
113+
overflow: auto;
114+
padding-top: 50px;
115+
}
116+
</file>
117+
</example>
53118
*/
54119
function $AnchorScrollProvider() {
120+
// TODO(gkalpak): The $anchorScrollProvider should be documented as well
121+
// (under the providers section).
55122

56123
var DEFAULT_OFFSET = 0;
57124

@@ -88,14 +155,13 @@ function $AnchorScrollProvider() {
88155
function scrollTo(elem) {
89156
if (elem) {
90157
elem.scrollIntoView();
158+
var offset = scrollOffsetGetter();
159+
if (offset) {
160+
$window.scrollBy(0, -1 * offset);
161+
}
91162
} else {
92163
$window.scrollTo(0, 0);
93164
}
94-
95-
var offset = scrollOffsetGetter();
96-
if (offset) {
97-
$window.scrollBy(0, -1 * offset);
98-
}
99165
}
100166

101167
function scroll() {

0 commit comments

Comments
 (0)