Search code examples
actionscript-3flashremovechild

removechild not working when the swf is loaded externally


my problem is that the close button (removechild) which is placed in a swf works perfectly alone but when the swf is loaded from another one the button no longer works.

Here's the external swf code:

eti_scroll.scrollTarget = box_eti ;
hab_scroll.scrollTarget = box_hab ;
com_scroll.scrollTarget = box_com ;
descr_scroll.scrollTarget = box_descr ;



       exit.addEventListener(MouseEvent.CLICK, exitBtn_clickHandler);  

    function exitBtn_clickHandler(event:MouseEvent):void {  
    if(this.parent) this.parent.removeChild(this);
}  

And here's the button code from the main swf:

menu_button_2.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler2);

function fl_MouseClickHandler2(event:MouseEvent):void
{
    var myLoader:Loader = new Loader();                     
    var url:URLRequest = new URLRequest("pages/page_template.swf");  
    myLoader.load(url);                                  
    addChild(myLoader);
}

In the main swf there is no packages imported or loaderclass

Here is the link to the fla version and the example version: http://www.mediafire.com/file/5dzqnq3kth6n6dt/examples.rar

Error thrown when I use trace code by @organis and loaded from an external SWF file: The error thrown:

 I am here! Exit Button: [object SimpleButton] object Event Handler: function
 Function() {} function Exit.addEventListener: function Function() {} function 
MouseEvent.CLICK This: [object MainTimeline] object Parent: [object Loader] 
object Parent.removeChild: function Function() {} function Error: Error #2069:
 La clase Loader no implementa este método(The Loader Class doesn't implement 
this method). at Error$/throwError() at flash.display::Loader/removeChild() at 
page_template_fla::MainTimeline/onClick()[page_template_fla.‌​MainTimeline::frame1‌​
:65] –

Solution

  • Let me explain how to deal with this kind of problem. Once something that is supposed to work does not, the first thing to do is to pinpoint where the problem starts exactly, so you can probably diagnose what the problem is rather than have a vague understanding there is a problem somewhere.

    So you read all the traces from standalone run, then from loaded run and there certainly must be a difference. Upon finding it, you act with the regard to what that difference is.

    // If this does not work, that means scripts do not work in the loaded SWF at all.
    trace("I am here!");
    
    // If this doesn't work the same as standalone, that means
    // something breaks while constructing the loaded content.
    trace("Exit Button:", exit, typeof(exit));
    
    // Lets check id the event handler is doing fine.
    trace("Event Handler:", onClick, typeof(onClick));
    
    // If the method is not present on the object,
    // something is deeply wrong with the whole thing.
    trace("Exit.addEventListener:", exit.addEventListener, typeof(exit.addEventListener));
    
    exit.addEventListener(MouseEvent.CLICK, onClick);  
    
    function onClick(event:MouseEvent):void
    {
        // If it doesn't work that means there's no mouse event.
        trace("MouseEvent.CLICK");
    
        // Just to check things out.
        trace("This:", this, typeof(this));
        trace("Parent:", this.parent, typeof(this.parent));
        trace("Parent.removeChild:", this.parent.removeChild, typeof(this.parent.removeChild));
    
        if(this.parent) this.parent.removeChild(this);
    }
    

    UPD: Now, you're getting the error (you should have mentioned it in your question in the first place, actually)

    Error: Error #2069: La clase Loader no implementa este método(_The Loader Class doesn't implement tihs method_). at Error$/throwError() at flash.display::Loader/removeChild() at page_template_fla::MainTimeline/onClick()[page_template_fla.‌​MainTimeline::frame1‌​:65]

    Now take a look here (I like this link as it explains quite a lot): https://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e26.html

    Your script is on the main timeline. So, when you run it in a standalone mode, this.parent points to stage which can add and remove children, no problem.

    Then, when you run it in the loaded mode, the hierarchy goes main SWF stage -> main SWF root -> ... -> Loader -> loaded SWF root. As you can see, when you address this.parent you get the Loader instance, the very one you use in main SWF to load the other one. Loader is a DisplayObjectContainer but is not intended for adding/removing children, thus it throws the exception mentioned above.

    With all this I advise another way of removing content out of sight:

    exit.addEventListener(MouseEvent.CLICK, onClick);  
    
    function onClick(event:MouseEvent):void
    {
        // Unsubscribe to help Garbage Collector do its job.
        exit.removeEventListener(MouseEvent.CLICK, onClick);  
    
        // Hide the content.
        visible = false;
    
        // Remove all of its children.
        removeChildren();
    }
    

    Or you can figure the case your script is running in and act accordingly:

    exit.addEventListener(MouseEvent.CLICK, onClick);  
    
    function onClick(event:MouseEvent):void
    {
        // Unsubscribe to help Garbage Collector do its job.
        exit.removeEventListener(MouseEvent.CLICK, onClick);  
    
        // Checking for
        // if (parent == null)
        // is unnecessary here because if that was the case
        // there won't be a mouse event in the first place.
    
        var aParent:DisplayObjectContainer = parent;
    
        if (aParent is Loader)
        {
            // Loaded case.
            aParent.parent.removeChild(aParent);
        }
        else
        {
            // Standalone case.
            parent.removeChild(this);
        }
    }
    

    However, that figuring will only work in the simple cases and will not in more complicated setups (cross-domain content, security sandboxes, etc).