0

I am trying to make a button that executes a action immediately after he was clicked. But if the mouse is still down after a timeout the action should be repeated as long as the button is down.

In the following code the $interval is working. But somehow the $timeout gets ignored and the interval starts immediately. What am I doing wrong?

angular
  .module('myApp', [])
  .controller('myController', ($scope, $timeout, $interval) => {
    var interval;
    var timeout;
    let main = $scope;
    main.times = 0;
    let promise;
    let doSomethingOneTime = () => {
      $scope.times++;
    };

    let doSomethingInfinitely = function() {
      promise = $interval(function() {
        doSomethingOneTime();
      }, 100)
    };
    main.mouseDown = function(action) {
      doSomethingOneTime();

      $timeout(doSomethingInfinitely, 5000);
    };


    main.mouseUp = function() {
      $interval.cancel(promise);
    };


  });
<!DOCTYPE html>
<html ng-app='myApp'>

<head>
  <script data-require="[email protected]" data-semver="4.0.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
  <script data-require="[email protected]" data-semver="4.0.0" src="script.ts"></script>
  <script data-require="[email protected]" data-semver="4.0.0" src="system.config.js"></script>
  <script data-require="[email protected]" data-semver="4.0.0" src="tsconfig.json"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-controller='myController'>
  <button ng-mousedown="mouseDown()" ng-mouseup="mouseUp()">Mouse Down</button>
  <br>
  <span>Doing something {{times}} times</span>
</body>

</html>

4
  • There must be something else going on, but this should be easy to replicate in a snippet. Can you add one to your question demonstrating the issue in action? Commented Aug 29, 2018 at 14:27
  • I would love to do that, but don't know how (or where). Could you please give me a hint? Commented Aug 29, 2018 at 17:32
  • Add a code snippet to your question and put in the minimal needed code and HTML to demonstrate the issue. Commented Aug 29, 2018 at 17:46
  • Mind blown: did not know that you can do that within stackoverflow. The solution of @charliebeckwith works, but thanks for the help anyway. Commented Aug 30, 2018 at 5:54

1 Answer 1

1

The problem is two fold. The first case is that if you mouse up before the timeout delay has finished, the interval promise you set will still be undefined, thus when you call cancel nothing is cancelled. The second problem is if you click the button twice you will lose all reference to the first interval promise. The second click, which creates a second timeout will replace the first interval promise when it finishes. In effect you'll have 2 $intervals executing concurrently, one of which you have no reference to.

Here is a working example.

angular
  .module('myApp', [])
  .controller('myController', ($scope, $timeout, $interval) => {
    var interval;
    var timeout;
    $scope.times = 0;
    $scope.mouseUp = function(){
      $timeout.cancel(timeout);
      $interval.cancel(interval);
    };
    let increment = ()=>{
      $scope.times++;
    };
    $scope.mouseDown = function(){
      increment();
      timeout = $timeout(()=>{
        interval = $interval(()=>{
          increment();
        },100)
      }, 1000)
      
    };

  });
<!DOCTYPE html>
<html ng-app='myApp'>

<head>
  <script data-require="[email protected]" data-semver="4.0.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
  <script data-require="[email protected]" data-semver="4.0.0" src="script.ts"></script>
  <script data-require="[email protected]" data-semver="4.0.0" src="system.config.js"></script>
  <script data-require="[email protected]" data-semver="4.0.0" src="tsconfig.json"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-controller='myController'>
  <button ng-mousedown="mouseDown()" ng-mouseup="mouseUp()">Mouse Down</button>
  <br>
  <span>Doing something {{times}} times</span>
</body>

</html>

Sign up to request clarification or add additional context in comments.

1 Comment

Works now perfectly, thank you for the explanation and the great example!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.