PDA

View Full Version : [solved] can't access public method in closures-design



sinus
9 Jun 2010, 12:18 AM
Hi together,

i read the thread http://www.extjs.com/forum/showthread.php?54537-code-structure on code structure and use the recommended closures-application-design for my app.

Basicaly i write functions which return objects and call these functions from an initLayout-function to get the objects.

The pattern i use looks like:


namespace.functionName = function() {

//private stuff

var privateFunction = function() {
...
};


//public stuff

return {

publicFunction: function() {
...
},

publicObject: {
...
}
};
}();
It worked fine until i tried to access the public method inside the return-statement from the public object also inside return-statement.


Here is the code i'm trying to get work:


SAapp.Tools = function() {

var showHideInfos = function() {
var infoPanel = Ext.getCmp('informations');
if (infoPanel.hidden) {
infoPanel.show();
}
else {
infoPanel.hide();
}
};


return {

showHideTopics: function() {
var infoPanel = Ext.getCmp('topicsWindow');
if (infoPanel.hidden) {
infoPanel.show();
}
else {
infoPanel.hide();
}
},

mapTools: new Ext.Container({
//xtype: 'container',
id: 'mapToolsTop',
autoEl: {},
x: 5,
y: 100,
height: 50,
anchor: '-5',
cls: 'mapTools',
border: false,
items:[{
xtype: 'button',
id: 'topicsBt',
text: 'Unterthemen einblenden',
autoWidth: true,
scale: 'large',
disabled: true,
enableToggle: true,
cls: 'baseMapBt',
handler: this.showHideTopics
},{
xtype: 'button',
id: 'infoBt',
text: 'Informationen<br>einblenden',
autoWidth: true,
scale: 'large',
enableToggle: true,
cls: 'infoBt',
handler: showHideInfos
}]
})
};
}();
I can access the method "showHideTopics" from outside through "SAapp.Tools.showHideTopics()", but can't access it from the inside of the container "mapTools" as a button-handler through "this.showHideTopics".
I think i miss something fundamental here. I read the forum and looked for answers in general javascript forums, but realy don't get it. Can somebody please give me a hint. I'm stuck.

Is this even the right way to use the closures-application-design?
And is the closures-application-design good for this? Or would be another application structure better?



Thanks for any help.
sinus.

Animal
9 Jun 2010, 1:02 AM
You can access it. When you click the 'Unterthemen einblenden' button, it executes the function does it?

And when you set a breakpoint there, and press 'Unterthemen einblenden', what is "this"?

Condor
9 Jun 2010, 1:55 AM
You are using this.showHideTopics before you defined it.

Instead, you should use:

SAapp.Tools = new (function () {
var showHideInfos = function () {
var infoPanel = Ext.getCmp('informations');
if (infoPanel.hidden) {
infoPanel.show();
} else {
infoPanel.hide();
}
};
this.showHideTopics = function () {
var infoPanel = Ext.getCmp('topicsWindow');
if (infoPanel.hidden) {
infoPanel.show();
} else {
infoPanel.hide();
}
};
this.mapTools = new Ext.Container({
id: 'mapToolsTop',
autoEl: {}, x: 5,
y: 100,
height: 50,
anchor: '-5',
cls: 'mapTools',
border: false,
items: [{
xtype: 'button',
id: 'topicsBt',
text: 'Unterthemen einblenden',
autoWidth: true,
scale: 'large',
disabled: true,
enableToggle: true,
cls: 'baseMapBt',
handler: this.showHideTopics
}, {
xtype: 'button',
id: 'infoBt',
text: 'Informationen<br>einblenden',
autoWidth: true,
scale: 'large',
enableToggle: true,
cls: 'infoBt',
handler: showHideInfos
}]
});
return this;
});

sinus
9 Jun 2010, 2:04 AM
thanks for the reply animal.

no, the function does not get executed, when i click the button.
when i set a breakpoint at the button and exermine it during initializing time "this" is the window.

i think you mean the scope of the button-handler is wrong?!
i already tried to set the scope of the hanlder to "this". but still the handler doesn't even get called.

Animal
9 Jun 2010, 2:36 AM
@Condor: We're creating a singleton via immediate execution of an anonymous function. That won't have a valid "this".

If you need to be able to refer to "this" inside the creation of a singleton, then invoke it as a constructor:



SAapp.Tools = new function () {
var showHideInfos = function () {
var infoPanel = Ext.getCmp('informations');
if (infoPanel.hidden) {
infoPanel.show();
} else {
infoPanel.hide();
}
};
this.showHideTopics = function () {
var infoPanel = Ext.getCmp('topicsWindow');
if (infoPanel.hidden) {
infoPanel.show();
} else {
infoPanel.hide();
}
};
this.mapTools = new Ext.Container({
id: 'mapToolsTop',
autoEl: {}, x: 5,
y: 100,
height: 50,
anchor: '-5',
cls: 'mapTools',
border: false,
items: [{
xtype: 'button',
id: 'topicsBt',
text: 'Unterthemen einblenden',
autoWidth: true,
scale: 'large',
disabled: true,
enableToggle: true,
cls: 'baseMapBt',
handler: this.showHideTopics
}, {
xtype: 'button',
id: 'infoBt',
text: 'Informationen<br>einblenden',
autoWidth: true,
scale: 'large',
enableToggle: true,
cls: 'infoBt',
handler: showHideInfos
}]
});
};

NB: The "new" ensures it is called. You do not need the "()" after it. This is how the new Ext.data.Types singleton is created.

Animal
9 Jun 2010, 2:38 AM
thanks for the reply animal.

i think you mean the scope of the button-handler is wrong?!
i already tried to set the scope of the hanlder to "this". but still the handler doesn't even get called.

Yes, that's what I thought at first. But looking at the handler, it never refers to "this", so doesn't need scoping. It's something to always bear in mind though!

sinus
9 Jun 2010, 5:47 AM
@condor

I already tried that before and it works. So i'll go down that road now...

But still i wonder ... in the "code structure"-thread there is the example:




var bubbly = function () {

var foo = 1; // private through closure

return {

public1: 3,
privileged1: foo, // privileged can refer to private
privileged2: function(){
var ans;
ans = foo;
return ans;
},
privileged3: function(){
var ans;
// refer to other public properties with 'this'
ans = foo + this.public1;
return ans;
}
}
}(); // parens immediately evaluates the function and
// assigns the returned result to variable 'bubbly'

bubbly.public1; // 3
bubbly.privileged1; // 1
bubbly.foo; // undefined
bubbly.privileged2(); // 1
bubbly.privileged3(); // 4












"public1" gets called by "privileged3" and they are both inside the return-object. Can't see the difference to what i was trying to do in thr first place...

Condor
9 Jun 2010, 6:11 AM
In your example 'this.showHideTopics' is used before 'this' actually exists (it only exists after the contructor returned the object).

In the example above 'this.plublic1' is used when privileged3 executes, so 'this' does exist.

sinus
9 Jun 2010, 6:31 AM
got it. thanks to both of you for the quick help.
got me going again!

cheers sinus.