/** * @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
Go to bottom You're at the bottom!
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(); } } #bottom { display: block; margin-top: 2000px; }
*/ 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; }]; }