var app = angular.module("app", []); app.controller("mates", ["$scope", "$http", "$interval", function($scope, $http, $interval) { $scope.mates = 0; $scope.matesText = function() { return $scope.mates == 1 ? "mate" : "mates"; }; $scope.animation = undefined; $scope.countdownStyle = { width: '0%' }; $scope.cooldown = false; $scope.lastMate = ""; $http.get("/mates") .then((r) => { var json = angular.fromJson(r.data); $scope.mates = json.mates; $scope.lastMate = json.lastUpdate; animateCountdown($scope, $interval, json.lastUpdate, json.cooldown); }); $scope.countClick = () => { // Don't bother updating during a cooldown if ($scope.cooldown) return; $http.post("/mates") .then((r) => { var json = angular.fromJson(r.data); // Check if this was sent to early if (json.error || r.status != 200) return; $scope.mates = json.mates; $scope.lastMate = json.lastUpdate; animateCountdown($scope, $interval, json.lastUpdate, json.cooldown); }); }; }]); function animateCountdown($scope, $interval, lastUpdate, cooldown) { var lastUpdateDate = new Date(lastUpdate) var difference = timeSince(lastUpdateDate); // Check if there is a cooldown in progress if (difference < cooldown) { // Make sure there is no animation in progress before proceeding if (angular.isDefined($scope.animation)) return; // Run callback immediately as an interval workaround cooldownIntervalCallback($scope, $interval, lastUpdateDate, cooldown); // Set the interval $scope.animation = $interval(() => { cooldownIntervalCallback($scope, $interval, lastUpdateDate, cooldown); }, 1000); } } function cooldownIntervalCallback($scope, $interval, lastUpdateDate, cooldown) { var difference = timeSince(lastUpdateDate); if (difference >= cooldown) { // Cancel the interval if it exists and clear it if (angular.isDefined($scope.animation)) $interval.cancel($scope.animation); $scope.animation = undefined; // Reset the countdown bar $scope.countdownStyle = { width: '0%' }; // Reset the cooldown flag $scope.cooldown = false; } else { // Set the style based on the remaining percent $scope.countdownStyle = { width: ((cooldown - difference) / cooldown) * 100 + '%' }; // Set the cooldown flag $scope.cooldown = true; } } function timeSince(date) { return Math.ceil((new Date().getTime() - date.getTime()) / 1000); }