Showing posts with label extjs-only. Show all posts
Showing posts with label extjs-only. Show all posts

Monday, November 9, 2009

Ext JS vs. Google Closure

Since Google released its JavaScript library Google Closure there have been quite some people wondering about how it compares to Ext JS.
Because I'm belonging to this group of people, I thought it can't hurt to try to answer this question myself.


Hello World

The entry point for getting started with a library is usually a small "Hello World" application.
I'm not impressed at all with Google Closure's Hello World example.
Not sure if it's just a bad example, or if it shows very well what the library is about.
What you basically see is a JavaScript function which creates a DOM object via a helper method (goog.dom.createDom). This function is called via the slightly inelegant unload attribute of the body tag.
Personally I think Ext JS's Hello World is a better chosen example.
It uses the standard and more elegant Ext.onReady method, which initializes JavaScript code before waiting for images and other resources. Also it uses the Ext.Window widget which gives you a nice idea how Ext JS's widgets are initialized and configured.


Widget's base classes

Ext JS's class hierarchy for UI components such as the Tree widget is:


Ext.util.Observable
Ext.Component
Ext.BoxComponent
Ext.Container
Ext.Panel
(Ext.tree.TreePanel)

Google Closure's class hierarchy for UI components is:


goog.Disposable
goog.events.EventTarget
goog.ui.Component
(goog.ui.tree.BaseNode)

goog.events.EventTarget class seems to be the equivalent of Ext JS's Ext.util.Observable class, goog.Disposable and goog.ui.Component seem to be the equivalent of Ext JS's Ext.Component class.
Equivalents of the Ext.BoxComponent, Ext.Container and Ext.Panel classes, which handle components layouts, can't be found in the Google Closure's hierarchy since Google Closure seems to be missing a layout manager.


Layout manager

One of many reasons that made me a fan of Ext JS is its powerful layout manager that wasn't included in Yahoo UI's library at the time I started using Ext JS.
Google Closure doesn't seem to have a layout manager included at all, which is a big turn off for me. I couldn't live without it anymore.
Google leaves the layout part completely up to you, so you still have to hack your CSS or HTML tables right, to place your widgets where you want it to be.


Event handling

Google Closure's event handling logic is placed into the events.EventTarget class, whereas Ext JS's event handling logic can be found in the Ext.util.Observable class.
It looks like that you can only specify a handler and the event name in Google's solution.
Ext JS's solution seems to be more powerful, since you can specify optional options such as scope, delay, single, buffer and target.
Moreover I like Ext JS method names more, especially the "on" shortcut for the addListener method. Google Closure's names are addEventListener for adding listeners, and dispatchEvent for firing events, which is the equivalent of Ext JS's fireEvent method.


Documentation aka API reference

For me the Ext JS documentation in terms of look and usability is clearly superior to a lot of other open-source software projects, including Google Closure's documentation.
Google Closure's documentation browsing is a bit odd, since the class references are placed on the bottom right, which you constantly have to scroll to. The two panel solution of Ext JS's documentation definitely makes browsing easier.
The actually documentation pages for each classes don't seem to be much different then those of Ext JS or other API references.
I can't tell how helpful Google's documentation is though, since as mentioned above I haven't worked with Google Closure yet.
Ext JS's documentation has been doing a good job for me since I started using Ext JS.


Library's Age & Developer community

I don't know how long Google Closure has been existing within Google, but it just has come to see the light of the outer-Google world.
Ext JS has been out since 2007 and already built up an impressive big developer community which supposedly consists of over 500,000 developers (See statistics and history in this presentation).
You never can underestimate Google in terms of reach and brand power, but looking at Apple's iPhone vs. Google Android, a new library from Google doesn't necessarily mean that all developers will jump on it right away or ever.


Compressor aka Minifier

Besides the Google Closure library, Google released Closure Tools which includes a compiler for compressing and minifying JavaScript files.
There's a thread in the Ext JS forum where the difference in results between the Google Closure Compiler and the YUICompressor used by Ext JS are discussed.
After first tests, the well-known forum user "Condor" points out, that the output of compressing the ext-all-debug.js file with the compiler was 20 KB smaller than the output with the YUICompressor. Not sure what the YUICompressor output's file size is and if he actually tried to point out that is it much less or not. For me it sounds as that there's no big difference. Though he mentions that more optimizations may be reached when compiling the library files together with your application code files.
Follow this thread in the forum to keep an eye on this topic.
Also worth to check out is the Firebug extension Closure Inspector to debug obfuscated JavaScript code.


Ext GWT vs. Ext JS vs. Google Web Toolkit vs. Google Closure

I'm a little confused that Google now advertises Google Closure as the base library for all their AJAX applications like Gmail, since they stated before, that it's Google Web Toolkit, see Google Web Toolkit's description "Java software development framework that makes writing AJAX applications like Google Maps and Gmail easy for developers ...".
I wonder if Google Web Toolkit is to Google Closure what Ext GWT is to Ext JS, where GWT allows writing an application in one language (Java) using the JS library features.
Also the fact that you compile your application and can discover therefore errors before running in the browser might not be THE advantage of GWT anymore, since we have with Google Closure a pure JavaScript compiler now.


License

Ext JS is released under a dual license, which let's you use it in a GPL-based open-source application for free or in a closed commercial application for $329 per developer or less with volume discount.
Google Closure is freely available under the Apache License. jQuery creator John Resig apparently would have preferred the MIT license, since he just tweeted "I wish that Google Closure (the lib) was under the MIT license, can't really borrow code from it for jQuery, otherwise."
There are developers that avoid Ext JS because of the costs and license, others may choose Ext JS especially because of it and its commercial support.
The preference and choice is up to the developers and companies.
If you aren't a license expert yet, check out this comparison between the different type of licenses.


Grid widget

The reason I checked out Ext JS at the first place was that I looked for a Microsoft Excel-like grid functionality for one of my client's application.
I was instantly hooked by the Ext JS grid.
Unfortunately, Google Closure doesn't seem to have such a widget. The only feature for manipulating data in tables that I could find was the goog.ui.TableSorter class. I guess this speaks for itself. People who need powerful grid functionality such as sorting, column reordering, column resizing, data and pagination handling or fixed headers won't find that in Google Closure right now. You certainly can develop it on your own if you want to, or maybe one day there will exist a Grid widget plugin based on Google Closure.


Tree widget

The tree widget is another powerful widget, which is the reason of some people to start using a JavaScript Framework. Unlike with the grid widget, this type of widget is actually included in Google Closure. A demo can be found here. Ext JS's equivalent can be found here.
As with all examples, Ext JS provides for this widget better examples in terms of quantity, complexity and design. See all Ext JS tree examples here.
Going into the details of each tree implementation would go too far for this blog post. I only wanted to point out that there's a tree widget in Google Closure.



Examples a.k.a. demos

One thing I always liked about Ext JS are the extensive and impressive examples that they provide. See for yourself here. You pretty much can build your own Ext JS application by just searching for the functionality you need within the examples and take the code from there.
Google Closure also provides a bunch of examples here (click on the "Demo" tab on the right).
It may be due to the libraries young age or due to it current capabilities, but the examples are by far not as complete and complex as Ext JS's examples.


Usage examples a.k.a. references

Certainly, you can't beat the usage references of Google's Closure library, which is supposedly used in Gmail, Google Docs and Google Maps.
There aren't many well-known public websites that use Ext JS. Number one reason probably is that Ext JS is more used for internal applications. Ext JS definitely has an impressive client list though which you can see here.
The three best and public accessible Ext JS implementations I know of are Marketo, Zipwhip and Kohive. These applications give you a good sense of what's possible with Ext JS.

Disclaimer: Kohive is a client of mine, but that's not why I call it one of the best implementations. Take a look at it yourself. Moreover I didn't create the cool design, interface and architecture.


Default design

Ext JS's default design and template is certainly more shiny than that of Google Closure.
One problem I see with Ext JS's default design frequently is that designers and Mac users are turned off by Ext JS's Microsoft Windows-like design. As you see in the implementation examples above, it certainly can be customized to your preferences. Ext JS's 3.0 introduced some changes such as a separate structural and a visual CSS file that helps you with that.



Unit Testing

The fact that Google Closure has a namespace or package called testing sounds promising and shows that Google is taking unit testing more seriously than Ext JS.
It's certainly debatable what importance unit testing plays in an UI library, but I believe that there are definitely methods in the libraries that could and should be tested by unit tests, so this part goes to Google Closure.
Not sure how well-tested the Google Closure library is for real though.


Conclusion

As consumers usually win in a more competitive market, so should consumers and developers win in a more competitive JavaScript library market, as well.
I think there's no doubt that we can call Google Closure a competitor of Ext JS as Ext JS is a competitor of Google Closure. This doesn't mean that anybody has to worry here.
Ext JS is already an established company with an established product and community and a super smart team. Google also doesn't need to worry since it doesn't live from it.
Ext JS has already shown that it can live very well side-by-side with other similar and free libraries such as the YUI library.
A lot depends on how both companies keep developing, maintaining and supporting their products in the future and how Google Closure is adapted by developers.
But Google already has shown that it isn't a "killer" for everything, as some people may assume, see Google Base, Google Notebook and Google Android.

Anyways, I'm sure Google Closure is a win for the JavaScript community since there most likely are some nice goodies of JavaScript code included.
For now, Ext JS will stay my JavaScript framework of choice though.

Friday, June 27, 2008

Ext.ux.RowWithCellSelectionModel

I recently published another Ext JS extension at http://github.com/steffen/ext.ux.rowwithcellselectionmodel/ I want to let you know about.

Ext.ux.RowWithCellSelectionModel

This Ext JS extension enables the user to activate the editor of an editable cell in an Ext.grid.EditorGridPanel through a double click, to navigate through the cells via the cursor keys and select one or multiple rows through the mouse or through the cursor keys, if no cell is currently selected.
In summary, this selection model is a combination of the two built-in selection models Ext.grid.RowSelectionModel and Ext.grid.CellSelectionModel.
I created it out of the need to be able to add, edit and delete records in an EditorGridPanel. To delete one or multiple records, the user needs to select one or multiple rows which is not possible when using the default Ext.grid.CellSelectionModel.


Installation

Either
git clone git://github.com/steffen/ext.ux.rowwithcellselectionmodel.git
or download the files from http://github.com/steffen/ext.ux.rowwithcellselectionmodel/tarball/master
and put them in a public accessible folder.
Include the RowWithCellSelectionModel.js file in the header of your html page after the Ext JS files.



Usage

new Ext.grid.EditorGridPanel({
ds: your_data_store,
cm: your_column_model,
sm: new Ext.ux.RowWithCellSelectionModel()
});


Alternatives

There exists another extension called Ext.ux.grid.RowAction by Jozef Sakalos, aka Saki, which enables you to add
icons with actions to grid rows. You can't delete multiple records at once, but it's worth a look. See http://rowactions.extjs.eu/ for more infos.

Friday, June 13, 2008

Ext.form.FieldSet and Ext.layout.CardLayout

This post is a note to myself and maybe to some others, since I today searched for the second time for a solution for a misbehavior (bug) in Ext JS when using an Fieldset inside a Panel which belongs to a Panel with a CardLayout.
When I set the Panel with the Fieldsets as the active item via panel_with_card_layout.getLayout().setActiveItem('form_with_fieldsets_panel') everything was shown/rendered besides of the form fields inside the Fieldsets.
After a little debugging and breakpoints fun in Firebug, I decided to search in the Ext JS Forum and luckily found the solution for that problem fast, thanks to the Forum's Google Search.

The solution is that you have to call panel_with_card_layout.doLayout() after setting the active item.

In conclusion, the following two lines should always go together when using FieldSets in a CardLayout:
panel_with_card_layout.getLayout().setActiveItem('form_with_fieldsets_panel');
panel_with_card_layout.doLayout();

Here's the note from an Ext Support Team member regarding this problem, which notes that there is another solution when you are using the Ext.TabPanel (which has the CardLayout as default Layout):

This is exactly why layoutOnTabChange was added to tabpanel. Unfortunately this fix wasn't added to card layout, so you'll have to call cardPanel.doLayout(); yourself after cardPanel.render('showcard');
Quote from http://extjs.com/forum/showthread.php?p=156627


Luckily, this is one of the rare bugs you'll run in when working with Ext JS. Pretty much everything else works as expected. :-) After all, a Friday the 13th could be worse. ;-)

Saturday, May 31, 2008

Ext.apply and Ext.applyIf

In case you missed it, last weekend Jay Garcia released his third screencast in which he explains Ext.apply.

Here is the video, a short 7 and something minutes long, which is a fresh alternative of reading plain blog posts. :-)





Jay actually mentions a firebug bug which I wasn't aware of but which I encountered just this week after learning about it in his screencast. The bug is that the properties of an object you are inspecting (after clicking on the your object which is printed to your console via console.log(object) or console.info(object)) might not be the actual current ones. The work-around is to print directly the property you want to inspect via console.log(object.property).

If you're a little confused about the defaults (third) parameter of Ext.apply, then just think of it as you would write the the following

Ext.apply(receiver, defaults);
Ext.apply(receiver, source);

// is the same as
Ext.apply(receiver, source, defaults);


Also note that there is an Ext.applyIf method (without a third parameter) which only assigns properties/attributes to the receiver object if they aren't existing in the receiver object yet.

And as a small extra here's a real-world example of using Ext.apply which I implemented this week:

onBeforeLoad: function(store, options) {
options.params = options.params || {};
this.cleanParams(options.params);
var params = this.buildQuery(this.getFilterData());
if (store.lastOptions && store.lastOptions.params) {
options.params = Ext.apply(store.lastOptions.params, options.params);
}
Ext.apply(options.params, params);
}

I'm overwriting here the onBeforeLoad method from the excellent Ext.ux.GridFilter extension which is executed every time before the store is loading.
So if you load the store the first time via store.load({params: {start: 0, limit: 50}}), it will resend these parameters when the store is reloaded after you changed your filter values or after you manually executed store.load() after you saved changes to your EditorGridPanel for example. Moreover, the lastOptions params will be overwritten when you switch to the next page via your PagingToolbar, which calls something like store.load({params: {start: 50, limit: 50}}).

Wednesday, May 14, 2008

Ext JS Events, Observable and DomHelper slides

Want to learn more advanced stuff about how to use Ext JS?
Check out these slides from an Ext JS core developer named Aaron Conran. You might know him from the Ext JS forum.



First a very good and quick introduction to Javascript, where you learn more about strictly (not) equals such as === and !== which you encounter often in the Ext JS code and also some nice to know information about the difference between null and undefined.



The next presentation teaches you about Ext JS Event Handling:




Next a presentation about Ext JS Observable Class which includes a nice example of how to catch all fired events of an object and print them to your firebug console.



Ext JS's Dom helpers should also be checked out!






Thanks Aaron for putting together these very helpful slides!


Tuesday, April 8, 2008

Ext.ux.PrinterFriendly, 0.2

I hope nobody minds if I post some update announcements for my Ext JS extension here in my blog. The next Rails-specific post is coming soon...

Here are the changes for version 0.2:

  • Added config.js file for customized settings

  • Added Ext.ux.PrinterFriendly.ENABLE_SHORTCUTS config option

  • Added Ext.ux.PrinterFriendly.ROOT constant

  • Added x-grid3-cell-first and x-grid3-cell-last class to header cells

  • Added config parameter to printPreview to set config options for the print preview window, i.e. the title

  • Added 'printer-window' id for printer window

  • Added init.js file, which loads dynamically all other required files

  • Added closeText and printText config option to PrinterWindow for localization purposes

  • Added hiding of body until the printing layout gets initiated, this way the user doesn't see the page without the custom printer css, which the user might add in the onPrinting function

  • Removed Ext.PRINTER_FRIENDLY_CSS_URL constant

  • Changed all internal extensions to use Ext.ux.PrinterFriendly namespace

  • Changed name of format parameter from format to _format, since it conflicts with the format parameter in Ruby on Rails

  • Changed loading of printer friendly css file, will be loaded now when loading js scripts, which prevents the user from seeing the page before the css is loaded

  • Fixed error in Safari in addStyleSheet method which caused that onPrinting is not executed

  • Fixed print button for IE, IE is printing the content of the iframe now

  • Fixed css bug in IE, empty cells will be filled with now, so that the css border is shown



The files can be found here.

Friday, April 4, 2008

Ext.ux.PrinterFriendly, 0.1 (Initial Release)

I'm happy to announce the first release of my (first) Ext JS extension.
Here are the facts:

Name
Ext.ux.PrinterFriendly

Version
0.1 (Initial Release)

Summary
Easily build printer friendly layouts and grids for your Ext JS pages.

Features

  • Builds a normal html table (Ext.ux.PrinterGridPanel) based on your data store and column model, which saves a lot of cpu power and memory when printing large data sets. Moreover it shows all rows. (Remember, you can't use ext's pagination or scrolling on paper. ;-))

  • Remembers the state of your grid, such as that hidden columns stay hidden in printer friendly view, keep their column order and keep the row sorting. (This is not really a feature of this extension, it just uses the fabulous Ext.state.Manager, but I think it's important to mention, since this was an important requirement for me.)

  • Completely Javascript-driven, no need for extra server-side coding for printer friendly pages

  • Enables easy debugging of your printer-friendly layout (just add ?format=printerfriendly to your page url to see printer friendly view)

  • Enables adding your custom stylesheet for your printer-friendly format



Source
See attachments on this post (in the Ext JS Forum).

Documentation
http://extjs.com/learn/Extension:PrinterFriendly

Example
See attachments on this post (in the Ext JS Forum).

Feedback
Any Feedback via comments on this post in the official Ext JS forum or in this blog is welcome!

I hope you find this extension as useful as I do! :-D

Regards,
Steffen

Thursday, April 3, 2008

Ext JS Screencast (Sketchcast) about Ext.extend and Ext.override

Jay Garcia from TGD innovations LLC started doing a series of screencasts (or so-called sketchcasts) about Ext JS. Here's his second one about Ext.extend and Ext.override. It's certainly an interesting way of doing a screencast using a (digital) whiteboard.



Check out his Blog at http://tdg-i.com which also includes some nice explained Ext JS examples.

Thursday, March 27, 2008

Inspecting your Ext.onReady variables

In the Ext JS examples included in the Ext JS package, you'll find usually this code:

Ext.onReady(function(){
..
var store = new Ext.data.SimpleStore({
..
});

var grid = new Ext.grid.GridPanel({
store: store,
..
});
});


Notice the var keyword in front of the declared variables! The var keyword is defining the variables as local variables. They are only existing in the scope of the anonymous function which is passed to the Ext.onReady method.
But what if we'd like to inspect the values of our local variables in firebug? We could set a breakpoint inside our anonymous function which will allow us to inspect these local variables. But it's a little annoying to do that everytime we're working on an Ext page.

Well, we just could remove the var keyword or use this.store. But that would clutter up our global scope which isn't that nice.

Here is a better solution I came up with today:

Ext.screen = {}

Ext.onReady(function(){
var s = Ext.screen;
..
s.store = new Ext.data.SimpleStore({
..
});

s.grid = new Ext.grid.GridPanel({
store: s.store,
..
});
});


With that solution all our local variables can be referenced by Ext.screen.variable in our firebug console, while keeping our global scope clean by using the Ext.screen namespace.