EXT JS
In the world of Rich Internet Applications (RIA) development, Ext JS stands out as a cross-browser JavaScript library that offers the applications developer a powerful toolset. With a set of customizable user interface widgets similar to those found in desktop operating systems, an effective data binding model, a comprehensive programming interface for manipulating the Document Object Model and communicating with the server, a committed development team, and an enthusiastic users' community, the Ext JS library is a great choice for today's web builders.
EXT JS OVERVIEW
Ext JS is a cross-browser JavaScript library for building rich internet applications. It includes:
• High performance, customizable UI widgets
• Well designed and extensible Component model
• An intuitive, easy to use API
• Commercial and Open Source licenses available
BROWSER COMPATIBILITY
Ext JS supports all major web browsers including:
• Internet Explorer 6+
• FireFox 1.5+ (PC, Mac)
• Safari 3+
• Chrome 3+
• Opera 9+ (PC, Mac)
DOWNLOAD EXT
If you haven't done so already, you'll first want to download the most current Ext release which can always be found here: http://extjs.com/products/extjs/download.php.
There are several different options for what you can download, but you'll probably want to start with the most current stable production version available. Once you download and unzip the file, you're pretty much ready to go, but read on for some specifics depending on your server setup.
CONFIGURE
Some Ext JS examples require a HTTP server (and some a PHP server). This does not mean that Ext JS can only be used in combination with a HTTP server.
Ext JS code that uses server requests requires a HTTP web server (access pages through a webserver viahttp://something).
NO WEB SERVER
You can actually run Ext JS without a web server thanks to Doug Hendricks. If you would like to run Ext without a web server, check out this forum post.
IIS - MICROSOFT INTERNET INFORMATION SERVICES
If you encounter any difficulties on a IIS platform, additional tips can be found in this forum post.
APACHE
If you encounter issues with Apache on windows (files being corrupted), additional tips can be found in this forum post.
THE DEMOS / EXAMPLES
A good place to start exploring is the examples directory and the wiki (tutorials and manual). The examples directory in the download package has several working examples, please note the following:
Ext uses a 1x1 transparent gif image to create inline icons with CSS background images. The default URL to this file is "extjs.com/s.gif", so you'll want to change this somewhere at the top of your code by telling Ext where to find the empty image. You can modify the URL as needed with a command like this:
Ext.BLANK_IMAGE_URL = '/images/ext/resources/images/default/s.gif';
LET'S GET STARTED
We're going to walk through some of the most common tasks that people have to accomplish in Javascript and how to perform them using Ext. If you'd like to experiment as you go, you should download the starter files in IntroToExt2.zip which we will use to build up a page of working Ext code.
This zip contains four files: ExtStart.html, ExtStart.js, ExtStart.css and ajax-example.php.
- Unzip all 4 files into a folder directly under the folder where Ext is installed (for example, if Ext is at "C:\code\ext-2.0\," create a new folder under "ext-2.0\" called "tutorial" ie. "C:\code\ext-2.0\tutorial\").
- Double-click ExtStart.html so that it launches in your default web browser, and you should get a message telling you that everything is configured correctly. If you get a JavaScript error, please follow the instructions on that page to get it working.
Now you're ready to open ExtStart.js in your favorite IDE or text editor and take a look at it:
Ext.onReady(function() {
alert("Congratulations! You have Ext configured correctly!");
});
Ext.onReady is probably the first method that you'll use on every page. This method is automatically called once the DOM is fully loaded, guaranteeing that any page elements that you may want to reference will be available when the script runs. You can go ahead and delete the alert() line now so that we can start adding some real code that actually does something useful!
ELEMENT: THE HEART OF EXT
Almost everything you do in Javascript will at some point involve referencing specific elements on your page so that you can do interesting things with them. Using traditional Javascript, selecting a DOM node by ID is done like this:
var myDiv = document.getElementById('myDiv');
This works just fine, but the object that is returned (a DOM node) doesn't offer much in the way of power or convenience. In order to do anything useful with that node, you are left still writing a lot of custom plumbing code yourself. Plus it is your responsibility to handle all of the differences in how the node can be used from browser to browser, which can be daunting.
Enter the Ext.Element object. The Element really is the heart of Ext as most of what you'll do involves getting access to Elements and performing actions on them. The Element API is fundamental to the entire Ext library, and if you spend the time to really learn only one class in Ext well, Element should be it!
The corresponding code to get an Ext Element by ID looks like this (the starter page ExtStart.html contains a div with the id "myDiv," so go ahead and add this code to ExtStart.js):
Ext.onReady(function() {
var myDiv = Ext.get('myDiv');
});
So we are getting back an Element object now—what's so interesting about that?
- Element wraps most of the DOM methods and properties that you'll need, providing a convenient, unified, cross-browser DOM interface (and you can still get direct access to the underlying DOM node when you need it via Element.dom)
- The Element.get() method provides internal caching, so multiple calls to retrieve the same object are incredibly fast
- The most common actions performed on DOM nodes are built into direct, cross-browser Element methods (add/remove CSS classes, add/remove event handlers, positioning, sizing, animation, drag/drop, etc.)
This means that you can do all kinds of useful stuff with very minimal code. Here are just a few simple examples (see theElement API documentation for the complete list of everything that you can do). Go ahead and try adding some of these to ExtStart.js after the previous line where we got the 'myDiv' Element:
myDiv.highlight(); // The element's background will highlight to yellow then fade back
myDiv.addClass('red'); // Add a custom CSS class (defined in ExtStart.css)
myDiv.center(); // Center the element in the viewport
myDiv.setOpacity(.25); // Make the element partially-transparent
SELECTING DOM NODES
Often it is either impractical or impossible to select DOM nodes by ID. Maybe the ID is not set, or you don't know it, or there are too many elements to practically reference directly by ID. Sometimes you may want to select nodes based on something other than ID, like an attribute or a CSS classname. For these reasons, Ext ships with an extremely powerful DOM selector library called DomQuery.
DomQuery can be used as a standalone library, but more often when using Ext, you'll use it in the context of selecting Elements so that you can then act on them via the Element interface. Luckily, the Element object itself supports querying via the Element.select method, which internally uses DomQuery to select elements. As a simple example of how you might use this, the ExtStart.html file contains several paragraph (
) tags, none of which have ids. If you wanted to easily select every paragraph and perform an action on all of them at once, you could do something like this:
// Highlights every paragraph
Ext.select('p').highlight();
This example demonstrates a very handy aspect of Element.select—it returns a CompositeElement, which provides access to every underlying Element via the Element interface. This allows you to easily act on every Element instance returned by Element.select without looping and touching each one individually.
DomQuery supports a wide array of selection options, including most of the W3C CSS3 DOM selectors, basic XPath, HTML attributes and a lot more. Please see the DomQuery API documentation for complete details on this powerful library.
RESPONDING TO EVENTS
So far in our examples, all of the code we've written has been directly inside the onReady function, which means that it always executes immediately after the page loads. This doesn't give us much control—you will most commonly want your code to execute in response to specific actions or events that you choose to handle. To do this, you define event handlers that can respond to events using functions that you assign.
Let's start off with a simple example. Open up ExtStart.js and edit it so that your code looks like this:
Ext.onReady(function() {
Ext.get('myButton').on('click', function(){
alert("You clicked the button");
});
});
The code still executes when the page loads, but there's an important difference. The function containing the alert() is defined, but is not actually executed immediately—it is assigned as the "handler" of the button click event. Spelled out in plain English, this code might read: "Get a reference to the Element with id 'myButton' and assign a function to be called anytime someone clicks on the Element."
Not surprisingly, Element.select allows you to do the same thing, but with an entire group of Elements at once. For example, to show our message when any paragraph in our test page is clicked, we could do this:
Ext.onReady(function() {
Ext.select('p').on('click', function() {
alert("You clicked a paragraph");
});
});
In these two examples, the event handling function is simply declared inline, without giving it a function name. The term for this type of function is an "anonymous function" since it is declared without ever being named. You can also assign an event to be handled by a named function, which is especially useful if you want to reuse the function and have it handle multiple events. For example, this code is functionally equivalent to the previous example:
Ext.onReady(function() {
var paragraphClicked = function() {
alert("You clicked a paragraph");
}
Ext.select('p').on('click', paragraphClicked);
});
So far we have looked at performing a generic action when our event is raised, but how do we actually know which specific Element raised the event so that we can perform some action on it? It turns out to be pretty easy—the Element.onmethod passes three extremely useful parameters to the event handling function (we're only going to look at the first one here, but you should explore the API documentation to learn more about event handling details). In our previous examples our handling function was ignoring these parameters, but with one simple change, we can provide an additional level of functionality. The first, and most important, parameter is the event that occurred. This is actually an Ext.EventObject, which is both normalized across browsers and provides more information than the standard browser event. For example, the event's target DOM node can be retrieved with this simple addition:
Ext.onReady(function() {
var paragraphClicked = function(e) {
Ext.get(e.target).highlight();
}
Ext.select('p').on('click', paragraphClicked);
});
Note that target is a DOM node, so we first retrieve the corresponding Element, then perform whatever action we want on it. In this case, we are visually highlighting the paragraph.
PASSING ARGUMENTS TO EVENT HANDLERS
Here's a quick example on how to pass arguments to an event handler using createDelegate:
var someHandler = function(evt,t,o,myArg1,myArg2,myArg3) {
//do stuff
}
Ext.select('.notice-type1').addListener('click', someHandler.createDelegate(this, [4,'pizza',11], true));
Ext.select('.notice-type2').addListener('click', someHandler.createDelegate(this, [7,'stuff',12], true));
The function someHandler will get called with the following arguments:
evt, t, o
These are the arguments that would get passed to your event handler normally. They are: the EventObject describing the event, the Element which was the target of the event, and the options object from the addListener call. See addListener in the API for more information. You can also set a breakpoint in Firebug inside your event handler to check these objects out and see what kind of useful things they contain.
myArg1, myArg2, myArg3
your own custom arguments specified as an array which is passed as the second argument to createDelegate. In this case we're passing 4,'pizza',11 for elements of class "notice-type1" and 7,'stuff',12 for elements of class "notice-type2".
If all you want to do is pass custom arguments to the even handler and you don't need to have access to the element that fired the event you're probably better off just using createCallback.
See addListener and Function for more details.
USING WIDGETS
In addition to the core javascript library that we've been discussing, Ext also includes one of the richest sets of Javascript UI widgets available today. There are far too many to cover in this introduction, but let's take a look at a couple of the widgets that people use most commonly and how easy they are to work with.
MessageBox
Rather than a boring "Hello World" message box, let's add a little twist. We already have code that we wrote in the previous section that highlights each paragraph when you click on it. Let's modify that code to also show the text of the paragraph that was clicked in a message box. In the paragraphClicked function above, replace the line:
Ext.get(e.target).highlight();
...with this code:
var paragraph = Ext.get(e.target);
paragraph.highlight();
Ext.MessageBox.show({
title: 'Paragraph Clicked',
msg: paragraph.dom.innerHTML,
width:400,
buttons: Ext.MessageBox.OK,
animEl: paragraph});
There are a couple of new concepts being shown here that are worth discussing. In the first line, we are now creating a local variable named paragraph that will hold a reference to the Element representing the DOM node that was clicked (in this case we know it will always be a paragraph since our click event is only associated with
tags). Why are we doing this? Well, looking ahead for a moment, we will need a reference to the Element to highlight it, and we'll also use the same Element for some of the MessageBox parameters. In general, it is bad practice to make the same function call multiple times to retrieve the same value or object reference, so by assigning it to a local variable and reusing the variable, we are being good object-oriented developers!
Now, on to the MessageBox call, which demonstrates the other new concept for us to discuss. At first glance, this may look simply like a list of parameters being passed to a method, but if you look closely, there is a very specific syntax. What is actually being passed to MessageBox.show() in this case is only one parameter: an object literal that contains a set of properties and values. In JavaScript, an object literal is a dynamic, generic object that is created anytime you use the { and } characters surrounding a list of name/value properties, and the format for those properties is [property name] : [property value]. You'll see this pattern used extensively throughout Ext, so you should learn it well!
Why use an object literal? The main reason is flexibility. New properties can be added or removed from the object literal at any time, or defined in any order, while the method signature (the number and types of parameters expected by a method) never has to change. It also makes it far more convenient from the end developer's perspective when using methods with many optional parameters (as in the case of MessageBox.show). For example, let's say that a fictional method foo.action has four optional parameters, but you only need to pass one of them. In this case, your code might look like this: foo.action(null, null, null, 'hello'). However, if that method instead took an object literal, the code would look like this: foo.action({ param4: 'hello' }). Much easier to use, much more readable.
GRID
The grid is one of the most popular widgets in Ext, and usually the first one that people want to see, so let's take a look at how easy it is to get a basic grid up and running. Replace any existing code you have in ExtStart.js so that it looks like this:
Ext.onReady(function() {
var myData = [ ['Apple',29.89,0.24,0.81,'9/1 12:00am'],
['Ext',83.81,0.28,0.34,'9/12 12:00am'],
['Google',71.72,0.02,0.03,'10/1 12:00am'],
['Microsoft',52.55,0.01,0.02,'7/4 12:00am'],
['Yahoo!',29.01,0.42,1.47,'5/22 12:00am']
];
myReader = new Ext.data.ArrayReader({}, [{name: 'company'},{name: 'price', type: 'float'},{name: 'change', type: 'float'},{name: 'pctChange', type: 'float'},{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
]);
var grid = new Ext.grid.GridPanel({
store: new Ext.data.Store({data: myData,reader: myReader}),
columns: [{header: 'Company', width: 120, sortable: true, dataIndex: 'company'},
{header: 'Price', width: 90, sortable: true, dataIndex: 'price'},
{header: 'Change', width: 90, sortable: true, dataIndex: 'change'},
{header: '% Change', width: 90, sortable: true, dataIndex: 'pctChange'},
{header: 'Last Updated', width: 120, sortable: true,
renderer: Ext.util.Format.dateRenderer('m/d/Y'),dataIndex: 'lastChange'}],
viewConfig: {
forceFit: true
},renderTo: 'content',
title: 'My First Grid',
width: 500,
autoHeight: true,
frame: true});
grid.getSelectionModel().selectFirstRow();
});
While this looks like a lot, it is really only 4 lines of code in total (3 if you don't count the test data)!
- The first line of code creates an array of test data to be displayed in the grid. In real projects, you would likely load this data from some dynamic source like a database or web service.
- Next, we create a data reader that knows how to interpret the data and convert it into usable records for the grid's data store. There are several different types of Reader classes for different types of data.
- Next, we create the grid widget, passing in all sorts of config values, including:
- A new data store, configured on the fly with our test data and reader
- The column model definition using the columns config
- Additional options to set up specific grid features
- Finally, we tell the grid to highlight its first row via the SelectionModel.
Of course, there will probably be some details about this code that you may not fully understand at this point. The intent of this example is to show how it's possible to create an extremely rich, visually-complex user interface component with very few lines of code—learning the details will be left as an exercise for the reader. There are many resources to help you with learning the grid, including the interactive grid demos and the GridPanel API documentation.
And Many More...
We've only seen the tip of the iceberg here. There are literally dozens of UI widgets to choose from in Ext, including automatic page layouts, tabs, menus, toolbars, dialogs, a tree view and many more. Please explore the interactive examples for a glimpse of everything that's available.
USING AJAX
Once you have your page created and you know how to interact with it through Javascript, you'll probably want to know how to get data to and from a remote server, most commonly to load and save data from a database on the server. Doing this asynchronously via Javascript without reloading the page is known commonly as Ajax, and Ext has excellent Ajax support built right in. For example, a common goal is to handle a user interaction, post something to the server asynchronously, then update an element of the UI in response to the action. Here's an example of a very simple HTML form containing a text input field, a button, and a div used to display a message (Note: you can add this code to ExtStart.html if you'd like to follow along, but you'll have to have access to a web server in order to run the server code below):
Name:
Next, we'll add the Javascript required to get our data and post it to a server-based process (replace any existing code in ExtStart.js with this):
Ext.onReady(function(){
Ext.get('okButton').on('click', function(){
var msg = Ext.get('msg');
msg.load({
url: 'ajax-example.php', // <-- change if necessary
params: 'name=' + Ext.get('name').dom.value,
text: 'Updating...'
});
msg.show();
});
});
Note: This example will only run from a web server. The URL in your browser should start with http:// and not file:// or the Ajax transaction will not work! Localhost will work fine, but it must be via http.
The real challenges when dealing with Ajax processing involve all of the plumbing code required to properly process and format real structured data on the server. There are several formats to choose from that people use commonly (most often either JSON or XML). There are also many language-specific libraries available to deal with Ajax processing that can work well with Ext, as Ext is language-neutral with regard to the server. As long as the result is sent to the page in the proper data format, Ext does not care what happens on the server! Please see our list of platform-specific resources for additional information about server-side frameworks and tools.
REFERENCES
1. Pronunciation thread on Ext forum
2. (see also, Rich Internet application
3. Ext as of version 2.0 can works with different base libraries or adapters. (e.g. YUI, jQuery, Prototype), or it can work standalone.
4. API documentation includes a migration guide. http://extjs.com/deploy/dev/docs/
5. http://extjs.com/learn/Ext_1_to_2_Migration_Guide
6. ExtJS forum thread on the license change
7. http://www.gnu.org/licenses/lgpl-3.0.txt
8. http://extjs.com/blog/2008/04/21/ext-js-21-and-ext-gwt-10-released-preview-of-ext-js-30/
No comments:
Post a Comment