I'm uncertain about the appropriate title for this inquiry, so please correct me if I am mistaken.
Suppose that upon page refresh (load), I require an animated scroll to an anchor based on the current location's hash (I am aware of ngAnchorScroll, but I specifically need animated scrolling, which ngAnchorScorll cannot accomplish).
To achieve this, I have created a service that will be called upon controller initialization:
var Ctrl = function ($scope, initAnchorScrolling) {
initAnchorScrolling($scope);
};
Ctrl.$inject = ['$scope', "initAnchorScrolling"];
applicationServices.factory("initAnchorScrolling",
['scroll', '$location', '$timeout', function(scrollUtils, $location, $timeout) {
return function(scope) {
/** Some stuff here */
function scroll() {
var hash = $location.hash(), elm;
if (!hash) {
scrollUtils.scrollTo(0, 0);
} else if ((elm = getAnchorElement(hash))) {
scrollUtils.scrollToElement(elm);
} else {
scrollUtils.scrollTo(0, 0);
}
}
scope.$watch(function scrollWatch() { return $location.hash(); },
function scrollWatchAction() {
$timeout(function () {
scroll();
}, 0, true);
});
};
}]);
You can observe that this anchor implementation is very similar to ngAnchorScroll. The main distinction is that I utilize jQuery.animate() to transition between anchors.
According to my understanding from here, in order to delay function execution until the browser has finished rendering, one simply needs to call the $timeout service with a delay parameter set to 0. However, this method is not proving effective for me. Occasionally, the page scrolls to different positions unexpectedly. I attribute this issue to the fact that the scroll function is invoked before the digest cycle completes synchronization of views and models—the HTML blocks therefore possess inaccurate height and position at the time of invocation.
Hence, my query: is there a way to defer function invocation until the moment when the browser has fully completed rendering and the digest cycle has synchronized views and models (applied bindings)?