tatactic
tatactic

Reputation: 1385

event.preventDefault is unclear for me even if I understand stopImmediatePropagation and stopPropagation

event.preventDefault seems to be hard to understand to me.(this is the dark side of AS3). :)

stopImmediatePropagation - stopPropagation methods are pretty easy to understand. Here's a test I made (which need just a copy/paste on the timeline) this may avoid You to spend too much time.

I just do not understand in which case preventDefault may be useful... If you have some suggestions or links, please could You give me some feedback?

Here is the code :

// This example is coded on the Timeline.
// The Stage must fit 550 * 400 pixels (default size).
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;

// function to create a MovieClip and return it to a variable.
function createMC(target:DisplayObjectContainer):MovieClip{
    var mc:MovieClip = new MovieClip();
    target.addChild(mc);
    return mc;
}
// function that draws a Rectangle in the MovieClip of your choice.
function dRect(target:MovieClip,x:uint,y:uint,width:uint,height:uint,color:uint,alpha:Number):void{
    var g:Graphics = target.graphics;
    g.lineStyle(1,0x000000);
    g.beginFill(color,alpha);
    g.drawRect(x-width/2,y-height/2,width,height);
    g.endFill();
}
// event function that trace the properties of the Event.
function traceTarget(me:MouseEvent):void{
    trace(" *** event.phase = " + me.eventPhase + ", event.bubbles = " + me.bubbles);
    trace("me.target.name = " + me.target.name);
    trace("me.currentTarget.name(the listening object) = " + me.currentTarget.name);
    /*
    Use preventDefault and the events  for m1 AND this will be triggered.
    MOUSE_DOWN,setText will be called 2 times 1 time for this, the second time for m1!
    MOUSE_DOWN,traceTarget will be called 2 times 1 time for this, the second time for m1!
    */
    //me.preventDefault();
    /*
    Use stopPropagation to avoid that the same function is not called if an event occurs.
    MOUSE_DOWN,setText will be called !
    */
    me.stopPropagation();
    /*
    Use stopImmediatePropagation to avoid all the functions that another listener may trigger.
    MOUSE_DOWN,setText WILL NEVER BE CALLED because traceTarget has been called!
    stopImmediatePropagation will only allow the first listener (traceTarget).
    */
    //me.stopImmediatePropagation();
    trace(me.toString());
    // trace the Event that is triggered.
}
function setText(me:MouseEvent):void{
    tf_1.text = "me.target.name = " + me.target.name;
    tf_1.setTextFormat(tf);
    countText++;
    trace("setText("+ me.target + ") has been called " + countText + " time(s)");
    countText = 0;
}
/*
A counter to see how many times an Event method is triggered
*/
var countText:uint = 0;
/*
Declare a TextField
*/
var tf_1:TextField = new TextField();
this.addChild(tf_1);
tf_1.width = 300;
tf_1.height = 20;
tf_1.x = this.stage.stageWidth - this.stage.stageWidth/2 - tf_1.width/2;
tf_1.y = 30;
var tf:TextFormat = new TextFormat(null,16,0xff0000,true,null,null,null,null,TextFormatAlign.CENTER)
tf_1.text = "Click on a Square/Rectangle";
tf_1.setTextFormat(tf);
/*
Declare 4 MovieClips
3 MovieClips inside each other
    - m1 on "this" (root1 in this case).
    - m2 inside m1
    - m3 inside m2
1 MovieClip on "this" (root1 in this case).
*/
var m1:MovieClip
var m2:MovieClip
var m3:MovieClip
var otherClip:MovieClip
// Create the MovieClips
m1 = createMC(this);
m2 = createMC(m1);
m3 = createMC(m2);
otherClip = createMC(this);
// set the names for the MovieClip's
m1.name = "movieClip_1";
m2.name = "movieClip_2";
m3.name = "movieClip_3";
otherClip.name = "otherClip";
// Draw Rectangles in the MovieClip's
dRect(m1,275,200,100,100,0xff0000,1);
dRect(m2,275,200,50,50,0x00ff00,1);
dRect(m3,275,200,25,25,0x0000ff,1);
dRect(otherClip,100,200,50,50,0xff9900,1);
// Add a listener on m1 MovieClip.
m1.addEventListener(MouseEvent.MOUSE_DOWN,traceTarget,false);
m1.addEventListener(MouseEvent.MOUSE_DOWN,setText,false);
//  Add a listener on root (root1 in this case).
this.addEventListener(MouseEvent.MOUSE_DOWN,traceTarget,false);
this.addEventListener(MouseEvent.MOUSE_DOWN,setText,false);

If You could help me to understand the preventDefault method, I should be really happy.

Best regards. Nicolas.

Upvotes: 1

Views: 411

Answers (2)

Boat5
Boat5

Reputation: 91

From the as3 docs: preventDefault() "cancels the events behaviour if that behaviour can be cancelled".

One example i can give you is the android back button. If you press the back button, it will minimize your AIR app by default. But if you listen for it and call preventDefault(). It will stop that default behavior so you can navigate to, your last open page instead.

Another example would be the home button on android, you can call preventDefault() but this action cannot he cancelled, so it will be ignored.

A mouse event like your example however, im not in a position to test what exactly that does

Upvotes: 2

null
null

Reputation: 5255

From the documentation of preventDefault()

Many events have associated behaviors that are carried out by default. For example, if a user types a character into a text field, the default behavior is that the character is displayed in the text field. Because the TextEvent.TEXT_INPUT event's default behavior can be canceled, you can use the preventDefault() method to prevent the character from appearing.

Here's an example for that:

package 
{
    import flash.text.TextField;
    import flash.text.TextFieldType;
    import flash.display.Sprite;
    import flash.events.TextEvent;

    public class Main extends Sprite 
    {
        public function Main() 
        {
            var tf:TextField = new TextField();
            tf.type = TextFieldType.INPUT;
            tf.border = true;
            addChild(tf);

            tf.addEventListener(TextEvent.TEXT_INPUT, onInput);         
        }

        private function onInput(te:TextEvent):void
        {
            te.preventDefault();
        }
    }
}

The TextField is there, but you cannot type into it. If you comment out the line that adds the listener, the default behaviour is not prevent and you can type.


stopImmediatePropagation(), stopPropagation() and eventPhase are all concerned with the event flow: the three phases of capturing, target and bubbling. As such, they can be used to influence if an Event "reaches" an object that added a listener for it. If you want to think about the listeners that you add for an event as custom behaviour, you might call the three above "preventCustom()".

The documentation of the two methods explicitely mentions this:

Note: This method does not cancel the behavior associated with this event; see preventDefault() for that functionality.

preventDefault() deals with the default behaviour associated with the event and has nothing to do with the event flow.

As an example, you might be thinking that you could achieve the same thing as the above example by adding a listener for the capturing phase at stage and then stopping the propagation, like so:

package 
{
    import flash.text.TextField;
    import flash.text.TextFieldType;
    import flash.display.Sprite;
    import flash.events.TextEvent;

    public class Main extends Sprite 
    {
        public function Main() 
        {
            var tf:TextField = new TextField();
            tf.type = TextFieldType.INPUT;
            tf.border = true;
            addChild(tf);

            stage.addEventListener(TextEvent.TEXT_INPUT, onInput, true);  // new: added to stage and for capturing phase  
        }

        private function onInput(te:TextEvent):void
        {
            te.stopImmediatePropagation(); // new: stopping propagation
        }
    }
}

If you execute this code, you will be able to type into the TextField just fine. Again, you're just messing with the event flow here, not the default behaviour. All you do is prevent subsequent listeners to be getting the Event, for example, if you add a listener to the TextField itself as shown below, it will never be executed, because you stop the event flow before it is reached.

package 
{
    import flash.text.TextField;
    import flash.text.TextFieldType;
    import flash.display.Sprite;
    import flash.events.TextEvent;

    public class Main extends Sprite 
    {
        public function Main() 
        {
            var tf:TextField = new TextField();
            tf.type = TextFieldType.INPUT;
            tf.border = true;
            addChild(tf);

            tf.addEventListener(TextEvent.TEXT_INPUT, onTfInput);
            stage.addEventListener(TextEvent.TEXT_INPUT, onInput, true);         
        }

        private function onTfInput(te:TextEvent):void
        {
            // never executed
        }

        private function onInput(te:TextEvent):void
        {
            te.stopImmediatePropagation();
        }
    }
}

tl, dr;

If you find a bomb with a self timer ticking, stopImmediatePropagation() will stop other people getting notice about that and might prevent a panic, but only preventDefault() will save your life. If cancelable is false, you better run.

Upvotes: 2

Related Questions