diff options
Diffstat (limited to 'src/service/autoScroll.js')
| -rw-r--r-- | src/service/autoScroll.js | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/service/autoScroll.js b/src/service/autoScroll.js new file mode 100644 index 00000000..7b5b28e4 --- /dev/null +++ b/src/service/autoScroll.js @@ -0,0 +1,67 @@ +/** + * @ngdoc function + * @name angular.module.ng.$autoScroll + * @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}. + * + * If `$location` uses `hashbang` url (running in `hashbang` mode or `html5` mode on browser without + * history API support), `$autoScroll` watches the `$location.hash()` and scroll whenever it + * changes. + * + * You can disable `$autoScroll` service by calling `disable()` on `$autoScrollProvider`. + * Note: disabling is only possible before the service is instantiated ! + */ +function $AutoScrollProvider() { + + this.disable = function() { + this.$get = function() {return noop;}; + }; + + 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); + } + + // scroll whenever hash changes (with hashbang url, regular urls are handled by browser) + if ($location instanceof LocationHashbangUrl) { + $rootScope.$watch(function() {return $location.hash();}, function() { + $rootScope.$evalAsync(scroll); + }); + } + + return scroll; + }]; +} + |
