Contents


Build Ext JS extensions and plug-ins

Comments

Ext JS is a comprehensive JavaScript framework that includes a vast collection of features, including cross-browser-compatible JavaScript helper utilities for DOM traversal and manipulation and data object stores. It also handles Ajax and direct web remoting, has an impressive collection of UI controls and widgets, charts and graphs, a powerful data grid control, and much, much more.

When developing applications using Ext JS, or indeed any JavaScript library or framework, you can be sure that you are going to need functionality that isn't included out-of-the-box, or is present but doesn't work quite the way you want it to. Thankfully, Ext JS includes a powerful class and component ecosystem that makes it easy to extend existing features or build new components entirely. In this article, we will explore this extensibility, specifically looking at the concepts of extensions and plug-ins. You will learn what each of these concepts means and what is different between the two. You will then see how to build your own extensions and plug-ins and how to source existing plug-ins built by other developers for use in your own applications, saving you from reinventing the wheel.

What is an extension?

An extension for Ext JS is a derived class or a subclass, which is designed to allow the inclusion of additional features to existing Ext JS classes. Extensions can be as basic as "preconfigured classes," which basically supply a set of default values to an existing class configuration, useful if you frequently need to supply these parameters when using a particular component. For example, your application may use a series of pop-up windows using the Ext.Window class, but these windows will always have the same width and height values. Rather than specifying this width and height every time you use Ext.Window, you could create an extension of Ext.Window with the preconfigured sizing properties. Not only does this save you from repeating the same code over and over, but it also makes your application much easier to maintain. And if you need to change the default size of your application's pop-up windows, you will only need to change it in one place rather than in several different locations in your code.

Preconfigured classes are the most basic type of extensions. In addition to supplying values for the existing properties in a class, subclasses can also add new properties and methods that are not included in the parent class (that is, the class that is being subclassed or derived from).

If you are familiar with the basics of object-oriented programming, you will know that when an object is instantiated, the class constructor function is automatically called. This function usually performs some initialization routines such as setting default values of class properties. By default, when you create a subclass, its constructor merely calls the constructor of its parent class. However, by creating a constructor for the subclass, you can override the constructor of the parent class, performing functionality specific to the subclass (setting default value properties that were added by the subclass, for example). Ext JS makes it very straightforward to do this and ensures that you can call the constructor of the parent or super class easily from the subclass constructor function, so that you don't have to add in the code from the parent class constructor into the subclass constructor.

Overriding methods in a parent class is not limited to the constructor. You can also override regular functions in a subclass and call the overridden parent function from within the subclass.

What is a plug-in?

A plug-in is a class that is used to provide additional functionality to an existing component. Rather than directly instantiating an object of a plug-in class, plug-ins are attached to a component using the "plugins" configuration option for that component. One of the key advantages of using plug-ins is that the plug-in can be used not only by the component it is attached to, but also by all subclasses derived from that component.

A nice feature of using plug-ins in Ext JS is that multiple plug-ins can be attached to a single component, providing additional functionality as required. This means that additional functionality can be broken up and only used when needed, improving the performance of the application. Of course, plug-ins should be written in such a way that they do not conflict with other plug-ins, otherwise they will not be able to be used concurrently in a component.

Differences between extensions and plug-ins

At first it can be difficult to appreciate the difference between an extension and a plug-in in Ext JS, particularly given their similarities in terms of what they do. At the end of the day, both provide extended functionality to Ext JS classes. The primary difference lies in how they are written.

Ext JS extensions are written as subclasses of an existing class. They can provide additional properties or functions, or even modify the behavior of the parent class by overriding the constructor and other functions. To use an extension, you directly create an object of the extension subclass, which can then use, add, or override features to the parent class it is derived from. Extensions are best used when you need to change core functionality of an existing Ext JS component or feature, or when you want to build a brand new component altogether.

Ext JS plug-ins are written as classes that always have an init function. Unlike extensions, you will not create an object of a plug-in class directly, but rather you will register your plug-in with the component it attaches to. The options and functions defined in the plug-in will then become available to the component itself. Plug-ins are best used when you need to add features to a component. Because extensions are so tightly coupled with the classes they are derived from, plug-ins also present a viable alternative when you want your add-on to be easily detachable and interoperable with multiple components and derived components. Because plug-ins must be attached to an existing component, they are not usually suitable for building new components from scratch.

Building an Ext JS extension

In this section, you will learn how to build Ext JS extensions. You will first learn how to create preconfigured classes, which will make it easy to reuse code and keep your application in a maintainable state by creating subclasses that preset configuration options to default values. You will then learn how to create a more complex extension which changes the functionality of an existing Ext JS class and adds some new features.

Creating preconfigured classes

As previously stated, preconfigured classes are the most basic form of Ext JS extension. They simply define a set of preset configuration option values that allows you to use a component without having to pass default values each and every time. An example of this would be an Ext.Window component, where in your application many of the properties of the window are always the same, for example width, height, and title. For an example of this, look at this particular scenario, without the use of a preconfigured class (see Listing 1).

Listing 1. unextended.html
<html>
    <head>
        <title>Popup Window - Unextended Version</title>
        <link rel="stylesheet" type="text/css" href="ext/resources/
css/ext-all.css" />
        <script type="text/javascript" src="ext/adapter/ext/
ext-base.js"></script>
        <script type="text/javascript" src="ext/ext-all.js"></script>
        <script type="text/javascript">
        Ext.onReady(function() {
            var win1 = new Ext.Window({
                width: 500,
                height: 300,
                modal: true,
                closeAction: 'hide',
                resizable: false,
                maximizable: true,
                collapsible: true,
                draggable: false,
                title: 'Window 1',
                html: '<h2>Window 1</h2>'
            });

            var win2 = new Ext.Window({
                width: 500,
                height: 300,
                modal: true,
                closeAction: 'hide',
                resizable: false,
                maximizable: true,
                collapsible: true,
                draggable: false,
                title: 'Window 2',
                html: '<h2>Window 2</h2>'
            });

            var win3 = new Ext.Window({
                width: 500,
                height: 300,
                modal: true,
                closeAction: 'hide',
                resizable: false,
                maximizable: true,
                collapsible: true,
                draggable: false,
                title: 'Window 3',
                html: '<h2>Window 3</h2>'
            });

            var button1 = Ext.get('button1');
            var button2 = Ext.get('button2');
            var button3 = Ext.get('button3');

            button1.on('click', function() {
                win1.show(this);
            });

            button2.on('click', function() {
                win2.show(this);
            });

            button3.on('click', function() {
                win3.show(this);
            });
        });
        </script>
    </head>

    <body>
        <button id="button1">Show Window 1</button>
        <br />
        <button id="button2">Show Window 2</button>
        <br />
        <button id="button3">Show Window 3</button>
    </body>
</html>

In Listing 1 above, there are three buttons, each of which will show a separate Ext.Window component. Each of these windows has the same value for the following properties:

  • width
  • height
  • modal
  • closeAction
  • resizable
  • maximizable
  • collapsible
  • draggable

As you can see clearly in Listing 1, each of these eight properties is set in the configuration for each of the three Ext.Window objects. Not only does this result in extra lines of code, but it also means that if you decide to change the default property values of the Ext.Window, you need to make this change in three different places, which is less than ideal. This is where preconfigured classes come into play as shown in Listing 2.

Listing 2. extended.html
<html>
    <head>
        <title>Popup Window - Extended Version</title>
        <link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css" />
        <script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script>
        <script type="text/javascript" src="ext/ext-all.js"></script>
        <script type="text/javascript">
        MyWindow = Ext.extend(Ext.Window, {
            width: 500,
            height: 300,
            modal: true,
            closeAction: 'hide',
            resizable: false,
            maximizable: true,
            collapsible: true,
            draggable: false
        });

        Ext.onReady(function() {
            var win1 = new MyWindow({
                title: 'Window 1',
                html: '<h2>Window 1</h2>'
            });

            var win2 = new MyWindow({
                title: 'Window 2',
                html: '<h2>Window 2</h2>'
            });

            var win3 = new MyWindow({
                title: 'Window 3',
                html: '<h2>Window 3</h2>'
            });

            var button1 = Ext.get('button1');
            var button2 = Ext.get('button2');
            var button3 = Ext.get('button3');

            button1.on('click', function() {
                win1.show(this);
            });

            button2.on('click', function() {
                win2.show(this);
            });

            button3.on('click', function() {
                win3.show(this);
            });
        });
        </script>
    </head>

    <body>
        <button id="button1">Show Window 1</button>
        <br />
        <button id="button2">Show Window 2</button>
        <br />
        <button id="button3">Show Window 3</button>
    </body>
</html>

Much of the code in this listing is the same as in Listing 1. However, you will notice above the Ext.onReady call that I have created a new subclass, MyWindow. This is created using the Ext.extend function, specifying the default configuration values for the eight properties that are common across all three of my Ext.Window objects. As you can see, you can then create objects of this new subclass, specifying the two properties (title and html) that vary between each of the windows. The resulting application looks the same (see Figure 1) for both code listings, but I'm sure you'll agree that Listing 2 is a much more maintainable method.

Figure 1. Preconfigured classes example in action
Screen shot of MessageBox in Mozilla Firefox, showing Window 1
Screen shot of MessageBox in Mozilla Firefox, showing Window 1

Extending an Ext JS component

Predefining the configuration options for a component is all well and good, but what about extending the functionality of a component to provide additional features? In this section, you will learn how to create a subclass of Ext.Window that behaves like a web browser window.

You can use the <iframe> HTML element to display web pages inside another web page, so we'll take advantage of that to create a new ExtBrowserWindow class that will display this web page inside an Ext.Window. The goal is to simplify the process. To create a pop-up Ext browser window, all you need to do is supply a unique ID and a URL to display. In fact, in this example, you will even supply a default URL to navigate to, should none be supplied.

Listing 3 shows the full source code for the example.

Listing 3. extbrowser.html
<html>
    <head>
        <title>Ext Browser Window Extension</title>
        <link rel="stylesheet" type="text/css" 
href="ext/resources/css/ext-all.css" />
        <script type="text/javascript" src="ext/adapter/ext
/ext-base.js"></script>
        <script type="text/javascript" src="ext/ext-all.js"></script>
        <script type="text/javascript">
        ExtBrowserWindow = Ext.extend(Ext.Window, {
            closeAction: 'hide',
            width: 500,
            height: 300,
            title: 'Sencha',
            url: 'http://www.sencha.com',
            onRender: function() {
                this.bodyCfg = {
                    tag: 'iframe',
                    src: this.url,
                    cls: this.bodyCls,
                    style: { border: '0px none' }
                };
                ExtBrowserWindow.superclass.onRender.apply(this, arguments);
            }
        });

        Ext.onReady(function() {
            var win1, win2;

            var button1 = Ext.get('button1');
            var button2 = Ext.get('button2');

            button1.on('click', function() {
                if(!win1) {
                    win1 = new ExtBrowserWindow({
                        id: '1',
                        title: 'Google',
                        url: 'http://www.google.com'
                    });
                }
                win1.show(this);
            });

            button2.on('click', function() {
                if(!win2) {
                    win2 = new ExtBrowserWindow({
                        id: '2',
                    });
                }
                win2.show(this);
            });
        });
        </script>
    </head>

    <body>
        <button id="button1">Show Google</button>
        <br />
        <button id="button2">Show Sencha</button>
    </body>
</html>

Similar to the preconfigured class example, you are creating a subclass of the Ext.Window class and supplying some default configuration options such as width, height, and title. In this instance, however, you are also setting a new option that is specific to this new class, url. This is the property that will determine the web page URL to display in the window. In the example, this is set to default to the Sencha home page (see Related topics).

The ExtBrowserWindow subclass also overrides the onRender event function and applies a configuration to the body of the Ext.Window, telling it that it should use the iframe tag, with the src attribute set to the url configuration option and the style set to have no border. Finally, the corresponding onRender event handler in the superclass will be called.

The actual instantiation of the ExtBrowserWindow object is much the same as in the previous examples, except this time we're passing our user-defined configuration option url in the first button call (which will open Google). In the second example, we only use the default values specified in the class, which will show the Sencha home page. Figure 2 shows the ExtBrowserWindow extension in action.

Figure 2. ExtBrowserWindow extension in action
Screen shot of the Ext Browser Window extension in Mozilla                     Firefox, showing the Sencha home page in a new window
Screen shot of the Ext Browser Window extension in Mozilla Firefox, showing the Sencha home page in a new window

This is a very basic example of an Ext JS extension, but it could easily be extended further to include some more features. For example, you could add typical web browser features like back and forward buttons, an address bar, or even bookmarks.

Building an Ext JS plug-in

In this section, you will learn how to build an Ext JS plug-in. For the sake of simplicity, I will show you how to create the same functionality as in the previous section, but this time it will be created as a plug-in rather than an extension. It it standard practice to create plug-ins in an external JavaScript source file, so start off by creating a new file named BrowserPlugin.js, the contents of which are shown in Listing 4.

Listing 4. BrowserPlugin.js
BrowserPlugin = Ext.extend(Object, {    
    init: function(component) {        
        component.width = 500;
        component.height = 300;
        component.bodyCfg = {
            tag: 'iframe',
            src: component.url,
            cls: component.bodyCls,
            style: { border: '0px none' }
        };
    }
});
Ext.preg('browserPlugin', BrowserPlugin);

The plug-in is very simple: It contains the basic requirements of an Ext JS plug-in. The init function sets the width and height of the component accordingly and tells the component that it should render as an <iframe> element, with the src attribute coming from the URL configuration option, as it was in the extension example. Finally, the BrowserPlugin class is registered as a plug-in to allow it to be loaded lazily. This basically means that you don't need to instantiate the object manually; Ext JS will take care of it for you.

Next, create plugin.html, the file which will use the plug-in you just created. Its contents are listed in Listing 5.

Listing 5. plugin.html
<html>
    <head>
        <title>Ext Browser Window Extension</title>
        <link rel="stylesheet" type="text/css" href="ext/resources/css
/ext-all.css" />
        <script type="text/javascript" src="ext/adapter/ext
/ext-base.js"></script>
        <script type="text/javascript" src="ext/ext-all.js"></script>
        <script type="text/javascript" src="BrowserPlugin.js"></script>
        <script type="text/javascript">
        Ext.onReady(function() {
            var win1, win2;

            var button1 = Ext.get('button1');
            var button2 = Ext.get('button2');

            button1.on('click', function() {
                if(!win1) {
                    win1 = new Ext.Window({
                        title: 'Google',
                        closeAction: 'hide',
                        plugins: ['browserPlugin'],
                        url: 'http://www.google.ie'
                    });
                }
                win1.show(this);
            });

            button2.on('click', function() {
                if(!win2) {
                    win2 = new Ext.Window({
                        title: 'Sencha',
                        closeAction: 'hide',
                        plugins: ['browserPlugin'],
                        url: 'http://www.sencha.com'
                    });
                }
                win2.show(this);
            });
        });
        </script>
    </head>

    <body>
        <button id="button1">Show Google</button>
        <br />
        <button id="button2">Show Sencha</button>
    </body>
</html>

Again, this code is fairly familiar. You'll notice that below the loading of ext-all.js the new BrowserPlugin.js file is being loaded. The primary difference between the use of extensions and plug-ins can be seen in the click event handlers for the two buttons. When we created an extension, we instantiated an object of the new extension's subclass (ExtBrowserWindow), but when using a plug-in you instead use the regular Ext JS component you wish to display. In this case that is the Ext.Window component. In the configuration options for the component, you then specify that you wish to load the "browserPlugin" plug-in using the "plugins" configuration option.

The result of this is identical to that of the extension we created in the previous section, and you can see a screen shot of it in action in Figure 2, as seen earlier in this article. In this section, we have covered the basics of creating Ext JS plug-ins. Documentation and reading material on the subject is fairly sparse to say the least, so the best way to learn more advanced techniques is to download, use, and tinker with plug-ins and extensions created by other users in the Ext JS community. In the next section, you will learn how to use an existing extension in your own applications.

Using existing Ext JS plug-ins

You can find existing Ext JS extensions and plug-ins in a couple of ways. The first (and most complete) source is the Ext User Extensions and Plug-ins forum on the Sencha website (see Related topics). An unofficial user extension repository is also available (see Related topics). Most plug-ins and extensions are simply a JavaScript source file that you can download or copy and use in your own application. Most of these plug-ins and extensions are available for free use under relaxed licenses, but be sure to check the license for the extension in question before using in a commercial project.

When including an extension or plug-in, ensure that you do so after you have included the source JavaScript and CSS files for Ext JS itself. Extensions and plug-ins often override default Ext JS component functionality and require that these are loaded in advance of loading themselves.

The Ext JS project examples include a series of demos of custom extensions in action. In these demos, view the HTML source of the page to find the URL of the extension or plug-in JavaScript source file (if you are using JavaScript you can click on the link to open the source file directly). Copy this code and paste it into a file to use in your own projects. Each demo has a link to the JavaScript code that actually puts the plug-in into practice, so click on that to see how the example works.

See Related topics for links to Ext JS samples that are built on user extensions.

As you can see, a vast quantity of the official Ext JS samples and demos are built on user-contributed extensions. The user community plays a key role in the enhancement of the Ext JS framework, and several user extensions have gone on to become standard components in the framework itself.

Take some time to explore the demos above and look at the extension source code to get an appreciation for how complex an Ext JS extension or plug-in can be. User extensions in Ext JS usually are in the namespace Ext.ux, so look out for this when trying to find the source code for an extension.

Conclusion

In this article you learned the basics of Ext JS extension and plug-in development. You discovered what both of these concepts mean, what the differences are between them, and how to actually create them. You created a preconfigured class that saves time and valuable lines of code that can lead to more efficient applications that are easier to maintain. You then learned how to create an Ext JS extension—a browser window that subclassed the Ext.Window component. You learned how to define new properties and call corresponding functions in the superclass and how to use the new class in your application code. You then learned how to do the same thing, but in the form of an Ext JS plug-in. You learned how to create the plug-in, defining the mandatory init function, and how to register the plug-in to make it available to Ext JS components. With the basics learned in this article, you should now be ready to start learning about more complex concepts in Ext JS extension and plug-in development.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=590187
ArticleTitle=Build Ext JS extensions and plug-ins
publish-date=11232010