I'm having a difficulty (which is probably pretty silly) in storing a value in a property of an object in Javascript. I have done something similar recently using this.propriedade = valor
within the "constructor" function and I had no problem reusing the value in a function defined as 'Object.prototype.function_name'.
However, in this example ( available in JSFiddle ) a property ( this.m_oClickCallback
) is not visible in the function of ( MyButton.prototype.handleClick
), generating the following exception when the button is clicked:
Uncaught TypeError: Object [object global] has no method 'm_oClickCallback'
I imagine that probably the error is due to something very silly, but I can not see what it is.
Here is the example html that I have prepared:
<body onload="init();">
<canvas id="myCanvas" width="800" height="600">
O seu navegador não suporta HTML5. (<i>Your browser does not support HTML5.</i>)
</canvas>
</body>
And the Javascript code:
(function() {
// Objeto de botão customizado
var MyButton = function(sLabel, sColor, oClickCallback) {
// Chama o initialize do objeto protótipo (createjs.Container)
this.initialize();
// Armazena a referência para o callback do evento de click
this.m_oClickCallback = oClickCallback;
// Cria o conteúdo do botão
var oText = new createjs.Text(sLabel, "40px Arial", "#ffffff");
oText.textBaseline = "top";
oText.textAlign = "center";
var iWidth = oText.getMeasuredWidth() + 30;
var iHeight = oText.getMeasuredHeight() + 20;
var oBackground = new createjs.Shape();
oBackground.name = "Background";
oBackground.graphics.beginFill(sColor).drawRoundRect(0, 0, iWidth, iHeight, 10);
oText.x = iWidth / 2;
oText.y = 10;
this.addChild(oBackground, oText);
// Captura o evento de click
this.addEventListener("click", this.handleClick);
}
// Define o protótipo
MyButton.prototype = new createjs.Container();
// Função de tratamento do click no botão. Invoca o callback armazenado.
MyButton.prototype.handleClick = function(oEvent) {
this.m_oClickCallback(oEvent.target);
}
// Atribui o objeto ao escopo global de "window"
window.MyButton = MyButton;
}());
// Função de inicialização. Cria o botão no onload do corpo da página.
function init() {
g_oStage = new createjs.Stage("myCanvas");
var oButton = new MyButton("Olá mundo!", "red", function() { alert("Funciona!"); });
g_oStage.addChild(oButton);
g_oStage.update();
}
EDIT: The idea is to store the property so that it is differentiated between each new instance of the object (as if it were a private or public attribute of a class in other languages). Solutions where ownership is shared (as if it were static) are not in the interest of the question.
EDIT2:
I found that in the createjs.Container there is a property called this.mouseChildren
which when disabled causes the target
object sent in the payload of the mouse events to be directly the MyButton
object instead of its components (the text or the shape background color). Using this property and the target
object I can solve the problem in the following way (see this new example JSFiddle , now with two button instances):
//. . .
// Faz o target dos eventos ser diretamente o objeto MyButton, ao invés do texto
// ou do background nele inclusos
this.mouseChildren = false;
//. . .
// Função de tratamento do click no botão. Invoca o callback armazenado.
MyButton.prototype.handleClick = function(oEvent) {
oEvent.target.clickCallback(oEvent.target);
}
Logging the this
into the console, I realized that it is indeed the object window
. That's why the code did not work. I did not add this conclusion as a response because I still have the doubt as to why the mouse click handling function is not invoked at the button's scope but rather from the browser window. Anyone know?