0

when the mouse moves on the .mousemove DIV, the .show DIV appear and then if the mouse did not move in 3 seconds, the .show DIV disappear.

<div class="mousemove" ng-mousemove="myToggle()" ng-model="loading" ></div>
<div class="show" ng-show="loading"></div>

$scope.myToggle = function() {
    $scope.loading = true; 
    $timeout(
        function() {
            $scope.loading = false;
        }, 
    3000);
}

I have do something but when I move the mouse on the .mousemove DIV constantly,the .show DIV will twinkle.What should I do,and I'm new to AngularJS. here is my demo: http://embed.plnkr.co/WbhqAQ4JJvOfuCN4tI3I/preview

3 Answers 3

1

You can cancel the $timeout before restarting it if it is already running.

var myApp = angular.module('myApp',[]);

myApp.controller('myController', function($scope, $timeout) {

    $scope.myToggle = function() {
      // Check to see if there already is a $scope.loading timer
      if($scope.loading){
        // if there is then use the $timeout.cancel() method
        $timeout.cancel($scope.loading);
      }
      // Initialize the $timeout into the $scope.loading propert
      $scope.loading = $timeout(
        function() {
          $scope.loading = false;
      }, 3000);
    }
});

Demo: http://embed.plnkr.co/WbqGbFG9JTVNXJW970l8/preview

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

2 Comments

I so sorry for reply you now,because the network is so bad.Now it works successfully with your code.But I don't understand "$scope.loading" is not setted to "true" in your code,How it works to show the .show DIV?
@hollton the $timeout returns a promise docs.angularjs.org/api/ng/service/$timeout and hence it is not false. Whilst not specifically true it is truthy which is enough to pass the if clause sitepoint.com/javascript-truthy-falsy
1

You have to clear your timeout before relaunching it, as follow:

var myApp = angular.module('myApp',[]);

myApp.controller('myController', function($scope, $timeout) {
    $scope.timeout;
    $scope.myToggle = function() {
        $scope.loading = true;

        window.clearTimeout($scope.timeout);
        $scope.timeout = window.setTimeout(function() {
            $scope.$apply(function() {
                $scope.loading = false;
            });
        }, 3000);
    }
});

See working Plunker

2 Comments

Fristly,I so sorry for reply you now,because the network is so bad.Your code works well but I choose other's answer.thank you anyway.
I try,but I haven't get 15 reputation, can't vote (。_。)
0

There are a couple of things wrong with this plunk.

First, there's no reason to use ng-model here. Just set it as a scope variable, seeing as you are editing it from the controller anyway.

Second, mousemove will execute continuously. Every time you move the mouse it's going to create a new timeout and it's not going to cancel the old one. This is why it flickers. It's also very inefficient to call this function and constanly make calls to $timeout.cancel() and $timeout(function() { }, 3000).

Instead consider using mouseenter and mouseleave and make sure you cancel old timeouts.

HTML

<div ng-app="myApp" ng-controller="myController">
  <div class="mousemove" ng-mouseenter="enter()" ng-mouseleave="leave()"></div>
  <div class="show" ng-show="loading"></div>
</div>

Javascript

var myApp = angular.module('myApp',[]);

myApp.controller('myController', function($scope, $timeout) {

  var timeoutCanceller = null;

  $scope.loading = false;

  $scope.enter = function() {
    cancelTimeout();
    $scope.loading = true;
  };

  $scope.leave = function() {
    timeoutCanceller = $timeout(function() {
      $scope.loading = false;
    }, 3000);
  };

  function cancelTimeout() {
    if (timeoutCanceller) $timeout.cancel(timeoutCanceller);
  }
});

Here is a working demo.

Edit: Might also be a good idea to bind those events to a parent container instead of directly on the element. If that loader is an overlay bringing that up might accidentally call the mouseleave event. Also gives you more options for styling.

<div ng-app="myApp" ng-controller="myController">
  <div ng-mouseenter="enter()" ng-mouseleave="leave()">
    <div class="mousemove"></div>
    <div class="show" ng-show="loading"></div>
  </div>
</div>

1 Comment

I so sorry for reply you now,because the network is so bad. I learn a lot from your suggestions,however,maybe I didn't discribe what I want clearly.When the mouse is motionless in the frist DIV,the second DIV disappear instead of leave DIV.And now I have already solved.thank you anyway.

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.