This chapter introduces and defines the Ext JS plugins and extensions, the differences between them, and finally shows how to develop a plugin and an extension.
In this chapter we will cover:
What a plugin is
What an extension is
Differences between an extension and a plugin, and choosing the best option
Building an Ext JS plugin
Building an Ext JS extension
In this modern world of JavaScript, Ext JS is the best JavaScript framework that includes a vast collection of cross-browser utilities, UI widgets, charts, data object stores, and much more.
When developing an application, we mostly look for the best functionality support and components that offer it to the framework. But we usually face situations wherein the framework lacks the specific functionality or component that we need. Fortunately, Ext JS has a powerful class system that makes it easy to extend an existing functionality or component, or build new ones altogether.
An Ext JS plugin is a class that is used to provide additional functionalities to an existing component. Plugins must implement a method named init
, which is called by the component and is passed as the parameter at the initialization time, at the beginning of the component's lifecycle. The destroy
method is invoked by the owning component of the plugin, at the time of the component's destruction. We don't need to instantiate a plugin class. Plugins are inserted in to a component using the plugin's configuration option for that component.
Plugins are used not only by components to which they are attached, but also by all the subclasses derived from that component. We can also use multiple plugins in a single component, but we need to be aware that using multiple plugins in a single component should not let the plugins conflict with each other.
An Ext JS extension is a derived class or a subclass of an existing Ext JS class, which is designed to allow the inclusion of additional features. An Ext JS extension is mostly used to add custom functionalities or modify the behavior of an existing Ext JS class. An Ext JS extension can be as basic as the preconfigured Ext JS classes, which basically supply a set of default values to an existing class configuration. This type of extension is really helpful in situations where the required functionality is repeated at several places. Let us assume we have an application where several Ext JS windows have the same help button at the bottom bar. So we can create an extension of the Ext JS window, where we can add this help button and can use this extension window without providing the repeated code for the button. The advantage is that we can easily maintain the code for the help button in one place and can get the change in all places.
The Ext JS extensions and plugins are used for the same purpose; they add extended functionality to Ext JS classes. But they mainly differ in terms of how they are written and the reason for which they are used.
Ext JS extensions are extension classes or subclasses of Ext JS classes. To use these extensions, we need to instantiate these extensions by creating an object. We can provide additional properties, functions, and can even override any parent member to change its behavior. The extensions are very tightly coupled to the classes from which they are derived. The Ext JS extensions are mainly used when we need to modify the behavior of an existing class or component, or we need to create a fully new class or component.
Ext JS plugins are also Ext JS classes, but they include the init
function. To use the plugins we don't need to directly instantiate these classes; instead, we need to register the plugins in the plugins' configuration option within the component. After adding, the options and functions will become available to the component itself. The plugins are loosely coupled with the components they are plugged in, and they can be easily detachable and interoperable with multiple components and derived components. Plugins are used when we need to add features to a component. As plugins must be attached to an existing component, creating a fully new component, as done in the extensions, is not useful.
When we need to enhance or change the functionality of an existing Ext JS component, we have several ways to do that, each of which has both advantages and disadvantages.
Let us assume we need to develop an SMS text field having a simple functionality of changing the text color to red whenever the text length exceeds the allocated length for a message; this way the user can see that they are typing more than one message. Now, this functionality can be implemented in three different ways in Ext JS, which is discussed in the following sections.
We can choose to apply configuration to the existing classes. For example, we can create a text field by providing the required SMS functionality as a configuration within the listener's configuration, or we can provide event handlers after the text field is instantiated with the on
method.
This is the easiest option when the same functionality is used only at a few places. But as soon as the functionality is repeated at several places or in several situations, code duplication may arise.
By creating an extension, we can easily solve the problem as discussed in the previous section. So, if we create an extension for the SMS text field by extending the Ext JS text field, we can use this extension at as many places as we need, and can also create other extensions by using this extension. So, the code is centralized for this extension, and changing one place can reflect in all the places where this extension is used.
But there is a problem: when the same functionality is needed for SMS in other subclasses of Ext JS text fields such as Ext JS text area field, we can't use the developed SMS text field extension to take advantage of the SMS functionality. Also, assume a situation where there are two subclasses of a base class, each of which provides their own facility, and we want to use both the features on a single class, then it is not possible in this implementation.
By creating a plugin, we can gain the maximum re-use of a code. As a plugin for one class, it is usable by the subclasses of that class, and also, we have the flexibility to use multiple plugins in a single component. This is the reason why if we create a plugin for the SMS functionality we can use the SMS plugin both in the text field and in the text area field. Also, we can use other plugins, including this SMS plugin, in the class.
Let us start developing an Ext JS plugin. In this section we will develop a simple SMS plugin, targeting the Ext JS textareafield
component. The feature we wish to provide for the SMS functionality is that it should show the number of characters and the number of messages on the bottom of the containing field. Also, the color of the text of the message should change in order to notify the users whenever they exceed the allowed length for a message.
Here, in the following code, the SMS plugin class has been created within the Examples
namespace of an Ext JS application:
Ext.define('Examples.plugin.Sms', { alias : 'plugin.sms', config : { perMessageLength : 160, defaultColor : '#000000', warningColor : '#ff0000' }, constructor : function(cfg) { Ext.apply(this, cfg); this.callParent(arguments); }, init : function(textField) { this.textField = textField; if (!textField.rendered) { textField.on('afterrender', this.handleAfterRender, this); } else { this.handleAfterRender(); } }, handleAfterRender : function() { this.textField.on({ scope : this, change : this.handleChange }); var dom = Ext.get(this.textField.bodyEl.dom); Ext.DomHelper.append(dom, { tag : 'div', cls : 'plugin-sms' }); }, handleChange : function(field, newValue) { if (newValue.length > this.getPerMessageLength()) { field.setFieldStyle('color:' + this.getWarningColor()); } else { field.setFieldStyle('color:' + this.getDefaultColor()); } this.updateMessageInfo(newValue.length); }, updateMessageInfo : function(length) { var tpl = ['Characters: {length}<br/>', 'Messages:{messages}'].join(''); var text = new Ext.XTemplate(tpl); var messages = parseInt(length / this.getPerMessageLength()); if ((length / this.getPerMessageLength()) - messages > 0) { ++messages; } Ext.get(this.getInfoPanel()).update(text.apply({ length : length, messages : messages })); }, getInfoPanel : function() { return this.textField.el.select('.plugin-sms'); } });
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
In the preceding plugin class, you can see that within this class we have defined a "must implemented" function called init
. Within the init
function, we check whether the component, on which this plugin is attached, has rendered or not, and then call the handleAfterRender
function whenever the rendering is. Within this function, a code is provided, such that when the change
event fires off the
textareafield
component, the handleChange
function of this class should get executed; simultaneously, create an HTML <div>
element within the handleAfterRender
function, where we want to show the message information regarding the characters and message counter. And the handleChange
function is the handler that calculates the message length in order to show the colored, warning text, and call the updateMessageInfo
function to update the message information text for the characters length and the number of messages.
Now we can easily add the following plugin to the component:
{ xtype : 'textareafield', plugins : ['sms'] }
Also, we can supply configuration options when we are inserting the plugin within the plugins
configuration option to override the default values, as follows:
plugins : [Ext.create('Examples.plugin.Sms', { perMessageLength : 20, defaultColor : '#0000ff', warningColor : "#00ff00" })]
Let us start developing an Ext JS extension. In this section we will develop an SMS extension that exactly satisfies the same requirements as the earlier-developed SMS plugin.
We already know that an Ext JS extension is a derived class of existing Ext JS class, we are going to extend the Ext JS's textarea
field that facilitates for typing multiline text and provides several event handling, rendering and other functionalities.
Here is the following code where we have created the Extension
class under the SMS view within the Examples
namespace of an Ext JS application:
Ext.define('Examples.view.sms.Extension', { extend : 'Ext.form.field.TextArea', alias : 'widget.sms', config : { perMessageLength : 160, defaultColor : '#000000', warningColor : '#ff0000' }, constructor : function(cfg) { Ext.apply(this, cfg); this.callParent(arguments); }, afterRender : function() { this.on({ scope : this, change : this.handleChange }); var dom = Ext.get(this.bodyEl.dom); Ext.DomHelper.append(dom, { tag : 'div', cls : 'extension-sms' }); }, handleChange : function(field, newValue) { if (newValue.length > this.getPerMessageLength()) { field.setFieldStyle('color:' + this.getWarningColor()); } else { field.setFieldStyle('color:' + this.getDefaultColor()); } this.updateMessageInfo(newValue.length); }, updateMessageInfo : function(length) { var tpl = ['Characters: {length}<br/>', 'Messages:{messages}'].join(''); var text = new Ext.XTemplate(tpl); var messages = parseInt(length / this.getPerMessageLength()); if ((length / this.getPerMessageLength()) - messages > 0) { ++messages; } Ext.get(this.getInfoPanel()).update(text.apply({ length : length, messages : messages })); }, getInfoPanel : function() { return this.el.select('.extension-sms'); } });
As seen in the preceding code, the extend
keyword is used as a class property to extend the Ext.form.field.TextArea
class in order to create the extension class. Within the
afterRender
event handler, we provide a code so that when the change
event fires off the textarea field, we can execute the handleChange
function of this class and also create an Html <div>
element within this afterRender
event handler where we want to show the message information regarding the characters counter and message counter. And from this section, the logic to show the warning, message character counter, and message counter is the same as we used in the SMS plugin.
Now we can easily create an instance of this extension:
Ext.create('Examples.view.sms.Extension');
Also, we can supply configuration options when we are creating the instance of this class to override the default values:
Ext.create('Examples.view.sms.Extension', { perMessageLength : 20, defaultColor : '#0000ff', warningColor : "#00ff00" });
The following is the screenshot where we've used the SMS plugin and extension:

In the above screenshot we have created an Ext JS window and incorporated the SMS extension and SMS plugin. As we have already discussed on the benefit of writing a plugin, we can not only use the SMS plugin with text area field, but we can also use it with text field.
We have learned from this chapter what a plugin and an extension are, the differences between the two, the facilities they offer, how to use them, and take decisions on choosing either an extension or a plugin for the needed functionality. In this chapter we've also developed a simple SMS plugin and an SMS extension.