views:

876

answers:

5
up.addEventListener(MouseEvent.CLICK, 
    function clickFunc(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
down.addEventListener(MouseEvent.CLICK, 
    function clickFunc(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

The above code adds a listener to a couple of MC's. Originally the methods were anonymous but I have named them clickFunc() in order to try an reference them in my remove listener.

Here is my remove listener code. Both of these snippets are in separate functions. The add listener method is called before the remove method.

up.removeEventListener(MouseEvent.CLICK, clickFunc );
down.removeEventListener(MouseEvent.CLICK, clickFunc);

As soon as I publish the movie I get this error:

1120: Access of undefined property clickFunc.
A: 

try this:

up.addEventListener(MouseEvent.CLICK, 
    clickFunc = function(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

down.addEventListener(MouseEvent.CLICK, 
    clickFunc = function(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
antpaw
I have tried that already and it produces and additional "1120: Access of undefined property clickFunc" error on itself
ed209
+1  A: 

This one should work... just remove methode name...

 up.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void
        { 
            revealSpinner(event,51.42,1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);
    down.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void
        { 
            revealSpinner(event,51.42,-1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);
OXMO456
yes that does work, but I need to remove the event listener from both "up" and "down" no matter which one you click on. Your suggestion would remove the need to event call removeEventListener() as it's part of the CLICK action. I need to remove the listener externally from the add listener.
ed209
The only way I can think of is to assign both functions to local variables, use them to add listeners, and return those two vars as an object and store that object in a global variable. Now, call remove listener from both functions using `globalObj.upFunction` and `globalObj.downFunction`. But before you start writing the code for this I strongly suggest you consider using instance methods instead of anonymous/inner functions.
Amarghosh
+1  A: 

First of all, you have the same name used twice (clickFunc), it cannot be inferred which one you refer to in your calls to removeEventListener. Second of all, clickFunc will only be accessible in the function where it is declared:

function foo() {
    var clickFunc: Function;
    up.addEventListener(MouseEvent.CLICK, 
        clickFunc = function (event:MouseEvent):void
        { 
            revealSpinner(event,51.42,1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);

    // 'clickFunc' available here, so this is possible:
    up.removeEventListener(MouseEvent.CLICK, clickFunc);
}

function bar() {
    // 'clickFunc' is not available here, so this is not possible:
    up.removeEventListener(MouseEvent.CLICK, clickFunc);
    // 1120: Access of undefined property clickFunc
}

If you need to reference the methods (like, say, removing them from an event), they can't be anonymous. If you need to reference them from several methods, then they shouldn't be local to one method (foo in the example above). And they need different identifiers (clickFunc1 and clickFunc2 if you will). This is my suggested solution:

private function addHandlers(): void
{
    up.addEventListener(MouseEvent.CLICK, upClickHandler, false, 0, true);
    down.addEventListener(MouseEvent.CLICK, downClickHandler, false, 0, true);
}

private function removeHandlers(): void
{
    up.removeEventListener(MouseEvent.CLICK, upClickHandler);
    down.removeEventListener(MouseEvent.CLICK, downClickHandler);
}

private function upClickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

private function downClickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

Of course, if, like in your example, the methods are identical you can use only one:

private function addHandlers(): void
{
    up.addEventListener(MouseEvent.CLICK, clickHandler, false, 0, true);
    down.addEventListener(MouseEvent.CLICK, clickHandler, false, 0, true);
}

private function removeHandlers(): void
{
    up.removeEventListener(MouseEvent.CLICK, clickHandler);
    down.removeEventListener(MouseEvent.CLICK, clickHandler);
}

private function clickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}
Markus Johnsson
A: 

ok there is a few ways that you can do this. here is the first way which i think is what your looking for.

var upAnon:Function;
var downAnon:Function;

up.addEventListener(MouseEvent.CLICK, 
    upAnon = function (event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
down.addEventListener(MouseEvent.CLICK, 
    downAnon = function (event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

up.removeEventListener(MouseEvent.CLICK, upAnon);
down.removeEventListener(MouseEvent.CLICK, downAnon);

and here is another way, getting the same desired effect and functionality as the first. just cleaner and usually standard practice.

function upFunction(event.MouseEvent):void {
    revealSpinner(event,51.42,1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}
function downFunction(event.MouseEvent):void {
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

up.addEventListener(MouseEvent.CLICK, upFunction, false, 0, true);
down.addEventListener(MouseEvent.CLICK, downFunction, false, 0, true);

up.removeEventListener(MouseEvent.CLICK, upFunction);
down.removeEventListener(MouseEvent.CLICK, downFunction);

The reason that you would use the first type, is if you were creating the eventHandler inside a function and need to use variables defined in that function, inside your anonymous function. for example, here im accessing the var countMe inside the anon function and incrementing it on mouse_down, and it will increment until the mouse_up is activated. so every time i click down, it will count up from 0 till mouse is up, then will start over.

var anonFunc:Function;

function doThisStuff(event:MouseEvent):void {
    var countMe = 0;

    stage.addEventListener(Event.ENTER_FRAME,
        anonFunc = function (e:Event) {
            countMe++;
            trace(countMe);
        }
    );  
}

function stopCounting(event:MouseEvent):void {
    stage.removeEventListener(Event.ENTER_FRAME, anonFunc);
}

stage.addEventListener(MouseEvent.MOUSE_DOWN, doThisStuff);
stage.addEventListener(MouseEvent.MOUSE_UP, stopCounting);
Sheac
A: 

You're creating the event handlers with weak references (passing true for that last parameter). As you probably already know, a weak reference won't prevent the garbage collector from collecting your function. However, unless you maintain a reference to your event handlers outside the scope of the function you're defining them in (doesn't look like you are), the handlers will have only that one weak reference to keep them alive so as soon as the garbage collector runs, your handlers are gone anyway. The bottom line is that your event handlers don't look like they will fire once garbage collection runs so worrying about removing the handlers is somewhat pointless. They'll go away all on their own whether you want them to or not.

You'll need to maintain a reference to those event handlers in a scope that will still exist when they should fire. Once you've done that, you should be able to use those references to remove them.

Tim