views:

15

answers:

2

I'm making a custom slider component. The head (the thing that you drag) is programmed like this:

        head.addEventListener(MouseEvent.MOUSE_DOWN, function():void {
            head.startDrag(false, new Rectangle(stubDiv,0,width - stubDiv - ((levels-maxLevel)*stubDiv),0));
        });
        head.addEventListener(MouseEvent.MOUSE_MOVE, function():void {
            updateLevel();
        });
        head.addEventListener(MouseEvent.MOUSE_UP, function():void {
            head.stopDrag();
            setHeadPos();
        });

Because the head is constrained to the area of the slider bar, the mouse can move away from it. If that happens, the object is still being dragged, but it doesn't receive MOUSE_MOVE events, nor the MOUSE_UP event if the mouse is released.

What's the best solution?

+1  A: 

Instead of calling updateLevel() in head's MOUSE_MOVE event, call it in the head's ENTER_FRAME event:

head.addEventListener(MouseEvent.MOUSE_DOWN, function():void { 
    head.startDrag(false, new Rectangle(stubDiv,0,width - stubDiv - ((levels-maxLevel)*stubDiv),0)); 
    head.addEventListener(Event.ENTER_FRAME, function():void  { updateLevel(); });
}); 

head.addEventListener(MouseEvent.MOUSE_UP, function():void { 
    head.stopDrag(); 
    head.removeEventListener(Event.ENTER_FRAME, function():void  { updateLevel(); });
    setHeadPos(); 
}); 

head.Stage.addEventListener(Event.MOUSE_LEAVE, function():void { 
    head.stopDrag(); 
    head.removeEventListener(Event.ENTER_FRAME, function():void  { updateLevel(); });
    setHeadPos(); 
}); 

I worked on a similar feature before and I also needed to handle Stage's Mouse_Leave. Depending on your requirement, you might also want to add MouseEvent.MOUSE_OUT to head

David
A: 

In AS3 this is handled by adding a MouseEvent listener to the stage listening for the MOUSE_UP event.

head.addEventListener(MouseEvent.MOUSE_DOWN, _handleDown);

function _handleDown($evt:MouseEvent):void {
    // add a MouseEvent.MOUSE_UP listener to the stage
    stage.addEventListener(MouseEvent.MOUSE_UP, _handleUp);
    head.removeEventListener(MouseEvent.MOUSE_DOWN, _handleDown);
    head.addEventListener(MouseEvent.MOUSE_MOVE, _handleMove);
    head.addEventListener(MouseEvent.MOUSE_UP, _handleUp);
    head.startDrag(false, new Rectangle(stubDiv,0,width - stubDiv - ((levels-maxLevel)*stubDiv),0)
}

function _handleMove($evt:MouseEvent):void {
    updateLevel();
}

function _handleUp($evt:MouseEvent):void {
    // remove the MouseEvent.MOUSE_UP listener from the stage
    stage.removeEventListener(MouseEvent.MOUSE_UP, _handleUp);
    head.removeEventListener(MouseEvent.MOUSE_UP, _handleUp);
    head.removeEventListener(MouseEvent.MOUSE_MOVE, _handleMove);
    head.addEventListener(MouseEvent.MOUSE_DOWN, _handleDown);
    head.stopDrag();
    setHeadPos();
}

As you can see, as a matter of style, I avoid using anonymous functions in my event listeners. This allows for far more flexibility in most cases, and in my opinion, is far easier to read.

As far as your other issue, not having the "scroll handle" react to MOUSE_MOVE events... do you want it to still react even after you have rolled away from the handle? Depending on how you want this to work it could be done a variety of ways.

Please clarify exactly what behavior you are looking for.

sberry2A