AngularJS - Smooth Anchor Scroll

by Nivaldo

HTML

<div ng-app="app">
<div id="scrollArea" ng-controller="ScrollCtrl">
    
    <a ng-click="gotoElement('middle')">Go to middle</a><br/>
    <a ng-click="gotoElement('bottom')">Go to bottom</a><br/>
    <a ng-click="gotoElement('bottle')">Go to bottle</a>
    
    <p>Keffiyeh locavore aesthetic trust fund. Fingerstache irony Truffaut gastropub, cliche chambray gentrify. PBR&B raw denim kogi, tote bag cardigan Tumblr Neutra readymade Odd Future vinyl. Small batch single-origin coffee swag selvage, Blue Bottle occupy try-hard. Carles tote bag meggings Cosby sweater. Yr Vice photo booth put a bird on it, slow-carb kale chips locavore. Banh mi High Life biodiesel, Tonx fanny pack plaid Terry Richardson ennui small batch.</p>

<p>Single-origin coffee butcher next level, umami chia cornhole hashtag four loko PBR fashion axe sustainable. Church-key High Life sartorial butcher, hella +1 Intelligentsia chambray Wes Anderson Terry Richardson leggings Helvetica stumptown brunch gentrify. Schlitz pour-over whatever cray, bicycle rights semiotics tousled try-hard hella selvage. Banksy next level art party, swag church-key Etsy bicycle rights hella synth hoodie Williamsburg Brooklyn letterpress meh stumptown. Slow-carb lo-fi umami, 3 wolf moon vegan PBR banh mi pop-up. Semiotics kogi photo booth occupy next level mumblecore Banksy master cleanse, asymmetrical chia forage vinyl swag. Leggings beard shabby chic 3 wolf moon cray, farm-to-table skateboard you probably haven't heard of them small batch squid mlkshk +1 banjo flannel pour-over.</p>

<div id="bottle">Bootle</div>
<p>Blue Bottle occupy Vice hella, four loko cornhole plaid Tumblr Etsy readymade +1 irony Tonx distillery. Raw denim kogi umami, pickled bicycle rights Marfa Williamsburg Neutra Terry Richardson 3 wolf moon. Lomo selvage DIY, Wes Anderson Banksy biodiesel four loko aesthetic pop-up kogi kitsch brunch Tumblr Truffaut. Cray church-key meggings organic 3 wolf moon before they sold out. Photo booth trust fund raw...

JavaScript

var $scope, $location;
var app = angular.module('app', []);

app.service('anchorSmoothScroll', function(){
    
    this.scrollTo = function(eID) {

        // This scrolling function 
        // is from http://www.itnewb.com/tutorial/Creating-the-Smooth-Scroll-Effect-with-JavaScript
        
        var startY = currentYPosition();
        var stopY = elmYPosition(eID);
        var distance = stopY > startY ? stopY - startY : startY - stopY;
        if (distance < 100) {
            scrollTo(0, stopY); return;
        }
        var speed = Math.round(distance / 10);
        if (speed >= 20) speed = 20;
        var step = Math.round(distance / 25);
        var leapY = stopY > startY ? startY + step : startY - step;
        var timer = 0;
        if (stopY > startY) {
            for ( var i=startY; i<stopY; i+=step ) {
                setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
                leapY += step; if (leapY > stopY) leapY = stopY; timer++;
            } return;
        }
        for ( var i=startY; i>stopY; i-=step ) {
            setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
            leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
        }
        
        function currentYPosition() {
            // Firefox, Chrome, Opera, Safari
            if (self.pageYOffset) return self.pageYOffset;
            // Internet Explorer 6 - standards mode
            if (document.documentElement && document.documentElement.scrollTop)
                return document.documentElement.scrollTop;
            // Internet Explorer 6, 7 and 8
            if (document.body.scrollTop) return document.body.scrollTop;
            return 0;
        }
        
        function elmYPosition(eID) {
            var elm = document.getElementById(eID);
            var y = elm.offsetTop;
            var node = elm;
            while (node.offsetParent && node.offsetParent != document.body) {
                node = node.offsetParent;
          ...