Tutorial:Application Layout for Beginners (Legacy)
This version of our Learning Center is unmaintained.
This article may be out-of-date or contain incorrect information.
Please visit the new Sencha Learning Center for up-to-date material.
From Sencha - Learn
| Summary: This tutorial helps you to create your application right way. |
| Author: Jozef Sakalos |
| Published: August 25, 2007 |
| Ext Version: 1.1+ / 2.0+ |
Languages: English Chinese Portuguese
|
Contents |
Before you start
This tutorial assumes that you have already installed ExtJS - JavaScript Library and that it is installed in directory extjs one directory up from our application directory. If you have installed Ext JS elsewhere you will need to change paths in src attributes of script tags in example files.
What do we need?
Besides the ExtJS - JavaScript Library we need two files:
- applayout.html
- applayout.js
Let's start with files with minimum content. Here they are together with detailed explanation:
applayout.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link rel="stylesheet" type="text/css" href="../extjs/resources/css/ext-all.css"> <script type="text/javascript" src="../extjs/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../extjs/ext-all-debug.js"></script> <script type="text/javascript" src="applayout.js"></script> <!-- A Localization Script File comes here --> <script type="text/javascript"> Ext.onReady(myNameSpace.app.init, myNameSpace.app); </script> <title>Application Layout Tutorial</title> </head> <body> <div id="btn1-ct"></div> </body> </html>
The first two lines specify the document type. The application could run without a doctype, however, in this case the browser would probably go into Quirks Mode which would detract from the cross-browser compatibility of your application.
We will use HTML 4.01 Transitional for the purpose of this tutorial because this doctype is supported very well by all major browsers. Of course, you can use any other document type if you want or need but keep in mind that you should always specify a doctype.
After the start of html and head comes Content-Type specification. Again, your application can live without it but it should be there.
Then we include Ext styles, adapter and ExtJS itself. There are two versions of ExtJS:
- ext-all.js - human unreadable, loads faster, for production
- ext-all-debug.js - human readable, for development
We're going to develop, include debug version then.
Then comes our application applayout.js and, after it, any localization scripts that can override English texts in applayout.js and ExtJS with translated versions before the application is initialized.
Now we're ready to install event handler that initializes (runs) our application after the document is fully loaded.
Line
Ext.onReady(myNameSpace.app.init, myNameSpace.app);
says: When the document is fully loaded, run init method of myNameSpace.app in the scope of myNameSpace.app.
Then come title, end of head, body (empty for now) and closing tags.
That's all for our minimal html file.
applayout.js
/** * Application Layout * by Jozef Sakalos, aka Saki * http://extjs.com/learn/Tutorial:Application_Layout_for_Beginners */ // reference local blank image Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif'; // create namespace Ext.namespace('myNameSpace'); // create application myNameSpace.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() { alert('Application successfully initialized'); } }; }(); // end of app // end of file
First lines of this file are comments that explain content of the file, author and another relevant information. Sure, your applications would run without any single comment line but remember: Always write your application as if you were writing it for another. When you come back to your own code after a couple of months and you don't know what it does then remember the above rule and change your coding practices.
Then comes the reference to blank image pointing to your own server instead of default extjs.com. You don't want to access extjs.com on each application load, do you?
Now we create our own namespace. The reason is to encapsulate all variables and methods in one global object to avoid any conflicts of variable names and unpredictable changes of their values by various functions should they be global. The name you choose is up to you.
The core of it, at last... We create property app of myNameSpace as the return value of the function that runs immediately.
If we run the following code
var o = function() { return {p1:11, p2:22}; }();
we're in fact creating an anonymous function (function without name) that runs immediately after parsing (mind () after the function definition). The function returns an object which is assigned to the variable o. Our application will use the same logic.
You can put an initialization, private variables, and/or private functions definitions between the beginning of the function and return statement but keep in mind: This code runs as a part of head when no html elements yet exist so any attempt to access them would result in an error.
On the other hand, the init function, that is just one of the methods returned by that anonymous function, runs after the whole document is fully loaded when the whole DOM structure is already available.
So far, so good. If you haven't made any mistakes you get a success alert when you navigate to http://example.com/applayout/applayout.html (in another words, when you run your application).
Now comes most difficult part: To write something useful inside of this empty template.
Public, Private, Privileged?
Let's add some life to our application. Add the following line to applayout.html inside the body tag:
<div id="btn1-ct"></div>
It is an empty div that will serve as the button container. Then add a couple of lines to applayout.js so that it reads:
/** * Application Layout * by Jozef Sakalos, aka Saki * http://extjs.com/learn/Tutorial:Application_Layout_for_Beginners */ // reference local blank image Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif'; // create namespace Ext.namespace('myNameSpace'); // Just to allow this tutorial to work for 1.1 and 2. Ext.Ext2 = (Ext.version && (Ext.version.indexOf("2") == 0)); // create application myNameSpace.app = function() { // do NOT access DOM from here; elements don't exist yet // private variables var btn1; var privVar1 = 11; // private functions var btn1Handler = function(button, event) { alert('privVar1=' + privVar1); alert('this.btn1Text=' + this.btn1Text); }; // public space return { // public properties, e.g. strings to translate btn1Text: 'Button 1', // public methods init: function() { if (Ext.Ext2) { btn1 = new Ext.Button({ renderTo: 'btn1-ct', text: this.btn1Text, handler: btn1Handler }); } else { btn1 = new Ext.Button('btn1-ct', { text: this.btn1Text, handler: btn1Handler }); } } }; }(); // end of app // end of file
Variables btn1 and privVar1 are private. That means that they cannot be accessed, and that they are not even visible outside of your application. The same is true for the private function btn1Handler.
On the other hand, btn1Text is public variable that is visible and can be accessed or changed from outside of your application. (We will demonstrate it later.)
Function init is privileged in that it can access both private and public variables or functions. In our example, it accesses public variable this.btn1Text and also private function btn1Handler. Function init is public in that that it can be called from outside.
Ok, let's run it. Do you see the button in the upper left corner? Good. Click it. You get an alert with privVar1=11, right? Private function can access private variables.
But something is wrong with our second alert which reads this.btn1Text=undefined; that is not what was expected. The reason is that variable this inside of handler points to button and not to our application. Add scope:this to the button configuration so that it reads:
if (Ext.Ext2) { btn1 = new Ext.Button({ renderTo: 'btn1-ct', text: this.btn1Text, handler: btn1Handler, scope:this }); } else { btn1 = new Ext.Button('btn1-ct', { text: this.btn1Text, handler: btn1Handler, scope:this }); }
and reload the page. Works, yeah?
Overriding public variables
Add the following code near the end of applayout.js so that it reads:
Ext.apply(myNameSpace.app, { btn1Text:'Taste 1' }); // end of file
What does the whole code do now? It first creates our application object and then changes (overrides) the value of the public variable btn1Text. Run it to see that the text displayed on the button has changed.
It is good coding practice to put all text used by an application in public variables, as they can then easily be translated to other languages without touching the original application code.
Of course, you should also put other values such as default dimensions, styles, i.e. all customizable options, into public variables. Then you won't need to browse through thousands of lines of application code to find where to change the color of something.
Overriding public functions
Let's change our code that it reads the following:
Ext.apply(myNameSpace.app, { btn1Text:'Taste 1', init: function() { try { btn1 = new Ext.Button('btn1-ct', { text: this.btn1Text, handler: btn1Handler, scope: this }); } catch(e) { alert('Error: "' + e.message + '" at line: ' + e.lineNumber); } } }); // end of file
What are we doing here? Just overriding the init function with exactly the same code as before, only enclosed in a try/catch block so we can handle any errors. Should we expect it to run the same as it did before, or differently? Run it to find out.
Yes, there is an error stating that btn1Handler is not defined. It is because the updated function is trying to access a private variable, but it cannot. You see, the original init is privileged so it had access to private space, but the new init does not. There is also an aspect of safety in this: No code from outside can access the private space, even if it tries to override privileged methods.
To be continued...
I'm releasing this first part of the tutorial as I think that it can be useful as is; nevertheless, I plan to continue with another example.

English