Wednesday, September 24th, 2008
Category: Ext
, Usability
I am a strong believe in making the keyboard a first class citizen for your applications, including on the Web. Thus, I was interested to read how Ext JS has keyboard handling that ties into the entire system:
Ext.KeyMap
Ext provides several components that support keyboard navigation out of the box such as GridPanel, ComboBox, and TreePanel. To implement custom keyboard handling, developers can use the Ext.KeyMap and Ext.KeyNav classes to attach keyboard bindings to any component or element they wish.
The first set of keys we wanted to handle was all of the Function keys (F1-12). While most browsers reserve some/all of these keys, with some ext-pertise, we are able to override the default function if need be for our application. The application we were working with was completely dynamic and server driven, so we really couldn’t define all of the handlers ahead of time. This led to us dynamically building an array of key handler configuration objects and passing them all through to our new Ext.KeyMap object.
JAVASCRIPT:
-
-
var keys = [];
-
for(var i = 0;i <buttons.length;i++) {
-
var btn = buttons[i];
-
// fkey property contains a string referencing the Ext constants (ie: Ext.EventObject.F1)
-
var fk = eval(button.fkey);
-
btn.handler = this.handleKey.createDelegate(this, [fk]);
-
-
keys.push({
-
key: fk,
-
handler: this.handleKey.createDelegate(this, [fk]),
-
stopEvent: true,
-
scope: this
-
});
-
}
-
Ext.KeyNav
The next set of key handling added was some additions to the grid keyboard navigation. The GridPanel has built in key navigation from the RowSelectionModel that it creates. Check out this grid example and select a row, you can then use the arrow keys to move up/down and even hold shift and press down to select a range of rows. We added a simple way to navigate through a large paged data set by extending GrindPanel. The PagingToolbar provides keyboard handling once you’ve focused within the built-in TextField, but we wanted to allow the users to just hit ‘page down’ or ‘end’ when focus was anywhere within the GridPanel and ensure it functions as expected.
JAVASCRIPT:
-
-
MyGrid = Ext.extend(Ext.grid.GridPanel,{
-
...
-
afterRender : function() {
-
MyGrid.superclass.afterRender.call(this);
-
-
this.nav = new Ext.KeyNav(this.getEl(),{
-
pageDown: this.pagingNav.createDelegate(this,['next']),
-
pageUp: this.pagingNav.createDelegate(this, ['prev']),
-
home: this.pagingNav.createDelegate(this,['first']),
-
end: this.pagingNav.createDelegate(this,['last']),
-
scope: this
-
});
-
},
-
-
pagingNav: function(page) {
-
var pt = this.getBottomToolbar();
-
if (!pt[page].disabled) {
-
pt.onClick(page);
-
}
-
},
-
...
-
});
-
Thursday, September 18th, 2008
Category: Ext
, GWT

Darrell Meyer has announced the release of Ext GWT 1.1 which is said to "shortens the feature set gap between Ext JS."
New Features
The Grid component wraps the Ext JS grid, and it includes support for grid plugins which fit into component lifecycles. You can also use a subclass, EditableGrid which.... allows you to edit content on the fly.
Auto complete has been added to the combo boxes a la Google Suggest.
Portal is a custom layout container that uses a multi-column layout on contains Portlets. Each Porlet can be drag and dropped to change order or move to another column. Each Portlet can contain any content and supports icons to expand / collapse, close, etc.
The desktop mimics the behavior of the operating system look at feel. It is now possible to create multi-window applications with support for a task bar and start menu. Windows support normal, maximize, and minimize states. The start menu is a custom menu that allows new menu items. In addition, there is support for a “task” area for adding additional items.
Java Bean Support with BeanModel
The Ext GWT Store and Binder API work with ModelData instances. The primary goal of ModelData is to provide a type of “introspection” as GWT does not allow runtime inspection of Java objects. You can query ModelData for a list of properties it contains, and these properties can be retrieved and set using the parameter name with the get and set methods.
Although this approach works, it forces you to either implement the ModelData interface in your Java Beans or extend the Ext GWT base classes that implement the ModelData interface. What is missing is a way to use your Java Beans as is, without having to extend the Ext GWT base classes or implement an “invasive” interface.
There are also new examples:
- Forum search is an example of a combo box, using a custom XTemplate, and remote data. The data can be paged with built-in support for a paging toolbar.
- Image Chooser shows loading a ListView in a Window. Each item has a linked details view, and the ListView supports custom sorting and filtering.
- This example shows a Dialog using an AnchorLayout to “anchor” the form fields to the dialog dimensions. When resized, the fields will adjust their size to match the dimensions of the dialog.
Wednesday, August 6th, 2008
Category: Ext
Ext 2.2 has been released, and it has features to complement the usual maintenance bug fixes and performance updates (Ext now works better in Firefox 3).
New features include:
CheckboxGroup / RadioGroup
Technically, while the individual Checkbox and Radio controls are not new, they may as well be, considering the overhaul they have had in this release. Gone are the ugly standard browser input controls, now replaced by attractive, visually-consistent Ext-ified versions (a long-overdue improvement).
In addition to that, we’ve added group controls for both that support complex layouts with just a config option or two. Previously in order to accomplish similar grouping layouts you would have had to create a container with a ColumnLayout and manually place your controls across multiple column configs.
History
Another component that has been missing in Ext is a browser history utility to enable history stack navigation within your single-page Ext application. The new Ext.History singleton makes it extremely easy to do exactly that, and it uses an event-based API to notify you when the browser history as changed.
MultiSelect / ItemSelector
These two components were contributed to Ext by community member TJ Stuart (thanks TJ). The MultiSelect is a traditional list control that allows for selecting multiple list items, and the ItemSelector combines two MultiSelects into a more sophisticated control that includes drag-and-drop list selection and bulk selection and deselection among other features.
FileUploadField
This is an official extension provided as a sample for implementing a useful form component. Not everyone needs a form upload component, but if you do, you can’t live without it. This control is fully styled and has an API consistent with other Ext form controls. It also supports both Text+Button (read-only text) and Button-only modes, and can participate fully in form layouts.
XmlTreeLoader
This official extension provides a great demonstration of extending an existing Ext component to provide functionality that you need in your own application. Again, loading an XML document into a tree is not needed by everyone, but if you do need something similar, this should be a great demo.
GMapPanel
This extension was originally written up as a demo for one of our previous blog posts. However, it proved to be such a hit with the community that we transformed it into an official extension. This is another useful example of extending a standard Ext component, in this case to interface with an external API.
Monday, August 4th, 2008
Category: Ext
, Python
Are you an ExtJS and Django user? If so, you will want to check out this article by Matt of Tangible Worldwide on Using ExtJS's Grid Filtering with Django.
He goes into detail on how to tweak the grid filtering system that is aimed at PHP, and getting it to work in a way that allows you to write this Django code:
PYTHON:
-
-
# take a ContentType model name (say, from the URL)
-
# and create a QuerySet
-
ctype = ContentType.objects.get(model=ctype_model)
-
model_class = ctype.model_class()
-
obj_qs = model_class.objects.filter()
-
-
# 'q' is the set of POSTed filtering parameters
-
filter_params = request.POST.get('q', '[]')
-
-
# decode the filtering parameters w/ simplejson
-
filter_params = simplejson.loads(filter_params)
-
-
# apply the filtering params
-
filtered_qs = get_queryset_from_ext_filters(obj_qs, filter_params)
-
ExtJS 2.1 saw inclusion of the popular (at least in my world) user extension for AJAX filtering of data by grid columns. As useful as this is (provided you can abide by the GPL or paid licensing options), the filter parameters serialized as a PHP array, which is not particularly useful for other languages. With a quick modification to the grid filtering serialization method and a helper function for Django, we can rewire the system to send a JSON string that Django can use to directly apply filtering to a QuerySet. I've found that most clients love having this sort of command and flexibility over their data -- especially the kind that don't necessarily realize that this visualization and control exists. I like that. Additionally, the amount of work and code required is minimal, and the code both reusable and straight-forward. I like that, too.
There are 4 steps to this process:
- Modify the serialization method in GridFilters.js
- Set up the helper function that will process the QuerySet with the grid filter parameters
- Slightly customize your models (see below)
- Add (simple) helper code to your Ajax view
Wednesday, July 16th, 2008
Category: Ext
Many developers really like the live scrolling functionality popularized by DZone. As you scroll down the page, a XHR call is made which pulls back data and instantly refreshes and allows you to continue to scroll down almost endlessly. Aaron Conran has built a widget for the Ext JS library which provides this functionality in an easy-to-use user extension:
A LiveDataPanel can enhance your site by deferring the load of additional content until the user is ready to see it. Markup will never be generated unless it’s needed and therefore the browsers DOM will have a smaller footprint. It’s important to remember to use this component where approriate, because it will load every record into memory and render that record’s markup to the browser. By building upon Ext’s foundation classes, we were able to create a useful component without having to do a lot of the lower level work.

The extension is easy to call and very configurable. The demo code looks like this:
JAVASCRIPT:
-
-
// Creating the panel is easy
-
var p = new Ext.ux.LiveDataPanel({
-
frame: true,
-
title: 'Latest Blog Entries',
-
height: 400,
-
width: 590,
-
itemSelector: '.entry',
-
tpl: Ext.XTemplate.from('tplBlog'),
-
store: myStore
-
});
-
p.render('entry-list');
-
Tuesday, July 8th, 2008
Category: Ext
, GWT
Darrell Meyer has announced Ext GWT 1.0. This is the first fully stable release of the product and it includes a lot of goodies including:
- Documentation: new screencasts of the various steps
- GWT 1.5 support: "Ext GWT is a 100% native GWT application written in Java. Ext GWT does not wrap any 3rd party JavaScript and does not use any external JavaScript files. Ext GWT fully leverages the GWT API including the widget lifecylce, events, listeners, messaging, and RPC."
- "Performance was a high priority item for the Ext GWT 1.0 release. Many changes were made since the first beta releases. Initial rendering times are quicker and the new layout code reacts quicker to window resizing. Improvements can easily be seen in the Explorer demo."
- Advanced Form Layouts
- Improved Data Loading, Store, Binder, and Field API
Looks like a very solid release indeed. Congrats to the team.
Wednesday, June 11th, 2008
Category: Aptana
, Ext
When Aptana released Jaxer, it really excited the community because you could now leverage your client-side skills on the server end of things. Rich Waters of Ext JS talks about how to leverage Ext JS on the server via Jaxer. The code created by Rich creates a Ext JaxerStore which allows you to run queries and directly put them into a Ext Store. This has the benefit of leveraging the same Ext language syntax you've become accustomed to for server-side processing by allowing Jaxer to wrap client and server-side communications up allowing either synchronous or asynchronous calls between the client and server.
I asked Rich why would developers do this versus doing a simple Ajax call to a template sitting on a server:
The template bit lets you generate the html before the page is served up so that no extra client side calls are necessary. I think the Ext template system is really slick and easier than even a lot of other existing server side templating systems. More or less it was also just an example to get people thinking about what could be done now that Ext can be run server-side.
The code snippet allows you to make the calls to Jaxer very easily:
JAVASCRIPT:
-
-
Ext.onReady(function() {
-
var store = new Ext.data.JaxerStore({
-
table : 'demo',
-
fields : [
-
{name : 'name'},
-
{name : 'phone'},
-
{name : 'email'}
-
],
-
readerConfig : {
-
sortInfo : {
-
sort : 'name',
-
dir : 'asc'
-
}
-
}
-
});
-
-
// create the Grid
-
var grid = new Ext.grid.GridPanel({
-
store : store,
-
columns : [
-
{header : "Name", sortable : true, dataIndex : 'name'},
-
{header : "Phone #", sortable : true, dataIndex : 'phone'},
-
{header : "Email", sortable : true, dataIndex : 'email'}
-
],
-
viewConfig : {
-
forceFit : true
-
},
-
stripeRows : true,
-
height : 350,
-
width : 680,
-
title : 'Jaxer Demo Grid',
-
renderTo : Ext.getBody()
-
});
-
});
-
which would then populate a grid control and render it accordingly.
The source code to this new functionality can be downloaded here.
Thursday, June 5th, 2008
Category: Ext
, Opera

Shea Frederick has posted on building Wii-friendly web pages using the ExtJS library.
Shea focuses on the various issues that come up when building something for the Wii resolution, screen size, input types, and more.
For example, check out the layout:
JAVASCRIPT:
-
-
Ext.ns('Ext.ux.layout');
-
Ext.ux.layout.wii = Ext.extend(Ext.layout.FitLayout, {
-
setItemSize : function(item, size){
-
var viewSize = Ext.getBody().getViewSize();
-
this.container.addClass('ux-layout-wii');
-
item.addClass('ux-layout-wii-item');
-
size.height = (viewSize.height-60);
-
size.width = (viewSize.width-60);
-
item.setSize(size);
-
}
-
});
-
Ext.Container.LAYOUTS['wii'] = Ext.ux.layout.wii;
-
And then you can detect the Wii to set this layout:
JAVASCRIPT:
-
-
Ext.isWii = navigator.userAgent.toLowerCase().indexOf("wii")> -1;
-
var layout = 'fit';
-
var title = 'Normal';
-
if (Ext.isWii) {
-
layout = 'wii';
-
title = 'Wii';
-
}
-
Monday, April 28th, 2008
Category: Ext
, JavaScript
Jack Slocum and his team are listening, and appear to be working with the community to clear things up:
With our recent change to the GPL v3 some concerns have been brought up by the Ext Community. We are hoping to address some of those concerns via community discussion of two new FLOSS exceptions.
The first step for us is the Open Source License Exception for Extensions. It is currently in draft status and we are seeking input from the community before we have it finalized.
The intention of this exception is to allow for more liberal licensing of extensions, language packs, themes and open source developer toolkits and frameworks for Ext libraries under a variety of open source licenses. (Note: this exception is not for applications and does not grant any exception for the library itself. A FLOSS exception on the libraries for open source applications will be addressed in the exception discussed in “Next Up†below).
He is looking for input and feedback. You can see the latest draft, and if you have thoughts join the discussion.
This exception is the first step, with more to come:
After the Extension Exception is complete, the next step will be drafting a FLOSS exception similar to the one by MySQL AB for both Ext JS and Ext GWT.
This exception will for open source applications that use Ext JS. It will have a few distinct additional grants the Extension Exception doesn’t have (e.g. “bundling†will be ok) but won’t be applicable to extensions or toolkits, as that’s what the Extension Exception is for.
Quick work, and the fact that he is joining and leading the discussion is huge.
Sunday, April 27th, 2008
Category: Editorial
, Ext
, JavaScript
OpenEXT is here. It is a fork of Ext JS 2.0.2, which was under an LGPL license (kinda.... with some invalid, non-open source licensing).
The crux of the fork is:
Ext are claiming that a fork of the existing 2.0 version is not legal, due to the way they applied the LGPL. This is likely to be incorrect, and if correct then their use of the name LGPL was grossly misleading.
At this point, developers are getting increasingly passionate, and Jack needs to make a big effort and come clean to his community to save the reputation of the project. If not, it will probably always be in a cloud of darkness as people are both confused and wonder about motives. This is not about personal attacks, but due to not having clarity on the core issues.
You will notice that most of the detractors are members of the Ext community. They aren't out to spoil some of the work that they themselves put into the project. You see the opposite in fact when you read posts such as this one from Jason Sankey:
The saddest part about this is that the Ext team really have built a fantastic library, and a vibrant community around it. The library had all the hallmarks of an open source success story. Now, however, Ext have committed the cardinal sin of an open source project: they have undermined the trust of their own community.
There are others too.
I actually believe that Jack has been given really poor legal advice, which hasn't helped his thinking on the issue. It has thus spiraled out of control, and needs a big humble gesture to steer things in the other direction.
If I were Jack, I would call a meeting (phone, irc, whatever) and get all of the parties together. Hash it out with an open mind, and end up with the right answer. Again, this is for the sake of the Ext JS community, customers, as well as the entire open source JavaScript community. If this doesn't happen, you are keeping the cloud around the project, and handing cont