mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-23 09:50:24 +00:00
Per a request made by Peter Bacon Darwin here: http://www.benlesh.com/2013/02/angular-js-scrolling-to-element-by-id.html?showComment=1370941217879#c8718313084813008967
95 lines
2.9 KiB
JavaScript
95 lines
2.9 KiB
JavaScript
/**
|
|
* @ngdoc function
|
|
* @name ng.$anchorScroll
|
|
* @requires $window
|
|
* @requires $location
|
|
* @requires $rootScope
|
|
*
|
|
* @description
|
|
* When called, it checks current value of `$location.hash()` and scroll to related element,
|
|
* according to rules specified in
|
|
* {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.
|
|
*
|
|
* It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
|
|
* This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
|
|
*
|
|
* @example
|
|
<example>
|
|
<file name="index.html">
|
|
<div ng-controller="MainCtrl">
|
|
<a ng-click="gotoBottom()">Go to bottom</a>
|
|
<a id="bottom"></a> You're at the bottom!
|
|
</div>
|
|
</file>
|
|
<file name="script.js">
|
|
function ScrollCtrl($scope, $location, $anchorScroll) {
|
|
$scope.gotoBottom = function (){
|
|
// set the location.hash to the id of
|
|
// the element you wish to scroll to.
|
|
$location.hash('bottom');
|
|
|
|
// call $anchorScroll()
|
|
$anchorScroll();
|
|
}
|
|
}
|
|
</file>
|
|
<file name="style.css">
|
|
#bottom {
|
|
display: block;
|
|
margin-top: 2000px;
|
|
}
|
|
</file>
|
|
</example>
|
|
*/
|
|
function $AnchorScrollProvider() {
|
|
|
|
var autoScrollingEnabled = true;
|
|
|
|
this.disableAutoScrolling = function() {
|
|
autoScrollingEnabled = false;
|
|
};
|
|
|
|
this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
|
|
var document = $window.document;
|
|
|
|
// helper function to get first anchor from a NodeList
|
|
// can't use filter.filter, as it accepts only instances of Array
|
|
// and IE can't convert NodeList to an array using [].slice
|
|
// TODO(vojta): use filter if we change it to accept lists as well
|
|
function getFirstAnchor(list) {
|
|
var result = null;
|
|
forEach(list, function(element) {
|
|
if (!result && lowercase(element.nodeName) === 'a') result = element;
|
|
});
|
|
return result;
|
|
}
|
|
|
|
function scroll() {
|
|
var hash = $location.hash(), elm;
|
|
|
|
// empty hash, scroll to the top of the page
|
|
if (!hash) $window.scrollTo(0, 0);
|
|
|
|
// element with given id
|
|
else if ((elm = document.getElementById(hash))) elm.scrollIntoView();
|
|
|
|
// first anchor with given name :-D
|
|
else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();
|
|
|
|
// no element and hash == 'top', scroll to the top of the page
|
|
else if (hash === 'top') $window.scrollTo(0, 0);
|
|
}
|
|
|
|
// does not scroll when user clicks on anchor link that is currently on
|
|
// (no url change, no $location.hash() change), browser native does scroll
|
|
if (autoScrollingEnabled) {
|
|
$rootScope.$watch(function autoScrollWatch() {return $location.hash();},
|
|
function autoScrollWatchAction() {
|
|
$rootScope.$evalAsync(scroll);
|
|
});
|
|
}
|
|
|
|
return scroll;
|
|
}];
|
|
}
|
|
|