0

I have an Angular state which can rotate between three templates each controlled by its own directive. The directives have event listeners, but as I rotate through the directives the event listeners add up by one and after the first transition to another directive everything starts to get buggy. I have attempted to fix these bugs but to no avail. Here is an example of one of the three directives:

angular.module('app').directive('presetStationOne', function($interval, $parse, $compile, PresetFactory){

    var linker = function(scope, element, attrs){

        PresetFactory.assign(1,6,scope);

        scope.$watch('page1', function(newVal, oldVal){
            if(newVal === true) {
                allEncompassing(document, PresetFactory, scope, "start");
            }
        });
        scope.$on('$destroy', function(){
            allEncompassing(document, PresetFactory, scope, "finish");
        });

    };

    return {
        restrict: 'EA',
        scope: false,
        link: linker,
        templateUrl: 'public/templates/freeplay/presetspage1.html'
    };  
}); 

And here is the function allEncompassing(), which is all three presetStation directives. They all use PresetFactory and when I change from one directive to another, the calls on PresetFactory incrementally increase.

function allEncompassing(document, PresetFactory, scope, msg){

    if (msg === "finish"){
        removeMyListeners();
    }   

    function clickListen(e){
        var f;
        if (!e.target.attributes.stationnumber){
            if (undefined){
                return;
            } else if(!e.target.parentNode || !e.target.parentNode.parentNode || !e.target){
                return;
            } else if (!e.target.parentNode.parentNode.attributes.hasOwnProperty('stationnumber')){
                return;
            } else {
                return f = e.target.parentNode.parentNode.attributes;
            }
        } else {
            return f = e.target.attributes;
        }
    }

    function resetMouseup(PresetFactory){
        restartMyListeners();
        PresetFactory.mouseUp();            
    }
    function execMouseup(e){
        resetMouseup(PresetFactory);
    }
    function execClickListen(e){
        var f = clickListen(e);
        if (f !== undefined){
            PresetFactory.mouseDown(f, scope);
            scope.$digest();
            restartMyListeners();
        } else {
            return;         
        }
    }

    function restartMyListeners(){
        restartMousedown();
        document.removeEventListener('mouseup', execMouseup);
        document.addEventListener('mouseup', execMouseup);
    }
    function restartMousedown(){
        document.removeEventListener('mousedown', execClickListen);         
        document.addEventListener('mousedown', execClickListen);
    }
    function removeMyListeners(){
        document.removeEventListener('mousedown', execClickListen);         
        document.removeEventListener('mouseup', execMouseup);
    }
    if (msg === "start"){
        restartMyListeners();
    }
}

What is the best way to mitigate increasing these event listeners and keep it to a single event listener?

Les Paul
  • 1,260
  • 5
  • 22
  • 46
  • 1
    The most obvious thing that I can think of, is to add your event listeners on your template, let angular handle them. It looks like you are attaching click events to the entire page? Would something like `` work for you? – Shan Robertson Jul 27 '16 at 00:32
  • I will give that a try and report back. – Les Paul Jul 27 '16 at 00:33
  • 1
    I always go for that when i get into your situation, unless it's a global element outside of the view being changed. You could also try making an "App" controller (or directive i suppose) that is only loaded on the inital page load and doesn't change when you switch your routes. – Shan Robertson Jul 27 '16 at 00:36
  • Actually Shan, I just realized that might not work since the event listeners are very specific: if the mouse is held down less than one second, a "radio station dial" is changed. If more than a second, a "radio preset" is saved. So I believe an event listener of some kind is necessary. – Les Paul Jul 27 '16 at 00:48
  • @ShanRobertson Actually, I may have found a solution: http://stackoverflow.com/questions/25180332/how-can-i-listen-for-a-click-and-hold-in-angularjs – Les Paul Jul 27 '16 at 01:10

1 Answers1

0

Here is the answer, and it's a lot easier than using event listeners. I thought I needed event listeners since I was watching a mousedown event to determine if I should set a radio station or change to a radio station. Instead, I used the $interval service and HTML attributes data-ng-mousedown="radioStn(1)" data-ng-mouseup="checkResult()":

var dial = null;
var promise = null;
var time = 0;  
var check = false;

function defaultVal(){
    dial = null;
    promise = null;
    time = 0;
}    

function checkTime(dial, scope, $interval, $rootScope, PresetFactory){
    $interval.cancel(promise);
    if (check === true){
        console.log(dial + ' check is true');
        PresetFactory.setPreset(dial, scope);
    } else {
        console.log(dial + ' check is false');
        PresetFactory.changeStn(dial);
    }
    defaultVal();
}


angular.module('app').directive('presetStationOne', function($rootScope, $interval, $parse, $compile, PresetFactory){

    var linker = function(scope, element, attrs){

        PresetFactory.assign(1,6,scope);

        scope.radioStn = function(x){
            dial = x;
            promise = $interval(function(){
                time += 100;
                console.log(time);
                if (time >= 1000){
                    check = true;
                    checkTime(dial, scope, $interval, $rootScope, PresetFactory);
                    return;
                }
            }, 100);
        };

        scope.checkResult = function(){
            if (check === true){
                check = false;
                return;
            } else {
                checkTime(dial, scope, $interval, $rootScope, PresetFactory);
            }
        };

        scope.$on('$destroy', function(){
            defaultVal();
            check = false;
        });

    };

    return {
        restrict: 'EA',
        scope: false,
        link: linker,
        templateUrl: 'public/templates/freeplay/presetspage1.html'
    };  
});
Les Paul
  • 1,260
  • 5
  • 22
  • 46