AngularJS: Preventing 'mouseenter' event triggering on child elements
Asked Answered
C

1

6

I'm playing right now with the AngularJS framework and I stumbled upon a problem. I made a directive which is called 'enter'. It triggers functions on mouseenter and mouseleave. I applied it as an attribute to the table row elements. It is now triggered for every child element (all the columns and etc), but it should be only triggered, when you go with your mouse over the table row.

This is how my directive looks like:

myapp.directive('enter', function(){
    return {
        restrict: 'A', // link to attribute... default is A
        link: function (scope, element){
            element.bind('mouseenter',function() {
                console.log('MOUSE ENTER: ' + scope.movie.title);
            });
            element.bind('mouseleave',function() {
                console.log('LEAVE');
            });
        }
    }
});

Here is an example: http://jsfiddle.net/dJGfd/1/

You have to open the Javascript console to see the log messages.

What is the best way to achieve the functionality that I want in AngularJS? I prefer to not use jQuery if there is a reasonable AngularJS solution.

Carboni answered 7/3, 2013 at 19:5 Comment(1)
That looks like a bug to me. Just a quick note, you can also apply the Angular directive called "ng-mouseenter" / "ng-mouseleave". My idea would be to save the last hovered element and see if it is different.Jorgan
S
6

You can try this:

myapp.directive('enter', function () {
    return {
        restrict: 'A',
        controller: function ($scope, $timeout) {
            // do we have started timeout
            var timeoutStarted = false;

            // pending value of mouse state
            var pendingMouseState = false;

            $scope.changeMouseState = function (newMouseState) {
                // if pending value equals to new value then do nothing
                if (pendingMouseState == newMouseState) {
                    return;
                }
                // otherwise store new value
                pendingMouseState = newMouseState;
                // and start timeout
                startTimer();
            };

            function startTimer() {     
                // if timeout started then do nothing
                if (timeoutStarted) {
                    return;
                }

                // start timeout 10 ms
                $timeout(function () {
                    // reset value of timeoutStarted flag
                    timeoutStarted = false;
                    // apply new value
                    $scope.mouseOver = pendingMouseState;
                }, 10, true);
            }
        },
        link: function (scope, element) {
            //**********************************************
            //  bind to "mouseenter" and "mouseleave" events
            //**********************************************
            element.bind('mouseover', function (event) {
                scope.changeMouseState(true);
            });

            element.bind('mouseleave', function (event) {
                scope.changeMouseState(false);
            });

            //**********************************************
            //  watch value of "mouseOver" variable
            // or you create bindings in markup
            //**********************************************
            scope.$watch("mouseOver", function (value) {
                console.log(value);
            });
        }
    }
});

Same thing at http://jsfiddle.net/22WgG/

Also instead

element.bind("mouseenter", ...);

and

element.bind("mouseleave", ...);

you can specify

<tr enter ng-mouseenter="changeMouseState(true)" ng-mouseleave="changeMouseState(false)">...</tr>

See http://jsfiddle.net/hwnW3/

Sequential answered 10/3, 2013 at 23:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.