View Full Version : A question of scope in custom name space
acebone
30 Aug 2007, 6:07 AM
In my custom namespace, I'd like to retrieve a reference for an existing DOM object - however Ext.get() fails me (or rather - I can't see through the scope issues)
Consider this code:
// reference local blank image
Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif';
// create namespace
Ext.namespace('bb');
// create application
bb.app = function() {
// do NOT access DOM from here; elements don't exist yet
// private variables
// private functions
// public space
return {
// public properties, e.g. strings to translate
// public methods
init: function() {
// Create a login form in a dialog
this.loginDlg = new Ext.BasicDialog("my-dlg", { height: 200,
width: 300,
minHeight: 100,
minWidth: 150,
modal: true,
autoCreate : true,
proxyDrag: true,
animateTarget : 'divBebonetToolbar',
shadow: true
});
var dlg = this.loginDlg
dlg.addKeyListener(27, dlg.hide, dlg); // ESC can also close the dialog
dlg.addButton('Annuller', dlg.hide, dlg); // Could call a save function instead of hiding
dlg.addButton('Log ind', dlg.hide, dlg);
/**********************************
HOW CAN I GET THIS LINE TO WORK LIKE....
**********************************/
alert(Ext.get('divBebonetToolbar').innerHTML)
/**********************************
... THIS LINE ?
**********************************/
alert(document.getElementById('divBebonetToolbar').innerHTML)
},
};
}(); // end of app
// end of file
Ext.onReady(bb.app.init, bb)
Ext.onReady( function() {
})
Obviously I run bb.app.init in the bb namespace
Ext.onReady(bb.app.init, bb)
But how do I tell Ext.get to operate in the window namespace, so that I might get the actual/existing DOM nodes ?
ApocalypseCow
30 Aug 2007, 6:19 AM
I think it could be a couple of things:
1. is there an element with an id of divBebonetToolbar in the dom?
2. the line :
alert(Ext.get('divBebonetToolbar').innerHTML)
will display undefined because an Ext element doesn't have an innerHTML property.
You could access it via Ext.get('divBebonetToolbar').dom.innerHTML instead, although I'd question why you were trying to access it in this way in the first place.
Have a look at the docs for Element to help you out further:
http://extjs.com/deploy/ext/docs/output/Ext.Element.html
acebone
30 Aug 2007, 7:10 AM
Sorry about the innerHTML nonsense - that's not what I want to do at all
I totally misunderstood my own problem !
But yes - the DIV 'divBebonetToolbar' is in the markup of the page, so it already exists when Ext.onReady is executed
What I want to do is this:
// HOW CAN I GET THIS LINE TO WORK LIKE....
Ext.get('divBebonetToolbar').on('click', bb.loginDlg.show)
That is - when somebody clicks the divBebonetToolbar DIV - the logindialog should pop up.
I've tried this as well:
// THIS LINE ?
document.getElementById('divBebonetToolbar').onclick = bb.loginDlg.show
BOTH methods gives the same error when the DIV is clicked:
this.fireEvent is not a function
http://localhost/b2/fileadmin/extjs/ext-all.js
Line 136
However if I execute
bb.loginDlg.show()
directly from the console of firebug - the dialog appears as it should.
As far as I can see it's still a question of scope though....
Animal
30 Aug 2007, 7:13 AM
Ext.get('divBebonetToolbar').on('click', bb.loginDlg.show, bb.loginDlg)
acebone
30 Aug 2007, 7:31 AM
Ext.get('divBebonetToolbar').on('click', bb.loginDlg.show, bb.loginDlg)
YES !
Through the documentation I found out that Ext.get() returns an 'Element', but I can't find the method 'on' of Element in the docs - so I don't know what that third param actually does.
If it sets the scope to bb.loginDlg - then I'd be calling bb.loginDlg.bb.loginDlg.show() - and that is obviously not what is happening.
BUT !!
Another scope-error creeps in now - because I get:
Ext.get(this.animateTarget, true) has no properties
http://localhost/b2/fileadmin/extjs/ext-all.js
Line 136
sorry to seem such a dork - but eh... I am learning !
Animal
30 Aug 2007, 7:34 AM
It's a synonym for http://extjs.com/deploy/ext/docs/output/Ext.Element.html#addListener
Animal
30 Aug 2007, 7:36 AM
Your scope, "this" is not correct.
What object do you expect it to be?
acebone
1 Sep 2007, 8:43 AM
I had the forum in 'hybrid' mode, thus it didn't show me your last reply! Weird....
Well - I didn't set the this scope, obviously Ext wants me to, but I'd like the animate target to be the already existing div-layer "#divBebonetToolbar"
Instead of ID'ing the div with a string, I tried to assign a ref to the div, like this:
// Create a login form in a dialog
this.loginDlg = new Ext.BasicDialog("my-dlg", { height: 200,
width: 300,
minHeight: 100,
minWidth: 150,
modal: true,
autoCreate : true,
proxyDrag: true,
animateTarget : document.getElementById('divBebonetToolbar'), // Trying another angle here
shadow: true
});
But I get the exact same error
Animal
2 Sep 2007, 11:13 PM
That's not where your problem is.
Somewhere, you are specifying a method of BasicDialog as a handler, without specifying that dialog as the scope in which to execute that function, so when that function tries to access this.animateTarget, "this" is the window, and so the statement fails.
acebone
3 Sep 2007, 3:01 AM
That's not where your problem is.
Somewhere, you are specifying a method of BasicDialog as a handler, without specifying that dialog as the scope in which to execute that function, so when that function tries to access this.animateTarget, "this" is the window, and so the statement fails.
No, if I understand correctly, I do specify the scope as per your earlier advice
Ext.get('divBebonetToolbar').on('click', bb.loginDlg.show, bb.loginDlg)
Here is my entire code again (to eliminate misunderstandings)
// reference local blank image
Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif';
// create namespace
Ext.namespace('bb');
// create application
bb.app = function() {
// do NOT access DOM from here; elements don't exist yet
// private variables
// private functions
// public space
return {
// public properties, e.g. strings to translate
// public methods
init: function() {
// Create an empty DOMContainer for our effects to appear in
this.DOMContainer = Ext.DomHelper.append(document.body, {tag : 'div',
id : 'bb-container',
style : 'display : none'
})
// Create a login form in a dialog
this.loginDlg = new Ext.BasicDialog("my-dlg", { height: 200,
width: 300,
minHeight: 100,
minWidth: 150,
modal: true,
autoCreate : true,
proxyDrag: true,
animateTarget : document.getElementById('divBebonetToolbar'),
shadow: true
});
var dlg = this.loginDlg
dlg.addKeyListener(27, dlg.hide, dlg); // ESC can also close the dialog
dlg.addButton('Annuller', dlg.hide, dlg); // Could call a save function instead of hiding
dlg.addButton('Log ind', dlg.hide, dlg);
// HOW CAN I GET THIS LINE TO WORK LIKE....
Ext.get('divBebonetToolbar').on('click', bb.loginDlg.show, bb.loginDlg)
}
};
}(); // end of app
// end of file
Ext.onReady(bb.app.init, bb)
Animal
3 Sep 2007, 3:34 AM
OK, are you sure "divBebonetToolbar" exists? What happend is you set a breakpoint where you create the dialog, and see what document.getElementById('divBebonetToolbar') returns?
acebone
3 Sep 2007, 4:07 AM
The div is in the markup, so yes I am pretty sure it exists when Ext.onReady is executed.
I had to change the code a little bit, in order for firebug to tell me what was going on:
// Create a login form in a dialog
var options = { height: 200,
width: 300,
minHeight: 100,
minWidth: 150,
modal: true,
autoCreate : true,
proxyDrag: true,
animateTarget : document.getElementById('divBebonetToolbar'),
shadow: true
}
options.animateTarget // this line is only for debug purposes
this.loginDlg = new Ext.BasicDialog("my-dlg", options);
Evaluating options.animateTarget shows me that it has got the right div (#divBebonetToolbar). ID is right, and it has the right .innerHTML
Animal
3 Sep 2007, 4:24 AM
So what causes the error?
acebone
3 Sep 2007, 5:01 AM
So what causes the error?
That is indeed the question - Being a ExtJS newbie, I haven't got the faintest idea.
The bb.loginDlg.show method is definitely assigned to the divBebonetToolbar onclick event - when I click it, the page dims and the error occurs. If I execute bb.loginDlg.show() from the console of firebug, the dialogue appears as it should (animating from divBebonetToolbar as I want it to).
I am stumped!
Animal
3 Sep 2007, 5:28 AM
Post a link to a running versino of this page, and we'll be able to fix it.
acebone
3 Sep 2007, 6:45 AM
I had to extract it out of out typo3 CMS and make sure all the includes were there. I think I managed, the erroneous behaviour is the same:
http://www.baldersbo.dk/test/
If you start by executing bb.loginDlg.show() - you'll be able to see which DIV is divBebonetToolbar
Animal
3 Sep 2007, 6:50 AM
Nope, can't do anything with that. Hundreds of JS errors - don't know what to do with anything, every pixel the mouse moves throws up JS errors.
Animal
3 Sep 2007, 6:53 AM
use ext-all-debug.js and actually break in BasicDialog.show
acebone
3 Sep 2007, 7:01 AM
Strange ... it works perfectly unright in my browser.... no errors except the ones I expect.
Gotta pack it in now, but will post later (tomorrow) with results of using the debug version.
Thnx for your awesome help so far !
acebone
4 Sep 2007, 4:45 AM
I've boiled the whole thing down to a simple showcase. It is located at http://baldersbo.dk/test
I've tested it in IE7 as well as Firefox - there should be no errors except the expected.
I've found out that it is very much a scope thing - if you look at the bottom of the following code, you can see two kinds of errors different scope assignment produces
Ext.BLANK_IMAGE_URL = 'resources/images/default/s.gif';
Ext.namespace('bb');
bb.app = function() {
return {
init: function() {
// Create a login form in a dialog
var options = {
height: 100,
width: 150,
modal: true,
autoCreate : true,
proxyDrag: true,
animateTarget : 'divBebonetToolbar',
shadow: true
}
this.loginDlg = new Ext.BasicDialog("my-dlg", options);
var dlg = this.loginDlg
dlg.addButton('Annuller', dlg.hide, dlg); // Could call a save function instead of hiding
dlg.addButton('Log ind', dlg.hide, dlg);
/*
this.fireEvent is not a function
file:///D:/www/typo3/htdocs/exttest/ext-all-debug.js
Line 17014
*/
// Ext.get('divBebonetToolbar').on('click', bb.loginDlg.show)
/*
this.fireEvent is not a function
file:///D:/www/typo3/htdocs/exttest/ext-all-debug.js
Line 17014
*/
//Ext.get('divBebonetToolbar').on('click', bb.loginDlg.show, bb)
/*
Ext.get(this.animateTarget, true) has no properties
file:///D:/www/typo3/htdocs/exttest/ext-all-debug.js
Line 17004
*/
Ext.get('divBebonetToolbar').on('click', bb.loginDlg.show, bb.loginDlg)
}
};
}();
Ext.onReady(bb.app.init, bb)
It oughta be possible to assign event handlers from inside a construction like this, but I am still stumped....
Animal
4 Sep 2007, 5:04 AM
Works perfectly.
acebone
4 Sep 2007, 6:37 AM
I hope you mean that it works in the sense it produces the right errors ?
If it just plainly works - thats me ALL confudded
Animal
4 Sep 2007, 6:40 AM
Nope. Just works.
acebone
4 Sep 2007, 6:45 AM
Oh - I get it - it's because you try the button, and yes that will work. It's defined like this:
<input type="button" onclick="bb.loginDlg.show()".... etc....
Try clicking the white div named #divBebonetToolbar - you'll get the error
Animal
4 Sep 2007, 6:52 AM
OK, I got it.
The click event handler is passed the event as its first parameter. You're specifying BasicDialog's show method as the handler.
BasicDialog.show uses its parameter as an animate target.
So that doesn't work!
Ext.get('divBebonetToolbar').on('click', function() {bb.loginDlg.show();});
acebone
4 Sep 2007, 7:02 AM
You've got it!!
I've updated the test-case (http://baldersbo.dk/test/) with your code, and it works!
Let me see if I got this straight:
If NO parameter is passed to BasicDialog.show - then it looks to see if it already has an animTarget defined (which in this case - it has)
But when an event is triggered, whatever function is called is passed one parameter (namely an event object), so BasicDialog.show() was passed an event-object an tried to make that the animTarget - which of course failed.
Is that a correct understanding ?
Thanx ever so much for your incredible patience!
Animal
4 Sep 2007, 7:25 AM
That's correct.
acebone
4 Sep 2007, 7:28 AM
So it turned out that this wasn't a scope related problem at all, because even
Ext.get('divBebonetToolbar').on('click', function(){bb.loginDlg.show()})
(without the scope assignment) works !
Thank you again!
Animal
4 Sep 2007, 7:30 AM
It doesn'tneed the scope because it's using the global reference to the dialog to directly call the dialog's show method.
Powered by vBulletin® Version 4.1.5 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.