Building a Rating Widget with Ext Core 3.0 Final and Google CDN
Wednesday, June 10th, 2009We are very proud to announce the final release of Ext Core under the MIT license. Your feedback was invaluable. Thank you for all the bugs reported and test cases created. For those of you who are new to Ext Core, we suggest you read the previous blog post about the all the features and examples that we released as part of the beta. You can find a list of changes and fixes we made for the final here.
For this post we will leverage the power of Ext by creating and dissecting a useful star rating example. We hope to share some of the general best practices behind creating unobtrusive, reusable code with Ext Core to liven up your pages.
Making a Splash
Including Ext Core on your site is easier than ever. We are honored to share with the community that Ext Core is now available via the Google AJAX Library API. Many thanks to Ben Lisbakken at Google for working with us to make this a reality.//any of these will work ;) <script type="text/javascript" src=".... http://ajax.googleapis.com/ajax/libs/ext-core/3.0/ext-core.js http://ajax.googleapis.com/ajax/libs/ext-core/3/ext-core.js http://ajax.googleapis.com/ajax/libs/ext-core/3.0/ext-core-debug.js http://ajax.googleapis.com/ajax/libs/ext-core/3/ext-core-debug.js
google.load('ext-core', '3'); google.load('ext-core', '3', {uncompressed : true});
Getting Started
Ext Core is a perfect fit for adding behavior to existing HTML. When designing a widget, having a markup structure that provides graceful degradation is an added plus. For this example, we will be using radio buttons. We can "group" the elements to specify which radio buttons are part of the control. It could look something like the following:<div id="rating1"> <input type="radio" name="rating1" value="1" title="Very poor"> <input type="radio" name="rating1" value="2" title="Not that bad"> <input type="radio" name="rating1" value="3" title="Average"> <input type="radio" name="rating1" value="4" title="Good"> <input type="radio" name="rating1" value="5" title="Perfect"> </div>
The API
One of the most important aspects of building reusable code is providing your developers a powerful API. Our aim here is to allow developers to progressively enhance and convert the markup into a star rating with a simple API. In this case we will need the element that wraps around the radio controls, and some optional configuration to customize the behavior of the widget. Following the Ext tradition we will provide these configuration options in the form of an object literal. A possible API for our widget could look like this://Keep it simple new Ext.ux.Rating('rating1', { showTitles: true });
Ext.util.Observable
So now that we know how we want to use our component, lets go ahead and actually look at some details on how to write it! In our previous post we mentioned that Ext Core allows you to write neatly structured object-oriented code. Whenever you want to create a piece of functionality, you should try to bundle it into a separate class. In most cases you will need to be able to listen for events on instances of your class. Ext provides a power class, the Ext.util.Observable class, to springboard your development. This is the same class that almost all classes in Ext JS extend from! Our basic shell for our rating plugin could look something like this:Ext.ns('Ext.ux'); Ext.ux.Rating = Ext.extend(Ext.util.Observable, { // Configuration default options showTitles: true, // Our class constructor constructor : function(element, config) { Ext.apply(this, config); Ext.ux.Rating.superclass.constructor.call(this); this.addEvents( 'change'); this.el = Ext.get(element); this.init() } });
Reaching the stars
It is time to think about the things we need to get our widget working. First we want to replace the radio buttons with our stars, we will need to store the values and titles for each star, we want to create a hidden input to put the current value in and finally we need to set up event listeners to listen for mouse hovers and clicks.init : function() { var me = this; // Some arrays we are going to store data in this.values = []; this.titles = []; this.stars = []; // We create a container to put all our stars into this.container = this.el.createChild({ cls: 'ux-rating-container ux-rating-clearfix' }); // We use DomQuery to select the radio buttons // Then we can loop over the CompositeElement using each this.radioBoxes = this.el.select('input[type=radio]'); this.radioBoxes.each(this.initStar, this); // We use DomHelper to create our hidden input this.input = this.el.createChild({ tag: 'input', type: 'hidden', name: this.name, value: this.values[this.defaultSelected] }); // Lets remove all the radio buttons from the DOM this.radioBoxes.remove(); if(this.disabled) { this.disable(); } else { // Enable will set up our event listeners this.enable(); } }
Creating Stars - using DomHelper and accessing the DOM from Ext Element
initStar : function(item, all, i) { // We use the name and disabled attributes of the first radio button if(i == 0) { this.name = item.dom.name; this.disabled = item.dom.disabled; } // Saving the value and title for this star this.values[i] = item.dom.value; this.titles[i] = item.dom.title; // Now actually create the star! var star = this.container.createChild({ cls: 'ux-rating-star' }); // Save the reference to this star so we can easily access it later this.stars.push(star.dom); },
Enable and Select Stars - listening for events, using the target of an event and firing custom events
enable : function() { // ... some code missing here ... // We will be using the technique of event delegation by listening // for bubbled up events on the container this.container.on({ click: this.onStarClick, mouseover: this.onStarOver, mouseout: this.onStarOut, scope: this, delegate: 'div.ux-rating-star' }); }, onStarClick : function(ev, t) { if(!this.disabled) { this.select(this.stars.indexOf(t)); } }, select : function(index) { // ... some code missing here ... else if(index !== this.selected) { // Update some properties this.selected = index; this.value = this.values[index]; this.title = this.titles[index]; // Set the value of our hidden input so the rating can be submitted this.input.dom.value = this.value; // the fillTo() method will fill the stars up until the selected one this.fillTo(index, false); // Lets also not forget to fire our custom event! this.fireEvent('change', this, this.values[index], this.stars[index]); }
Filler Up - dom manipulation (adding classes)
fillTo : function(index) { var cls = 'ux-rating-star-on'; // We add a css class to each star up until the selected one Ext.each(this.stars.slice(0, index+1), function() { Ext.fly(this).addClass(cls); }); // And then remove the same class from all the stars after this one Ext.each(this.stars.slice(index), function() { Ext.fly(this).removeClass(cls); }); }
We won't discuss all the details since most of it is pretty straightforward, but the final product should give you a general idea of how to use the basic functionality available in Ext Core to tie together all the missing pieces.
Wrapping it up
In this example we used the following cross-browser compatible functionality available in Ext core:- Classical Inheritance Class System
- Observable Class
- DomQuery
- DOM manipulation and traversal
- Event handling
- Markup generation
Ext Core makes it fun to write code, and helps you create clean, well-structured classes using a set of cross-browser abstractions on the existing browser API's. For those of you who want to use it or are just interested in seeing the completed work, we have included a version of the widget in the Ext Core Final build. You can see the working widget embedded in the post below:
The example page illustrating this widget can be found here.

We are pleased to announce that the latest release candidate of 


One of the design decisions we made early on was that we wanted a rich desktop-like experience inside the web browser. We investigated the other major players in the field, but ultimately decided that ExtJS was the best. One of the things that made ExtJS especially appealing was the “Window” object that can contain “Panel” objects. Our core requirement was a windowed interface and having Ext.Window cross-browser out of the box was a major win.
We had the situation where we needed to create an Ext.DataView that displays Widgets. Currently you can only use an Ext.DataView with an Ext.Template. A solution that allows for controls to be created and inserted according to an Ext.data.Store would be valuable.
As developers, we spend countless hours researching best practices to build engaging software. Often we find ourselves implementing the same repetitive functionality to wire our frontend to our backend. We’ve become accustomed to partaking in complicated design patterns to help separate logic from presentation - forcing the browser to play the role of a dumb terminal. While the RIA movement has unshackled the web browser from that awful fate, accessing our server side logic remains mostly unchanged. Ext.Direct aims to solve this issue for developers creating Ext JS applications by providing a single communication point with the server-side.

















This past week members of the Ext team were sitting in my living room watching TV when we saw CNN report Toys for Tots is in desperate need of toys this year. Toys for Tots is a non-profit organization that works with the United States Marine Corps to gather and distribute toys to needy and underprivileged children during the holidays. Toys for Tots 

Ext.air.VideoPanel enables you to embed flash based video while maintaining the same functionality as an Ext.Panel. VideoPanel’s can also take part in Ext layout management. This means that you can nest your Video’s in a border layout, add toolbars, buttons, just as you have become accustomed to. You just need to provide the recorded FLV to playback or provide a camera connected to the PC. You can even watch the video fullscreen in high definittion!












As Enterprise applications begin moving to the web instead of the desktop many developers may forget about providing key bindings for their applications. Most web applications use the keyboard only for text entry and do not associate particular key combinations with user actions. By providing this type of key handling, particularly for applications which require a lot of data entry, we can improve the end-user experience. 














Early last week 

Theres no doubt that Google has some interesting and very useful JavaScript API’s - most of which I end up using over and over again. So why not package them up into an Ext component? Well thats exactly what I decided to do, adding a simple component centered around the Google Maps API.
It’s just as easy to create a Google map window that maps addresses and places markers at their locations (which could just as easily be nested in a layout instead).
Shortly after 

everything works the same as it would in a normal PC based web browser. With a complete JavaScript engine, its just as good as the full fledged Opera browser. Im not expecting any enterprise quality applications to be developed for use on the Wii, but it would be nice to use some of the ExtJS features to catch up on our blog, read the forum, or just drag windows around using the Wiimote (much more fun than it sounds).







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 


















In collaboration with Adobe, one of the key additions in

I regularly hit






The
Existing 1.x users should be happy to see the 








