I have an instance of a button called myBtn
on stage, and an instance of a square movie clip called myContainer
- all of which published from flash.
Within myContainer
i have a movieclip instance named mySquare
which is animated via classic tween from one point of the stage to another.
When the stage is loaded i use this.myBtn.on("click", startBtnOnClick)
to add an event listener to the button, and the function startBtnOnClick(evt)
is indeed successfully called.
What i'm trying to achieve is to tell myContainer
to start playing when the button is clicked, and to do so i currently need to use:
evt.target.parent.parent.myContainer.gotoAndPlay(0)
which works, but doesn't seem to be a best practice here.
What would be a more suitable approach?
The code is generated when i publish from Adobe Flash using HTML5 document type. My addition was the startBtnOnClick()
function definition and assigning the event handler to the myBtn
instance
Two files are created when i publish. In order to play the movie you open the html file.
SquareTrial.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SquareTrial</title>
<script src="http://code.createjs.com/easeljs-0.8.1.min.js"></script>
<script src="http://code.createjs.com/tweenjs-0.6.1.min.js"></script>
<script src="http://code.createjs.com/movieclip-0.8.1.min.js"></script>
<script src="SquareTrial.js"></script>
<script>
var canvas, stage, exportRoot;
function init() {
canvas = document.getElementById("canvas");
exportRoot = new lib.SquareTrial();
stage = new createjs.Stage(canvas);
stage.addChild(exportRoot);
stage.update();
createjs.Ticker.setFPS(lib.properties.fps);
createjs.Ticker.addEventListener("tick", stage);
}
</script>
</head>
<body onload="init();" style="background-color:#D4D4D4">
<canvas id="canvas" width="550" height="400" style="background-color:#FFFFFF"></canvas>
</body>
</html>
and SquareTrial.js:
(function (lib, img, cjs, ss) {
var p; // shortcut to reference prototypes
// library properties:
lib.properties = {
width: 550,
height: 400,
fps: 24,
color: "#FFFFFF",
manifest: []
};
// functions:
function startBtnOnClick(evt)
{
console.log("startBtnOnClick called.");
console.log("stage:");
console.log(stage);
console.log("stage.myContainer:");
console.log(stage.myContainer);
console.log("this.myContainer:");
console.log(this.myContainer);
}
// symbols:
(lib.MySquare = function() {
this.initialize();
// Layer 1
this.shape = new cjs.Shape();
this.shape.graphics.f().s("#000000").ss(1,1,1).p("AoWoWIQtAAIAAQtIwtAAg");
this.shape.setTransform(53.5,53.5);
this.shape_1 = new cjs.Shape();
this.shape_1.graphics.f("#6633FF").s().p("AoWIXIAAwtIQtAAIAAQtg");
this.shape_1.setTransform(53.5,53.5);
this.addChild(this.shape_1,this.shape);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(-1,-1,109,109);
(lib.MyBtn = function() {
this.initialize();
// Layer 1
this.shape = new cjs.Shape();
this.shape.graphics.f().s("#000000").ss(1,1,1).p("AprjWITXAAIAAGtIzXAAg");
this.shape.setTransform(62,21.5);
this.shape_1 = new cjs.Shape();
this.shape_1.graphics.f("#0099FF").s().p("AprDXIAAmtITXAAIAAGtg");
this.shape_1.setTransform(62,21.5);
this.addChild(this.shape_1,this.shape);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(-1,-1,126,45);
(lib.MyContainer = function(mode,startPosition,loop) {
this.initialize(mode,startPosition,loop,{});
// Layer 1
this.mySquare = new lib.MySquare();
this.mySquare.setTransform(53.5,53.5,1,1,0,0,0,53.5,53.5);
this.timeline.addTween(cjs.Tween.get(this.mySquare).to({x:397.5},47).wait(1));
}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(-0.5,-0.5,108,108);
// stage content:
(lib.SquareTrial = function() {
this.initialize();
// button
this.myContainer = new lib.MyContainer();
this.myContainer.setTransform(102.5,99.5,1,1,0,0,0,53.5,53.5);
this.myBtn = new lib.MyBtn();
this.myBtn.setTransform(111,337.5,1,1,0,0,0,62,21.5);
//this.myBtn.on("click", startBtnOnClick); //<< does not work
this.myBtn.on("click", startBtnOnClick, this);
this.addChild(this.myBtn,this.myContainer);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(323.5,245.5,125,314);
})(lib = lib||{}, images = images||{}, createjs = createjs||{}, ss = ss||{});
var lib, images, createjs, ss;
If you are just looking for the stage, you can use the stage
property (getter) on any display object, which returns the stage the instance lives on. It will return null if it can not reach the stage.
var stage = evt.target.stage;
Otherwise, you might want to look at your application architecture. For instance, you can bind your event handler to the current scope by passing this
as the 3rd parameter of the on()
method. This will make your startBtnOnClick
method fire in your app scope, rather than making you look up the scope relative to the clicked button.
this.myBtn.on("click", startBtnOnClick, this);
[Edited based on posted content]
Your update shows that myContainer
is a child of your Flash stage, which is actually exported as the SquareTrial
function in your library JS (named after your FLA). This class is instantiated as exportRoot
in the HTML.
The way you define the function inside the library is a little unorthodox. It is basically an anonymous function, but the bigger issue is that if you re-export your library from Flash, it will get overwritten. I recommend either moving it to another script you include, or actually including it in your frame script.
Anyways, on to the actual function. Since you use the on()
method to call it in scope, the this
variable will refer to the SquareTrial
instance (aka the exportRoot
). You should be able to reference this.myContainer
in your startBtnOnClick
method.
The stage
getter I suggested is not ideal, since the EaselJS stage only contains the exportRoot
. It would also need to be accessed as this.stage
. The stage
reference you use does exist, but it is the global variable created in the index.html.
So, using the new approach, you should be able to do this:
// In your frame script:
this.myBtn.on("click", startBtnOnClick, this);
// In your function callback
console.log(this); // Should be the instance, and NOT window.
this.myContainer.gotoAndPlay(0);
If you decided to stick with an un-scoped, anonymous function, then you can reference your content via the global exportRoot
variable:
exportRoot.myContainer.gotoAndPlay(0);
Hope that clears up any confusion.