Ext JS

From CSE330 Wiki
Jump to: navigation, search

Ext JS is a JavaScript Framework. It serves two main functions:

  • Simplifies common operations that would take many lines in pure JavaScript
  • Provides a selection of APIs for client-side gadgets

As you read through this article, you might find it helpful to play with some of the examples. Feel free to open up a new JSFiddle, and where it says "Choose a Framework", select a recent version of Ext JS (version 4+).

Using Ext JS in Your Site

For the purposes of this class, you can go ahead and hot-link Ext JS from Sencha's CDN (Content Delivery Network) by putting the following line in your <head> section:

<script src="//cdn.sencha.io/ext-4.2.0-gpl/ext-all-dev.js"></script>

That's it! You can now use Ext in your web application and follow along with the examples below.

A Note about File Size

While convenient, the above version of Ext JS from Sencha's CDN is huge, over 5 MB. There are two main reasons for this:

  1. The above version is the dev version, which will give you helpful errors in the WebKit Inspector.
  2. The above version comes with a whole bunch of GUI tools that you probably will never be using.

A functionally equivalent version (minus the dev tools) that is 1 MB in size is also available from Sencha's CDN:

<script src="//cdn.sencha.io/ext-4.2.0-gpl/ext-all.js"></script>

However, if you don't plan on using the GUI features of Ext JS, you can use this 213 KB version:

<script src="//cdn.sencha.io/ext-4.2.0-gpl/ext.js"></script>

A Note about Licensing

Sencha's Ext JS platform, as well as most Ext APIs like Extensible's Calendar Pro, is dual-licensed: you can use it under either the free GNU GPL or a paid commercial license.

For the purposes of this course, you may use both Ext and all of its APIs for free under the terms of the GNU GPL. Indeed, you may continue using them for free even when you're developing a finished commercial application in real life. The catch is that it is not legal to use GNU GPL components in a finished product unless that project is also released under the GNU GPL. At that point, if you don't want to post your source code for others to see and modify, you'll need to pay Sencha for the license.

Selecting an Element

In pure JavaScript, you used functions like document.getElementById() in order to select elements. The functions provided by the W3C work fine, but they are often limiting. Ext Core provides functionality that lets you make more advanced element selections in fewer lines.

Select by ID

To select an element by its ID and then perform an action on it, use Ext.fly(id):

// Add the class "required" to the element with id "myDiv":
Ext.fly("myDiv").addCls("required");

If you need to pass the element by reference, use Ext.get(id) instead:

// Add the class "required" to an element passed as an argument:
function setElementRequired( element ){
	element.addCls("required");
}

// Call the above function, passing the element with id "myDiv" as the argument:
setElementRequired( Ext.get("myDiv") );

Note: Ext.fly() is faster than Ext.get(). However, Ext.fly() does not return a useful reference like Ext.get() does.

Note: element.addCls() adds a CSS class to that element. Prior to version 4 of Ext JS, it was simply element.addClass().

Calls to most Ext Element methods can be chained:

// Add the class "required" to the element with id "myDiv", then make it slowly fade away,
// all in one line:
Ext.fly("myDiv").addClass("required").ghost();

// The above line is functionally equivalent to:
Ext.fly("myDiv").addClass("required");
Ext.fly("myDiv").ghost();

Example: Ext Core Select

View in JSFiddle

This example illustrates one use of Ext.select(). Notice how the Ext selector for the "games" list works exactly the same as the selector for the "movies" list.

Select by CSS Selector

CSS provides a syntax with which you are already familiar for selecting elements. Ext enables us to use CSS selectors within JavaScript to select elements via Ext.select(selector). For example:

Ext.select("ul.games li:nth-child(2n)").addClass("required");

Document Ready

When a browser loads JavaScript from a server, it runs the code as soon as it is treated. This can cause problems if your JavaScript depends on content later in the document. Consider the following example:

<!DOCTYPE html>
<html>
<head>
	<title>JavaScript Execution Order</title>
	<script>
		alert( Ext.fly("myDiv").getHTML() );
	</script>
</head>
<body>
	<div id="myDiv">Hello World</div>
</body>
</html>

This raises the following exception: "Uncaught TypeError: Cannot read property 'textContent' of null." Why? Because the JavaScript is run before the Div is created!

Ext solves this problem by enabling us to bind JavaScript code to the DOMContentLoaded event, which fires as soon as the document is loaded. (This is different from the load event, which fires when the entire web page is loaded, including images.) Simply use Ext.onReady:

<!DOCTYPE html>
<html>
<head>
	<title>JavaScript Execution Order</title>
	<script>
		Ext.onReady(function(){
			alert( Ext.fly("myDiv").getHTML() );
		});
	</script>
</head>
<body>
	<div id="myDiv">Hello World</div>
</body>
</html>

While you could do this in pure JavaScript, there are backwards compatibility issues with that approach which Ext handles behind the scenes.

Utility Methods

Ext JS provides a variety of tools that enable you to perform other common tasks more easily.

Strings

Example: String Utility Functions

View in JSFiddle

Demonstration of some of Ext's string utility functions.

You can access Ext's String utility functions inside Ext.String. See the JSFiddle example for a demonstration. Some of the useful functions include:

  • Ext.String.trim(str) trims str of leading whitespace.
  • Ext.String.ellipsis(str, len) puts a (fake) ellipsis after len characters in str
  • Ext.String.escape(str) escapes ' and \ characters from str
  • Ext.String.format(format, arg0, arg1, ...) is Ext's version of sprintf (see the example for a demonstration)
  • Ext.String.htmlEncode(str) encodes HTML special characters to make a string safe for display; similar to PHP's htmlentities() or htmlspecialchars()
    Note: This is aliased as Ext.util.Format.htmlEncode(str)

A complete list is available in the Ext JS documentation.

Creating DOM Elements

Example: Creating Elements

View in JSFiddle

Demonstration of how Ext can create elements for the DOM.

Ext JS makes it easy to create new DOM elements on the fly. The following code creates a new list item inside the unordered list with ID "myList":

Ext.DomHelper.useDom = true; // See next section for an explanation of this line

Ext.fly("myList").createChild({
	tag: "li",
	children: [
		{
			tag: "strong",
			children: [
				"To Do: "
			]
		},
		"Water the garden"
	]
});

The HTML generated by the above example would be:

<li><strong>To Do: </strong>Water the Garden</li>

See the JSFiddle example for a demonstration.

Preventing HTML Injection

If you pass a string where Ext JS expects a child element, Ext will treat the string as an HTML string by default. This may open your application to XSS vulnerabilities if you are not careful. It is therefore recommended that you force Ext to create text nodes (thereby displaying strings literally) by putting this line at the top of your JavaScript file:

Ext.DomHelper.useDom = true;

Event Binding

Example: Event Binding

View in JSFiddle

How to use Ext to bind events. Gives examples of the `scope` and `options` parameters.

Event binding is relatively straightforward using Ext:

Ext.fly("myButton").on("click", function(){
	alert("You clicked my button");
});

The Ext.Element.on() method takes four parameters: the event type, the callback function, the scope of the callback function, and an options object. The callback function is passed three parameters: the event object, the target element, and the options object. For example:

var myObject = {
	say: function(message){
		alert(message);
	}
};
Ext.fly("myButton").on("click", function(event, element, options){
	this.say(options.message);
}), myObject, {
	message: "Hello World"
});

Other Helpful Utilities

  • Ext.Number.constrain(num, min, max) returns num iff it is between min and max, or otherwise min if the number was smaller or max if the number was bigger
  • Ext.Number.randomInt(min, max) returns a random integer between min and max inclusive.
  • Ext.Object.getKeys(obj) returns all keys from the object literal obj
  • Ext.Object.each(obj, fn) iterates through the object literal obj, calling fn(key, value) on each key/value pair.
  • Ext.each(arr, fn) iterates through the array arr, calling fn(value, index) on each item in the array.
  • Ext.Array.map(arr, fn) returns an array containing the return value of fn(value, index) on each item in arr.
  • Ext.Array.min(arr) and .max(arr) and .mean(arr) return the maximum value, minimum value, and average value of arr, respectively.
  • Ext.toArray(non_arr) converts the iterable non_arr into a true Array. Especially useful for dealing with the arguments non-array: alert( Ext.Array.toArray(arguments).join(" - ") );

AJAX

Ext Core makes AJAX easy. The following code fetches and parses the contents of data.json and then displays it on the page:

Ext.Ajax.request({
	url: "data.json",
	success: function(response){
		var jsonData = Ext.decode(response);
		Ext.fly("myDiv").setHTML( jsonData.description );
	},
	failure: function(respose){
		console.log( "Error loading data; received error code " + response.status );
	}
});

The following code sends a comment ID to comment_ajax.php, which responds with a JSON object containing the comment's HTML:

Ext.Ajax.request({
	url: "comment_ajax.php",
	params: {
		comment_id: 45
	},
	success: function(response){
		var jsonData = Ext.decode(response);
		// Sanitize the response before displaying it on the page:
		var sanitizedComment = Ext.util.Format.htmlEncode( jsonData.contents );
		Ext.fly("myDiv").setHTML( sanitizedComment );
	},
	failure: function(respose){
		console.log( "Error loading data; received error code " + response.status );
	}
});

Note: When parameters are given, Ext sends a POST request by default. If no parameters are given, Ext sends a GET request. If you want to send a GET request but also prevent caching, set the disableCaching option to true.

Note: We use Ext.util.Format.htmlEncode(str) in the above example. This is Ext's closest equivalent to PHP's htmlencode($str).

Submitting an Entire Form over AJAX

Ext gives us another handy feature for AJAX requests: it enables us to automatically send the entire contents of a form. For example, suppose we had the following form in HTML:

<form id="myForm" action="login.php">
	<label>Username: <input type="text" name="usr" /></label>
	<label>Password: <input type="password" name="pwd" /></label>
</form>

We can submit this form asynchronously in just one line of Ext:

Ext.Ajax.request({ form: "myForm" });

In practice, you may want to bind a function that submits the form in this manner to the submit event of that form.

Ext.fly("myFormId").on("submit", function(event, element){
	event.preventDefault();
	Ext.Ajax.request({
		form: element,
		success: function(response) {
			console.log("Success", response);
		},
		failure: function(response) {
			console.log("Failure", response);
		}
	});
});

Model View Controller

What really sets Ext.JS apart from other JavaScript libraries is the toolset it gives you to create GUI components. Ext.JS has an MVC engine that works on the front end of your application.

Models, Stores, and Proxies

Ext.JS adds a fourth concept to the MVC pattern: stores. A "store" is a collection of records, where a record is an instance of a model. In a lot of ways, if a model in Ext.JS is like a row in SQL, then a store in Ext.JS is like a table in SQL.

Ext.JS also introduces the concept of proxies: a mechanism that syncs the data in your front-end application to the server. In Ext.JS, a proxy is typically associated with a store. Ext.JS conforms to the RESTful paradigm in web application development.

For an example of models, stores, and proxies, see Extensible Calendar.

The Lino Framework

This wiki would not be complete without mentioning Lino, a framework that integrates Ext.JS into the Django stack. You may earn creative portion points on Module 6 if you choose to implement your project using the Lino framework.