Você está na página 1de 84

Introduction

Ext Core is a lightweight and feature rich core JavaScript library available
under an MIT license. Ext Core is packed full of exciting features intended to
allow for rapid web development while encouraging well designed and
scalable code. This library provides abstractions for DOM
manipulation/traversal, Ajax, Events and custom events, animations,
templating, OO mechanisms and more. Ext Core is released under an MIT
license and is perfect for inclusion in a dynamic webpage or even a small
application.

Download

Ext Core can be downloaded here and the latest information can be found on
the Ext Core Project Page.

Including Ext Core

Ext Core ships with both a debug version as well as a production version.
The production version has been minified (whitespace, carriage returns and
comments removed) and obfuscated (all local variables have been renamed
to shorter versions) using YUI Compressor. You should always use the -
debug version when developing since you'll receive more informative (ie:
unobfuscated) error messages.

To include the Ext Core library's development version, simply include the
following JavaScript file:

<script src="ext-core-debug.js"></script>

And for the production version (25k compressed and gzipped), simply
remove "-debug":

<script src="ext-core.js"></script>

That's it. There is no css file to include with Ext Core.


Simple Example

After you have included Ext Core to your web page, try out the following
code to check if everything working correctly

Ext.onReady(function() {
Ext.DomHelper.append(document.body, {tag: 'p', cls: 'some-class'});
Ext.select('p.some-class').update('Ext Core successfully injected');
});

About

The Ext Core Manual was authored by Tommy Maintz, Aaron Conran, James
Donaghue, Jamie Avins & Evan Trimboli. Thank you to all reviewers who
reviewed the manual prior to its release. We are currently looking for
translations to all other languages.

The Ext Core Manual is licensed under the GNU FDL, GNU Free
Documentation License.

Copyright (C) 2009 Ext JS, LLC.


Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
Ext.Element
Getting Ext.Elements

An HTML Document typically consists of a lot of html markup. When the


browser loads your html document, each tag in your markup get translated
into an HTMLElement and the browser builds a Document Object Model
(DOM) tree of the markup. This DOM tree is saved in the browser's global
scope in a variable called document. This document variable holds a
reference to every piece of markup which has been loaded on the page.

The document object provides an important method named getElementById.


This method allows you to retrieve the underlying HTMLElement in any
browser. However, you should be mindful that there are many differences
among browsers when directly manipulating the DOM. Ext Core implements
a class named Ext.Element which wraps around typical HTMLElement's
providing you cross-browser support.

Ext.Element has the most methods out of any class in the Ext Core library.
These methods can be categorized as follows:

CSS & Styling


(eg: setStyle, addClass)
Dom Querying or Traversal
(eg: query, select, findParent)
Dom Manipulation
(eg: createChild, remove)
Dimensions
(eg: getHeight, getWidth)

You can use the method Ext.get to create an instance of an Ext.Element


which wraps around any HTMLElement. For example, if your markup had an
element with an id of 'myElementId' you could retrieve it like this.

var el = Ext.get('myElementId');
Using Firebug, try executing the following code. Observe the methods
exposed by Ext.Element. Remember that because you are looking at the raw
JS Object, both public as well as private methods are visible. When in doubt,
consult the API documentation.

var el = Ext.get('myElementId');
console.dir(el);

console.dir is a method provided by Firebug which will dump out the


contents of an object in an easily viewable format. It also allows you to
expand and collapse sub-objects which have additional properties. Properties
are shown in the color black. Methods/Functions are green; constructors or
classes in red.
Now let's try interacting with the paragraph above which has an id of
myElementId.

var el = Ext.get('myElementId');
el.addClass('error');

After executing this code, the font color in the paragraph above will change
to red. This page has a CSS rule which changes all elements with a class of
error to the color red. The CSS rule looks like this:

.error {
color: red;
}

The next section on Ext.Element (CSS Classes & Styling) will cover many
ways to interact with with your elements' CSS classes and styling.

Introducing the Flyweight

The Flyweight Design Pattern is a pattern used to minimize memory usage


by creating a single global object and then re-using that object over and
over again. Ext creates a global Ext.Element to use as the Flyweight when it
starts up. This global flyweight instance can then be used to target any node
in the Dom. To access this flyweight object you can use the Ext.fly method.
Those new to Ext often express confusion about whether to use Ext.get or
Ext.fly:

Whenever a reference to an Ext.Element is required to be saved for later


use, use the Ext.get method. For times when you don't need to store a
reference to the element, you can use the shared flyweight Ext.Element
across the library. To access this flyweight object, use the method
Ext.fly(elementId).

Let's remove the error class from the paragraph above.

Ext.fly('myElementId').removeClass('error');
When this code was executed, Ext was able to re-use the existing shared
flyweight object and did not have to instantiate a brand new instance of an
Ext.Element. The fly method is appropriate in situations executing a single,
one-lined, atomic operation. You never want to try to store a reference to
the flyweight object, since it is subject to change by some other snippet of
code. For an example, let's take a look at the following example.

var el = Ext.fly('foo');
Ext.fly('bar').frame();
el.addClass('error');

frame is a highlighting effect that is included in the animation package of


Ext.Element. What do you think the results would be?

The answer is that the element with an id of bar will have the frame effect
applied to it and then immediately after it will also have the CSS class of
error applied to it. Nothing will happen to the element with an id of foo,
because the reference el points to the global flyweight which was
overwritten when we used the frame effect on bar. If you did not expect
this, re-read the section about flyweights as it is an important concept if you
wish to use the Ext.fly method.

Ext.get

Ext.get takes an HTMLElement, Ext.Element, String id as a parameter


and returns a new instance of an Ext.Element.
All three of the following return an Ext.Element:

var el1 = Ext.get('elId'); // takes an element id


var el2 = Ext.get(el1); // takes an Ext.Element
var el3 = Ext.get(el1.dom); // takes an HTMLElement
Ext.fly

Ext.fly takes the same argument as Ext.get but it returns a reference


to an internally managed flyweight instance of an Ext.Element. Never
store a reference to the flyweight object as it will change per
invocation of this method. It is intended purely as a mechanism to
enhance performance by circumventing the need to instantiate a new
Ext.Element when a reference in not needed (eg: if you just want to
perform an action).

Here is an example of using Ext.fly:

// We want to perform only one discrete action on this element.


Ext.fly('elId').hide();

Ext.getDom

Ext.getDom returns a dom node for the passed in String (id), dom
node, or Ext.Element.
Here are some examples:

// gets dom node based on id


var elDom = Ext.getDom('elId');
// gets dom node based on the dom node
var elDom1 = Ext.getDom(elDom);

// If we don't know if we are working with an


// Ext.Element or a dom node use Ext.getDom
function(el){
var dom = Ext.getDom(el);
// do something with the dom node
}
CSS Clases & Styling

We have learned about markup, how that relates to the document and the
methods that Ext Core provides making it easy to retrieve that data. What
about the layout of the document though? How do we manipulate the layout
and styling of the document? The answer is to use Cascading Style Sheets
(CSS) styling. CSS is the language by which we can control layout and visual
information about our page. Ext Core makes it really easy to manipulate the
style of elements in the document through classes or by modifying styles
directly.

<style type="text/css">
myCls {
color: #F00;
}
</style>

...

<div type="myCls">Hello</div>

In the example above the class 'myCls' is applied to the div giving the text
'Hello' a visual color of red (#F00).
Now that we have already learned about firebug, take a look some more of
the wonderful tools that it has to offer us. Right click on any element in the
page and choose "Inspect Element". Now in firebug we can see the dom tree
and where that element is located. If you look to the right of that tree you
will see a panel with all of the styles applied to that element.

If you're not yet familiar with using FireBug, pause now and learn all about it
-- it's the oscilloscope of web-development. Inspect-element comes in handy
for changing styles on an existing site or creating and debugging styles on a
new site. So lets explore the methods that Ext Core provides to make css
modifications easier for you.

addClass

To easily add a class to an element:

Ext.fly('elId').addClass('myCls'); // adds the class 'myCls' to the


element

radioClass

Add class in one element and remove that same class if it exists from
all of its siblings in one call.

// add the class 'myCls' to the element and remove that same class from
// all sibilings.
Ext.fly('elId').radioClass('myCls');
removeClass

Remove one or more classes from an element.

Ext.fly('elId').removeClass('myCls'); // remove the class from the


element

toggleClass

Toggle a class on/off. If it isn't applied to the element it will be, it is is


then it will be removed.

Ext.fly('elId').toggleClass('myCls'); // the class is added


Ext.fly('elId').toggleClass('myCls'); // the class is removed
Ext.fly('elId').toggleClass('myCls'); // the class is added again

hasClass

Check to see if the element has the class applied.

if (Ext.fly('elId').hasClass('myCls')) {
// it has the class
}

replaceClass

Replace the class a with class b.

Ext.fly('elId').replaceClass('myClsA', 'myClsB');
getStyle

Gets a normalized (currentStyle and computed style) property from


the element.

var color = Ext.fly('elId').getStyle('color');


var zIndx = Ext.fly('elId').getStyle('z-index');
var fntFmly = Ext.fly('elId').getStyle('font-family');
// ... etc.

setStyle

Set style properties on an element. Takes a string or an object literal.

Ext.fly('elId').setStyle('color', '#FFFFFF');
Ext.fly('elId').setStyle('z-index', 10);
Ext.fly('elId').setStyle({
display : 'block',
overflow : 'hidden',
cursor : 'pointer'
});
// animate the transition of color
Ext.fly('elId').setStyle('color', '#FFFFFF', true);
// animate the transition of color with a duration of .75 seconds
Ext.fly('elId').setStyle('color', '#FFFFFF', {duration: .75});
// ... etc.
getColor

Gets a normalized (6 digit hex) color value for the passed in property,
accepts a default value if the property is not set and a prefix (# is the
default).

Ext.fly('elId').getColor('background-color');
Ext.fly('elId').getColor('color');
Ext.fly('elId').getColor('border-color');
// ... etc.

setOpacity

Sets the opacity of the element.

Ext.fly('elId').setOpacity(.5);
Ext.fly('elId').setOpacity(.45, true); // animates
// animates with a duration of half a second
Ext.fly('elId').setOpacity(.45, {duration: .5});

clearOpacity

Clears any opacity settings of the element.

Ext.fly('elId').clearOpacity();
Dom Traversal

Frequently we want to navigate around the dom tree from any given position
that we are working in. Ext Core provides many useful cross browser
methods that give you trememndous power in traversing up, down and all
around the dom. Again CSS comes to the rescue when we want to perform
complex navigations rather easily. The use of CSS3 selectors has a powerful
application in this domain. Take the following markup:

<style type="text/css">
.red {
color: #F00;
}
</style>
...
<div id='elId'>
<ul>
<li>a-one</li>
<li>a-two</li>
<li>a-three</li>
<li>a-four</li>
</ul>
<ul>
<li>b-one</li>
<li>b-two</li>
<li>b-three</li>
</ul>
</div>

Now say you have a requirement to make every other list item have red
text. Ext Core allows you to solve this elegantly with the following one-liner.
Ext.fly('elId').select('li:nth-child(2n)').addClass('red');
Here is the result:

Now that we've seen some of the power in Ext Core's Dom Traversal API,
lets explore more:

is

Tests the current element to see if it matches the selector.

var el = Ext.get('elId');
if (el.is('p.myCls')) {
// do something
}

findParent

Finds a parent node that matches the selector, starts at the current
node.

Ext.fly('elId').findParent('div'); // returns a dom node


Ext.fly('elId').findParent('div', 4); // looks up 4 parent nodes
Ext.fly('elId').findParent('div', null, true); // returns an
Ext.Element

findParentNode

Finds a parent node that matches the selector, starts at the parent
node.
Ext.fly('elId').findParentNode('div');

up

Finds a parent node that matches the selector, starts at the parent
node. This returns an Ext.Element

Ext.fly('elId').up('div');
Ext.fly('elId').up('div', 5); // only looks up 5 parents

select

Select takes a query and returns an Ext.CompositeElement or an array


of Ext.Elements. Also if you call this from an element it is used as the
root to start the query, if it is called from Ext.select the entire
document is searched.

// CompositeElement of results is returned


Ext.fly('elId').select('div:nth-child(2)');
// Array of elements is returned
Ext.fly('elId').select('div:nth-child(2)', true);
// Entire document is searched
Ext.select('div:nth-child(2)');

query

Select takes a query and returns an array of dom nodes. Takes an


optional root element as a second argument, if this is not present it
defaults to document root.

Ext.query('div:nth-child(2)'); // Array of dom nodes that matched the


selector
child

Child selects a single child at any given depth below the current
element based on the passed in selector.

Ext.fly('elId').child('p.highlight'); // returns an Ext.Element


Ext.fly('elId').child('p.highlight', true); // returns a dom node

down

Selects a single direct child based on the passed in selector.

Ext.fly('elId').down('span'); // returns an Ext.Element


Ext.fly('elId').down('span', true); // returns a dom node

parent

Gets the parent node for this element. If a selector is passed in it will
go up the chain looking for a match.

// grabs the parent node as and Ext.Element


Ext.fly('elId').parent();
// grabs the parent node as a dom node
Ext.fly('elId').parent("", true);
// grabs the first parent that is a div, returns Ext.Element
Ext.fly('elId').parent("div");
next

Gets the next sibling skipping text nodes. If a selector is passed in it


will filter for that selector.

// grabs the next sibling node as and Ext.Element


Ext.fly('elId').next();
// grabs the next sibling node as a dom node
Ext.fly('elId').next("", true);
// grabs the next sibling node that is a div, returns Ext.Element
Ext.fly('elId').next("div");

prev

Gets the previous sibling skipping text nodes. If a selector is passed in


it will filter for that selector.

// grabs the previous sibling node as and Ext.Element


Ext.fly('elId').prev();
// grabs the previous sibling node as a dom node
Ext.fly('elId').prev("", true);
// grabs the previous sibling node that is a div, returns Ext.Element
Ext.fly('elId').prev("div");

first

Gets the first sibling skipping text nodes. If a selector is passed in it


will filter for that selector.

// grabs the first sibling node as and Ext.Element


Ext.fly('elId').first();
// grabs the first sibling node as a dom node
Ext.fly('elId').first("", true);
// grabs the first sibling node that is a div, returns Ext.Element
Ext.fly('elId').first("div");
last

Gets the last sibling skipping text nodes. If a selector is passed in it


will filter for that selector.

// grabs the last sibling node as and Ext.Element


Ext.fly('elId').last();
// grabs the last sibling node as a dom node
Ext.fly('elId').last("", true);
// grabs the last sibling node that is a div, returns Ext.Element
Ext.fly('elId').last("div");

Manipulation

Elements
In a dynamic page one of the most frequent tasks is to create or remove
elements in the DOM. Due to inconsistencies between browsers this can
prove to be a challenging task. Ext Core provides a stong API that abstracts
these cross browser inconsistencies and is internally optimized for efficiency.
We can easily add, remove or replace nodes in the Dom tree at any position
we want relative to siblings and parents using Ext Core's Dom Manipulation
API. Let's take a look for ourselves -- observe the following markup:

<div id='elId'>
<p>paragraph one</p>
<p>paragraph two</p>
<p>paragraph three</p>
</div>
Here is a screenshot of the markup:

Lets create a new node and insert this as a first child of 'elId':
Ext.fly('elId').insertFirst({
tag: 'p',
html: 'Hi I am the new first child'
});

Now we can see that our node was inserted:

Easy enough! -- lets explore some of the more powerful mainuplation API's
provided by Ext Core:

appendChild

Appends the passed element(s) to this element.

var el = Ext.get('elId1');
// append the dom node with this id.
Ext.fly('elId').appendChild('elId2');
// append an Ext.Element
Ext.fly('elId').appendChild(el);
// append the result of an array of selectors
Ext.fly('elId').appendChild(['elId2','elId3']);
// append a straight dom node
Ext.fly('elId').appendChild(el.dom);
// append a CompositeElement of all divs
Ext.fly('elId').appendChild(Ext.select('div'));

appendTo

Appends this element to the passed in element.

var el = Ext.get('elId1');

Ext.fly('elId').appendTo('elId2'); // append to the dom node with this


id.
Ext.fly('elId').appendTo(el); // append to the Ext.Element el

insertBefore

Inserts this element before the passed in element.

var el = Ext.get('elId1');

// inserts before the dom node with this id.


Ext.fly('elId').insertBefore('elId2');
// inserts before the Ext.Element el
Ext.fly('elId').insertBefore(el);

insertAfter

Inserts this element after the passed in element.

var el = Ext.get('elId1');

// inserts after the dom node with this id.


Ext.fly('elId').insertAfter('elId2');
// inserts after the Ext.Element el
Ext.fly('elId').insertAfter(el);

insertFirst
Takes an element, id, or DomHelper config and inserts the existing
node or creates a new element from the DomHelper config as the first
child of this element.

var el = Ext.get('elId1');

// inserts the dom node with this id as the first child.


Ext.fly('elId').insertFirst('elId2');
// inserts the Ext.Element el as the first child
Ext.fly('elId').insertFirst(el);

// creates a new node with the DomHelper config and inserts


// the result as the first child.
Ext.fly('elId').insertFirst({
tag: 'p',
cls: 'myCls',
html: 'Hi I am the new first child'
});

replace

Replace the passed in element with this element.

var el = Ext.get('elId1');

// replaces the element with id 'elId2' with 'elId'.


Ext.fly('elId').replace('elId2');
// replaces the element with id 'elId1' with 'elId'
Ext.fly('elId').replace(el);
replaceWith

Takes an element, id, or DomHelper config and replaces this element


with the existing node or the newly created element from the
DomHelper config.

var el = Ext.get('elId1');

Ext.fly('elId').replaceWith('elId2'); // replaces 'elId' with 'elId2'.


Ext.fly('elId').replaceWith(el); // replaces 'elId' with 'elId1'

// creates a new node with the DomHelper config


// and replaces 'elId' with this node.
Ext.fly('elId').replaceWith({
tag: 'p',
cls: 'myCls',
html: 'Hi I have replaced elId'
});
DomHelper configs
In the examples above, perhaps you notice the following:
.insertFirst({
tag: 'p',
html: 'Hi I am the new first child'
});

You may have wondered what the 1st argument to insertFirst is. This is a
DomHelper config which represents the markup to be created. DomHelper
configs support many properties for specifying child nodes, such as html
fragments and DomNode attributes (css classes, url, src, id, etc). Here are
some of the API's available on Ext.Element that allow you to interact directly
with Ext.DomHelper:

createChild

Creates the passed DomHelper config and appends it to this element


or optionally inserts it before the passed child element.

var el = Ext.get('elId');
var dhConfig = {
tag: 'p',
cls: 'myCls',
html: 'Hi I have replaced elId'
};

// creates a new node and appends it to 'elId'.


el.createChild(dhConfig);
// creates a new node and inserts before el's first child.
el.createChild(dhConfig, el.first());
wrap

Wraps this element with a newly created element

Ext.fly('elId').wrap(); // wraps elId with a div

// wraps elId with the newly create element


Ext.fly('elId').wrap({
tag: 'p',
cls: 'myCls',
html: 'Hi I have replaced elId'
});

Html Fragments
Html fragments are just what they sound like, fragments of html markup.
Ext Core provides the ability to modify the dom with html fragments,
allowing you to focus upon just those fragments of markup that you intend
to modify the dom with, freeing you from browser implementation and
performance worries. Ext Core does all of that for you -- all you need to do
is provide the markup. For example, given the following markup:

<div id='elId'>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</div>

What do you think the following Ext Core code will do?

Ext.fly('elId').insertHtml('beforeBegin', '<p>Hi</p>')
Lets take a look at the markup afterward:

<p>Hi</p>
<div id='elId'>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</div>

Suprised? That's because we are able to specify the relative position where
we want this markup applied. We specified 'beforeBegin'. What about this:
Ext.fly('elId').insertHtml('afterBegin', '<p>Hi</p>')

Lets take a look:


<div id='elId'>
<p>Hi</p>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</div>

Now we will use 'beforeEnd'.


Ext.fly('elId').insertHtml('beforeEnd', '<p>Hi</p>')

Lets take a look:


<div id='elId'>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<p>Hi</p>
</div>

And finally lets look at 'afterEnd'.


Ext.fly('elId').insertHtml('beforeEnd', '<p>Hi</p>')
Lets take a look:
<div id='elId'>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</div>
<p>Hi</p>

The following API is yeaprovided for you to work with html fragments.

insertHtml

Inserts an html fragment into this element. You need to specify where
(beforeBegin, beforeEnd, afterBegin, afterEnd) the fragment and can
optionally specify if you want an Ext.Element returned instead of the
dom node.

Ext.fly('elId').insertHtml(
'beforeBegin',
'<p><a href="anotherpage.html'>click me</a></p>'
); // returns dom node
Ext.fly('elId').insertHtml(
'beforeBegin',
'<p><a href="anotherpage.html'>click me</a></p>',
true
); // returns Ext.Element

remove

Removes this element from the DOM and deletes it from the cache.

Ext.fly('elId').remove(); // elId is removed from the dom and from


cache

removeNode
Removes a DOM node from the document. The body node will be
ignored if passed in.

Ext.removeNode(node); // node (HTMLElement) is removed from the dom

Ajax
Ext Core includes a powerful Ajax API. Ajax will be covered in greater detail
in later sections but here's a brief overview of the present API in Ext Core:

load

Direct access to the Updater Ext.Updater.update method. The method


takes the same object parameter as Ext.Updater.update

Ext.fly('elId').load({url: 'serverSide.php'})

getUpdater

Gets this element's Ext.Updater

var updr = Ext.fly('elId').getUpdater();


updr.update({
url: 'http://myserver.com/index.php',
params: {
param1: "foo",
param2: "bar"
}
});
Event Handling

Event handling poses one of the most troublesome differences among the
browsers. Ext Core abstracts the differences you would encounter to achieve
cross-browser event handling. If you were to use each browser's native
event handling mechanism you need to use different methods to register
and unregister events in addition to a myriad of other frustrating
inconsistencies.

Ext Core provides a rich event model which frees one from these differences
by using a single clean, consistent interface. Just as Ext.Element wraps
around a native Dom node, Ext Core will also wrap the browser's native
event-object with an instance of Ext.EventObject. Ext.EventObject
normalizes cross-browser differences, such as which mouse button is clicked,
keys pressed, mechanisms to stop event-propagation along with a method
to prevent default actions from taking place.

To tie an event handler to an element on the page we will use the on


method of Ext.Element. The on method is a preferred shorthand for
addListener. The first argument specifies which event to subscribe to and the
second argument specifies the function to run when that event occurs.

Ext.fly('myEl').on('click', function(e, t) {
// perform an action on click of myEl
// e is an Ext.EventObject describing what occured
// t is the target HTMLElement
});

Ext Core normalizes the arguments of all Dom events. The event handler
which is tied to the event will always receive a normalized event object
(Ext.EventObject) and the target HTMLElement.
Let's take a look at the API provided for Event Handling:

addListener/on

Appends an event handler to this element. The shorthand version on is


equivalent and preferred for concise code.

var el = Ext.get('elId');
el.on('click', function(e,t) {
// e is a normalized event object (Ext.EventObject)
// t the target that was clicked, this is an Ext.Element.
// this also points to t.
});

removeListener/un

Removes an event handler from this element. The shorthand version


un is equivalent.

var el = Ext.get('elId');
el.un('click', this.handlerFn);
// or
el.removeListener('click', this.handlerFn);

Ext.EventObject

EventObject exposes a cross-browser consistent event model


mimicking the standard W3C methods if necessary.

// e is not a standard event object, it is a Ext.EventObject


function handleClick(e){
e.preventDefault();
var target = e.getTarget();
...
}
var myDiv = Ext.get('myDiv');
myDiv.on("click", handleClick);
//or
Ext.EventManager.on('myDiv', 'click', handleClick);
Ext.EventManager.addListener('myDiv', 'click', handleClick);

Advanced Event Handling

Ext Core has several convenience configurations for more advanced event
handling techniques such as event delegation, buffering, and delays.

delegation

Event delegation is a technique that is used to reduce memory


consumption and prevent exposure to memory-leaks. The basic idea is
this:

Rather than registering an event handler for each element in a group


of elements, register it once in a container element taking advantage
of the bubbling phase in the event life-cycle and centralize the event-
handling at the container level.

This doesn't mean that you want to register one global handler on the
body element, as any action on the page that fired an event would
bubble up to that handler and probably have the reverse effect,
actually degrading performance. This technique is extremely useful in
situations like a drop-down, a calendar, etc. Anywhere you have a
group of elements that can be directly or almost directly contained by
a container element. Lets take a look:

Take the following markup:

<ul id='actions'>
<li id='btn-edit'></li>
<li id='btn-delete'></li>
<li id='btn-cancel'></li>
</ul>

Instead of registering a handler directly upon each list item as follows:

Ext.fly('btn-edit').on('click, function(e,t) {
// handle the event
});
Ext.fly('btn-delete').on('click, function(e,t) {
// handle the event
});
Ext.fly('btn-cancel').on('click, function(e,t) {
// handle the event
});

To use the event delegation technique instead, registering just one


handler on the container along with accompanying logic:

Ext.fly('actions').on('click, function(e,t) {
switch(t.id) {
case ''btn-edit':
// handle the event
break;
case 'btn-delete':
// handle the event
break;
case 'btn-cancel':
// handle the event
break;
}
});

Because events bubble up the dom hierarchy, they will reach the
handler that we registered on the 'actions' div. We then use a simple
switch to execute the required code. This approach scales well because
we can add many different child elements and still maintain a single
event handler.

delegate

This is a configuration option that you can pass along when registering
a handler for an event to assist with event delegation. By setting this
configuration option to a simple selector, Ext Core will filter the target
or look for a descendant of the target.

el.on('click', function(e,t) {
// handle click
}, this, {
// will filter target to be a descendant with the class 'clickable'
delegate: '.clickable'
});
hover

Ext Core has a cross browser solution for creating a hover effect. The
hover method will ensure that a function is run when the mouse enters
an element and when the mouse leaves an element. mouseenter and
mouseleave are native Internet Explorer events which will filter
mouseout and mouseover events when you are when working with
child elements. Ext Core implements these events for W3C compliant
browsers so that you can use them in any browser.

// handles when the mouse enters the element


function enter(e,t){
t.toggleClass('red');
}
// handles when the mouse leaves the element
function leave(e,t){
t.toggleClass('red');
}
// subscribe to the hover
el.hover(over, out);

removeAllListeners

Removes all previous added listeners from this element

el.removeAllListeners();
single

This is a configuration option that you can pass along when registering
a handler for the event. When set to true, the handler will fire just
once then automatically remove itself.

el.on('click', function(e,t) {
// handle click
}, this, {
single: true // will remove the event after its first firing.
});

buffer

This is a configuration option that you can pass along when registering
a hanlder for the event. This causes the handler to be scheduled to run
in an Ext.util.DelayedTask delayed by the specified number of
milliseconds. If the event fires again within that time, the original
handler is not invoked, but the new handler is scheduled in its place.

el.on('click', function(e,t) {
// handle click
}, this, {
buffer: 1000 // will delay and buffer the firing of
//this event after its initial fire 1000 miliseconds (or 1 second).
});
delay

This is a configuration option that you can pass along when registering
a hanlder for the event. The number of milliseconds to delay the
invocation of the handler after te event fires.

el.on('click', function(e,t) {
// handle click
}, this, {
// will delay the firing of this event after its initial
// fire 1000 miliseconds (or 1 second).
delay: 1000

});

target

This is a configuration option that you can pass along when registering
a hanlder for the event. If you have a specific target that you want to
handle for only, you can assign a reference of it to this config option
and Ext Core will make sure that your handler gets only calls the
handler when it has reached that node in its bubbling phase.

el.on('click', function(e,t) {
// handle click
}, this, {
// only handles the event when it has bubbled up to the first
'div'.
target: el.up('div')
});
Dimensions & Sizing

Often we need to retrieve or change the dimensions of some particular


element on a page. Once again, Ext Core abstracts dimensioning through a
clean API. Most of the setter-methods accept animation configurations or a
straight boolean true to animate the action. Let's take a look:

// changes the height to 200px and animates with default configuration


Ext.fly('elId').setHeight(200, true);

// changes the height to 150px and animates with a custom configuration


Ext.fly('elId').setHeight(150, {
duration : .5, // animation will have a duration of .5 seconds
// will change the content to "finished"
callback: function(){ this.update("finished"); }
});

Pull up firebug, inspect and element (right click and then click on 'Inspect
Element') and take a look at the right panel and click on "layout". You should
see something like this:
This information is extremely useful since it provides all the dimensions of
the inspected-element. Notice the element has a width of 895px, a height of
1669px, 0px padding all around, 0px border all around and 0px margin. All
this information is available to you through Ext Core's Dimensioning API of
Ext.Element!
var dimSz = Ext.get('dim-sizing');
var padding = dimSz.getPadding('lrtb'); // has value of 0px
var border = dimSz.getBorderWidth('lrtb'); // has value of 0px
var height = dimSz.getHeight(); // has value of 1691px
var width = dimSz.getWidth(); // has value of 895px

Grab this code and run it in firebug to see for yourself. In fact go a step
further and try using the setters to modify the height and width and see
what happens to the box in the firebug layout panel. (NOTE: if your height
and width are different from the image, that is because of the dimensions of
your browser. If you navigate of inspect that element in you actual browser
the outputs should match.)

Lets explore the rest of the API:

getHeight

Returns the offset height of the element

var ht = Ext.fly('elId').getHeight();

getWidth

Returns the offset width of the element

var wd = Ext.fly('elId').getWidth();
setHeight

Set the height of the element

Ext.fly('elId').setHeight();

setWidth

Set the width of the element

Ext.fly('elId').setWidth();

getBorderWidth

Gets the width of the border(s) for the specified side(s). Side can be t,
l, r, b or any combination of those to add multiple values. For
example, passing lr would get the border (l)eft width + the border
(r)ight width.

var bdr_wd = Ext.fly('elId').getBorderWidth('lr');

getPadding

Gets the width of the padding(s) for the specified side(s). Side can be
t, l, r, b or any combination of those to add multiple values. For
example, passing lr would get the padding (l)eft + the padding (r)ight

var padding = Ext.fly('elId').getPadding('lr');

clip

Store the current overflow setting and clip overflow on the element -
use unclip to remove

Ext.fly('elId').clip();
unclip

Return clipping (overflow) to original clipping before clip() was called

Ext.fly('elId').unclip();

isBorderBox

True if the detected browser is Internet Explorer running in non-strict


mode.

if (Ext.isBorderBox) {
// do something
}

Positioning

Through Ext Core's positioning API it's a snap to get and set all aspects of an
element's position across all browsers. Similar to the dimension API, most of
the setters support animations, either through a boolean true (for defaults)
or by passing an object-literal configuration object as the second argument.
Lets see an example of what this looks like: Lets see an example of what
this looks like:

// changes the x-coord to 75px and animates with a custom configuration


Ext.fly('elId').setX(75, {
duration : .5, // animation will have a duration of .5 seconds
// will change the content to "finished"
callback: function(){ this.update("finished"); }
});
getX

Gets the current X position of the element based on page coordinates.


Element must be part of the DOM tree to have page coordinates
(display:none or elements not appended return false).

var elX = Ext.fly('elId').getX()

getY

Gets the current Y position of the element based on page coordinates.


Element must be part of the DOM tree to have page coordinates
(display:none or elements not appended return false).

var elY = Ext.fly('elId').getY()

getXY

Gets the current position of the element based on page coordinates.


Element must be part of the DOM tree to have page coordinates
(display:none or elements not appended return false).

var elXY = Ext.fly('elId').getXY() // elXY is an array

setX

Sets the X position of the element based on page coordinates. Element


must be part of the DOM tree to have page coordinates (display:none
or elements not appended return false).

Ext.fly('elId').setX(10)
setY

Sets the Y position of the element based on page coordinates. Element


must be part of the DOM tree to have page coordinates (display:none
or elements not appended return false).

Ext.fly('elId').setY(10)

setXY

Sets the position of the element in page coordinates, regardless of


how the element is positioned. The element must be part of the DOM
tree to have page coordinates (display:none or elements not appended
return false).

Ext.fly('elId').setXY([20,10])

getOffsetsTo

Returns the offsets of this element from the passed element. Both
element must be part of the DOM tree and not have display:none to
have page coordinates.

var elOffsets = Ext.fly('elId').getOffsetsTo(anotherEl);

getLeft

Gets the left X coordinate

var elLeft = Ext.fly('elId').getLeft();


getRight

Gets the right X coordinate of the element (element X position +


element width)

var elRight = Ext.fly('elId').getRight();

getTop

Gets the top Y coordinate

var elTop = Ext.fly('elId').getTop();

getBottom

Gets the bottom Y coordinate of the element (element Y position +


element height)

var elBottom = Ext.fly('elId').getBottom();

setLeft

Sets the element's left position directly using CSS style (instead of
setX).

Ext.fly('elId').setLeft(25)

setRight

Sets the element's CSS right style.

Ext.fly('elId').setRight(15)
setTop

Sets the element's top position directly using CSS style (instead of
setY).

Ext.fly('elId').setTop(12)

setBottom

Sets the element's CSS bottom style.

Ext.fly('elId').setBottom(15)

setLocation

Sets the position of the element in page coordinates, regardless of


how the element is positioned. The element must be part of the DOM
tree to have page coordinates (display:none or elements not appended
return false).

Ext.fly('elId').setLocation(15,32)

moveTo

Sets the position of the element in page coordinates, regardless of


how the element is positioned. The element must be part of the DOM
tree to have page coordinates (display:none or elements not appended
return false).

Ext.fly('elId').moveTo(12,17)
position

Initializes positioning on this element. If a desired position is not


passed, it will make the the element positioned relative IF it is not
already positioned.

Ext.fly('elId').position("relative")

clearPositioning

Clear positioning back to the default when the document was loaded

Ext.fly('elId').clearPositioning()
Ext.fly('elId').clearPositioning("top")

getPositioning

Gets an object with all CSS positioning properties. Useful along with
setPostioning to get snapshot before performing an update and then
restoring the element.

var pos = Ext.fly('elId').getPositioning()

setPositioning

Set positioning with an object returned by getPositioning().

Ext.fly('elId').setPositioning({
left: 'static',
right: 'auto'
})
translatePoints

Translates the passed page coordinates into left/top css values for this
element

// {left:translX, top: translY}


var points = Ext.fly('elId').translatePoints(15,18);

Animations

Ext Core has animation plugins available that give you a robust set of
preconfigured animations that are alredy applied as methods to Ext.Element
so you can do cool things like this:

Ext.fly('slideEl').slideOut('r');

Copy the above code, run it in FireBug and see what happens. You will see
below that Ext has a full set of animations already built for you. Each
animation takes a configuration object literal making it very customizable if
you need more than the default behavior. Perhaps you want to add your own
callback function to fire upon completion of the animation:
Ext.fly('slideEl').slideOut('r', {
callback : function(){
alert('Finished sliding the element out');
}
});

So you can see there are some really powerful animations here.

Animations support 8-way anchoring, so you can choose from 8 different


anchor points to either start or end your animation.
Value Description
tl The top left corner
t The center of the top edge
Value Description
tr The top right corner
l The center of the left edge
r The center of the right edge
bl The bottom left corner
b The center of the bottom edge
br The bottom right corner
Lets explore the API further:

slideIn/slideOut

Slides the element into or out of view. An anchor point can be


optionally passed to set the point of origin for the slide effect. This
function automatically handles wrapping the element with a fixed-size
container if needed. See the Fx class overview for valid anchor point
options. Usage:

// default: slide the element in from the top


el.slideIn();
// default: slide the element out from the bottom
el.slideOut();

// common config options shown with default values


el.slideIn('t', {
easing: 'easeOut',
duration: .5
});
el.slideOut('t', {
easing: 'easeOut',
duration: .5,
remove: false,
useDisplay: false
});
puff

Fades the element out while slowly expanding it in all directions. When
the effect is completed, the element will be hidden (visibility =
'hidden') but block elements will still take up space in the document.
The element must be removed from the DOM using the 'remove' config
option if desired. Usage:

// default
el.puff();

// common config options shown with default value


el.puff({
easing: 'easeOut',
duration: .5,
remove: false,
useDisplay: false
});
switchOff

Blinks the element as if it was clicked and then collapses on its center
(similar to switching off a television). When the effect is completed,
the element will be hidden (visibility = 'hidden') but block elements
will still take up space in the document. The element must be removed
from the DOM using the 'remove' config option if desired. Usage:

// default
el.switchOff();

// all config options shown with default values


el.switchOff({
easing: 'easeIn',
duration: .3,
remove: false,
useDisplay: false
});
highlight

Highlights the Element by setting a color (applies to the background-


color by default, but can be changed using the "attr" config option)
and then fading back to the original color. If no original color is
available, you should provide the "endColor" config option which will
be cleared after the animation. Usage:

// default: highlight background to yellow


el.highlight();

// common config options shown with default values


el.highlight("ffff9c", {
//can be any valid CSS property (attribute) that supports a color
value
attr: "background-color",
endColor: (current color) or "ffffff",
easing: 'easeIn',
duration: 1
});

frame

Shows a ripple of exploding, attenuating borders to draw attention to


an Element. Usage:

// default: a single light blue ripple


el.frame();

// common config options shown with default values


el.frame("C3DAF9", 1, {
duration: 1 //duration of each individual ripple.
// Note: Easing is not configurable and will be ignored if included
});
pause

Creates a pause before any subsequent queued effects begin. If there


are no effects queued after the pause it will have no effect. Usage:

el.pause(1);

fadeIn/fadeOut

Fade an element in (from transparent to opaque). The ending opacity


can be specified using the "endOpacity" config option. Or fade an
element out (from opaque to transparent). The ending opacity can be
specified using the "endOpacity" config option. Note that IE may
require useDisplay:true in order to redisplay correctly. Usage:

// default: fade in from opacity 0 to 100%


el.fadeIn();
el.fadeOut();

// common config options shown with default values


el.fadeIn({
endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
easing: 'easeOut',
duration: .5
});
el.fadeOut({
endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
easing: 'easeOut',
duration: .5,
remove: false,
useDisplay: false
});
scale

Animates the transition of an element's dimensions from a starting


height/width to an ending height/width. Usage:

// change height and width to 100x100 pixels


el.scale(100, 100);

// common config options shown with default values. The height and
width will
// default to the element's existing values if passed as null.
el.scale(
[element's width],
[element's height], {
easing: 'easeOut',
duration: .35
}
);
shift

Animates the transition of any combination of an element's


dimensions, xy position and/or opacity. Any of these properties not
specified in the config object will not be changed. This effect requires
that at least one new dimension, position or opacity setting must be
passed in on the config object in order for the function to have any
effect. Usage:

// slide the element horizontally to x position 200 while changing


// the height and opacity
el.shift({ x: 200, height: 50, opacity: .8 });

// common config options shown with default values.


el.shift({
width: [element's width],
height: [element's height],
x: [element's x position],
y: [element's y position],
opacity: [element's opacity],
easing: 'easeOut',
duration: .35
});
ghost

Slides the element while fading it out of view. An anchor point can be
optionally passed to set the ending point of the effect. Usage:

// default: slide the element downward while fading out


el.ghost();

// common config options shown with default values


el.ghost('b', {
easing: 'easeOut',
duration: .5,
remove: false,
useDisplay: false
});

Complex animations

We can also use the Ext Core animation system to build our own
complex custom animations. Copy the following code into FireBug and
see what it does:

var el = Ext.get('complexEl')
el.animate({
borderWidth: {to: 3, from: 0},
opacity: {to: .3, from: 1},
height: {to: 50, from: el.getHeight()},
width: {to: 300, from: el.getWidth()}
});

Miscellaneous

The following are useful Ext.Element methods which don't fit in the previous
sections but bear mentioning.
focus

Tries to focus the element. Any exceptions are caught and ignored.

el.focus();

blur

Tries to blur the element. Any exceptions are caught and ignored

el.blur();

getValue

Returns the value of the "value" attribute

el.getValue();
el.getValue(true); // parses the value as a number

isBorderBox

True if the detected browser is Internet Explorer running in non-strict


mode

if (Ext.isBorderBox) { }

getAttributeNS

Returns the value of a namespaced attribute from the element's


underlying DOM node.

el.getAttributeNS("","name");
What is a Composite?

"The Composite (Design pattern) allows a group of objects to be treated in


the same way as a single instance of an object." (Wikipedia)
Ext.CompositeElement allows you to work with a collection of zero to many
elements as a single entity. CompositeElement uses the same interface as
Ext.Element simplifying your job as a developer and eliminating the need for
common run-time checks when dealing with a collection.
CompositeElement's are typically retrieved by using the static method
Ext.select. Ext.select uses DomQuery to search the entire document for any
element which matches a particular selector.

For example given the following markup:

<html>
<body>
<div id="first" class="title">Sample A</div>
<div id="second" class="doesNotMatch">Lorem Ipsum</div>
<div id="third" class="title secondCSSCls">Some additional
content</div>
</body>
</html>

We could use the CSS selector '.title' to search the entire page and retrieve
a CompositeElement that contains references to the div's first and third.

var els = Ext.select('.title');

Note: The element third also has an additional CSS class of secondCSSCls.
HtmlElement's can have multiple CSS classes by separating them with a
space. This selector does not require that only title is applied and therefore
both 'first' and 'third' will be returned.

After obtained a CompositeElement we can now work with this collection of


Elements as a single element. For Example, we could then add a CSS class
of error to the collection.
var els = Ext.select('.title');
els.addClass('error');

When you are aware of the location of the elements you want to retrieve
relative to another element on the page you should first obtain a reference
to that element and then search from there. This will make your search
perform faster because it is searching a smaller subset of the entire
document. Let's see what happens when we add an additional div with an id
of 'accordion' wrapping around our first, second and third elements.

<html>
<body>
<div id="accordion">
<div id="first" class="title">Sample A</div>
<div id="second" class="doesNotMatch">Lorem Ipsum</div>
<div id="third" class="title secondCSSCls">
Some additional content
</div>
</div>
</body>
</html>

Since we know that the elements will be within a div with an id of accordion
we can scope our search to only the accordion element.

var accordion = Ext.get('accordion');


accordion.select('title');

Any time that you are aware of the location of the elements within your
markup you should make sure that you scope your search like this to
optimize performance.

Other useful methods of CompositeElement are displayed in this code


sample:

var accordion = Ext.get('accordion');


accordion.select('title');
// firstItem now has an Ext.Element pointing to the first div
var firstItem = accordion.item(0);
// alerts 1 or the second position
alert(accordion.indexOf('third'));
// alerts 2
alert(accordion.getCount());
// Removes the element from the collection and from the DOM
accordion.removeElement('one', true);

Note: Methods which have been removed from CompositeElement which


users of Ext JS may be familiar with: each, first, last, fill, contains, filter.
Ajax Implementation

Ajax Defined

Asynchronous JavaScript and XML (coined AJAX in 2005), is a group of interrelated web development
techniques used to create interactive web applications or rich Internet applications. With Ajax, web
applications can retrieve data from the server asynchronously in the background without interfering
with the display and behavior of the existing page. Data is retrieved using the XHR (XMLHttpRequest)
object. Because of the complexity of handling cross-browser distinctions between XHR
implementations, Ajax frameworks have emerged to abstract these differences into a set of reusable
programming constructs. Within Ext, performing these functions is done within the Ext.Ajax singleton
object.

Ext.Ajax

Ext.Ajax extends the Ext.data.Connection class into a singleton and provides a centralized area to
make Ajax requests with maximum flexibility. By using this singleton, all Ajax requests can be routed
through one class and provide access to all functions, events, and parameters.

Ext.Ajax Events

Ext.Ajax exposes global Ajax events that can be handled on every request.

beforerequest (conn, opts)

Fires before any Ajax request is sent.

requestcomplete (conn, response, opts)

Fires after any Ajax request is completed successfully.

requestexception (conn, response, opts)

Fires if an error HTTP status was returned from the server.

// Example: show a spinner during all Ajax requests


Ext.Ajax.on('beforerequest', this.showSpinner, this);
Ext.Ajax.on('requestcomplete', this.hideSpinner, this);
Ext.Ajax.on('requestexception', this.hideSpinner, this);
Ext.Ajax Properties

Since Ext.Ajax is a singleton, you can set properties for it once and override them at the request
function level only if necessary. Common properties you may want to set are:

method: The default HTTP method to be used for requests. Note that this is case-sensitive
and should be all caps (defaults to undefined; if not set but parms are present will use "POST,"
otherwise "GET.")
extraParams: An object containing properties which are used as extra parameters to each
request made by this object (defaults to undefined). Session information and other data that
you need to pass with each request are commonly put here.
url: The default URL to be used for requests to the server (defaults to undefined). If the
server receives all requests through one URL, setting this once is easier entering it on every
request.
defaultHeaders: An object containing request headers which are added to each request
made by this object (defaults to undefined).

// Default headers to pass in every request


Ext.Ajax.defaultHeaders = {
'Powered-By': 'Ext Core'
};

Ext.Ajax.request

Ext.Ajax.request is the function called to send and receive data to the server via Ajax. Success and
failure functions can also be set up to handle the response returned by the server. Note that these
success/failure functions are asynchronous and will be called back when the server responds, while
this is happening they webpage will continue to operate.

Ext.Ajax.request({
url: 'ajax_demo/sample.json',
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
console.dir(obj);
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
Ext.Updater

Another common use for Ajax is updating elements dynamically on a page without refreshing
everything. The request method exposes an el configuration which will take the response from a
request and set it to the innerHTML of an element. Developers can also use the Ext.TaskMgr to setup
a recurring task to update the element periodically.

Posting a form with Ajax

Use the form configuration to post a form with Ext.Ajax.request

Ext.Ajax.request({
url: 'ajax_demo/sample.json',
form: 'myForm',
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
console.dir(obj);
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
What is DomQuery?

DomQuery provides high performance selector/xpath processing. It works on HTML and XML
documents (if a content node is passed in). DomQuery supports most of the CSS3 selectors spec,
along with some custom selectors and basic XPath. A list of the full CSS3 selector spec can be found
here.

Multiple Selections

You can select multiple sets of at elements with different criteria into a single result set.

// Matches all divs with class foo and all spans with class bar
Ext.select('div.foo, span.bar');

Selection Root

When using a selector, it is possible to specify an optional root node, if it is not specified it will default
to the document body. This can be useful to increase performance, since specifying a root means
there will be possibly less nodes to check.

Ext.get('myEl').select('div.foo');// These are equivalent


Ext.select('div.foo', true, 'myEl');// These are equivalent

Selection Chaining

Selectors can be chained to match multiple criteria, which is useful if you need to execute a complex
query. Chained attributes are processed in order

// Matches a div with a class of foo, that has a title attribute bar, that is
// the first child of its immediate parent.
Ext.select('div.foo[title=bar]:first');

Element selectors

* any element
E an element with the tag E
E F All descendent elements of E that have the tag F
E > F or E/F all direct children elements of E that have the tag F
E + F all elements with the tag F that are immediately preceded by an element with the
tag E
E ~ F all elements with the tag F that are preceded by a sibling element with the tag E

// Matches all div elements


Ext.select('div');
// Matches all span elements contained inside a div at any level
Ext.select('div span');
// Matches all li elements with a ul as their immediate parent
Ext.select('ul > li');

Attribute selectors

E.foo has a class "foo"


E[foo] has an attribute "foo"
E[foo=bar] has an attribute "foo" that equals "bar"
E[foo^=bar] has an attribute "foo" that starts with "bar"
E[foo$=bar] has an attribute "foo" that ends with "bar"
E[foo*=bar] has an attribute "foo" that contains the substring "bar"
E[foo%=2] has an attribute "foo" that is evenly divisible by 2
E[foo!=bar] has an attribute "foo" that does not equal "bar"

// Matches all div elements with the class news


Ext.select('div.news');
// Matches all a elements with an href that is http://extjs.com
Ext.select('a[href=http://extjs.com]');
// Matches all img elements that have an alt tag
Ext.select('img[alt]');

Pseudo selectors

E:first-child E is the first child of its parent


E:last-child E is the last child of its parent
E:nth-child(n) E is the nth child of its parent (1 based as per the spec)
E:nth-child(odd) E is an odd child of its parent
E:nth-child(even) E is an even child of its parent
E:only-child E is the only child of its parent
E:checked E is an element that is has a checked attribute that is true (e.g. a radio or
checkbox)
E:first the first E in the resultset
E:last the last E in the resultset
E:nth(n) the nth E in the resultset (1 based)
E:odd shortcut for :nth-child(odd)
E:even shortcut for :nth-child(even)
E:contains(foo) E's innerHTML contains the substring "foo"
E:nodeValue(foo) E contains a textNode with a nodeValue that equals "foo"
E:not(S) an E element that does not match simple selector S
E:has(S) an E element that has a descendent that matches simple selector S
E:next(S) an E element whose next sibling matches simple selector S
E:prev(S) an E element whose previous sibling matches simple selector S

// Matches the first div with a class of code


Ext.select('div.code:first');
// Matches spans that fall on an even index.
Ext.select('span:even');
// Matches all divs whos next sibling is a span with class header.
Ext.select('div:next(span.header));

CSS value selectors

E{display=none} css value "display" that equals "none"


E{display^=none} css value "display" that starts with "none"
E{display$=none} css value "display" that ends with "none"
E{display*=none} css value "display" that contains the substring "none"
E{display%=2} css value "display" that is evenly divisible by 2
E{display!=none} css value "display" that does not equal "none"
DomHelper

DomHelper (abbreviated DH) is a utility class used to dynamically generate


markup and works around many cross-browser issues encountered when
creating markup using raw DOM scripting. DH is intelligent enough to use
HTML Fragments and innerHTML where appropriate to optimize speed
without sacrificing compatibility. Since Ext.DomHelper is a singleton, all its
methods can be accessed statically without instantiating a new instance of
the class.

Ext.DomHelper is a singleton. Therefore you can access all of its methods


statically without instantiating a new instance of the class.

markup
Same as the deprecated createHtml
insertHtml
insertBefore
insertAfter
insertFirst
append
overwrite
DOM Scripting Ext.DomHelper

var myEl = document.createElement('a');


Ext.DomHelper.app
myEl.href = 'http://www.yahoo.com/';
id:
myEl.innerHTML = 'My Link';
myEl.setAttribute('target', '_blank');

href: 'htt
var myDiv = document.createElement('div');
htm
myDiv.id = 'my-div';
tar

myDiv.appendChild(myEl);
document.body.appendChild(myDiv);
DomHelper Configurations

When dynamically generating markup with Ext.DomHelper, a DomHelper


configuration is used to specify what markup to create and place in the
page. A DomHelper configuration is a representation of any arbitrary
HTMLElement to be created on the page.

Markup DomHelper Configuration

t
<a href="http://www.extjs.com">Ext JS</a> href: 'http
htm

Template

Tpl, formatting functions, static method from (importance of textarea)

Template member methods

Adding & executing member formatting functions


About JS Augmentation

Javascript is a flexible lanaguage and it allows the programmer to add


functions to existing base objects within Javascript. The reason for doing this
is because there are a number of functions that are extremely useful to use
on the base object, however they are either not implemented at all, or only
implemented in certain browsers. When using multiple libraries, they may
both implement functions on the base javascript objects. This overlap has
the potential to cause conflicts when using these libraries together. For this
reason, Ext adds only a few necessary functions onto the base objects. Here
is an interesting comparison about different libraries and their javascript
augmentation usage: Framework Scanner

Function Augmentation

The following functions have been added to the Function prototype (note
that createSequence and createInterceptor have not been included):

createCallback

Creates a callback function that can pass a series of arguments. These


arguments can be dynamic and defined at runtime. This function
ignores scope, if it's required you should use createDelegate.
createCallback passes all the arguments passed to itself to the callback
function.

var sayHello = function(firstName, lastName){


alert('Hello ' + firstName + ' ' + lastName);
};
Ext.get('myButton').on('click', sayHello.createCallback('John',
'Smith');

createDelegate

This is similar to createCallback, however is slightly more powerful. It


allows you to specify the scope that the function executes in. It also
gives more control about the arguments that are passed to the
callback function, especially if there are existing arguments for the
event. The first parameter is the scope. The second parameter is an
array of arguments to pass. The third parameter allows you to control
how the arguments are passed. If true, it means append the
arguments to the end of any arguments passed already (say in the
case of an event object). If false, it means just pass the argument
array, nothing else. If it's an integer, the arguments will be inserted at
that specific index.

var sayHello = function(firstName, lastName, e){


alert('Hello ' + firstName + ' ' + lastName);
};
Ext.get('myButton').on(
'click',
sayHello.createDelegate(this, ['John', 'Smith'],
//0 indicates we want to insert our arguments before any others.
0
);

defer

defer allows you to specify a time period to wait before executing a


function. The first argument is the amount of time, in milliseconds to
wait. The second argument is the scope in which to execute the
function.

var whatsTheTime = function(){


alert(new Date());
};
whatsTheTime.defer(3000); //Wait 3 seconds before executing.
Array Augmentation

The following methods are added to the Array prototype, if and only if they
are not already implemented by the browser:

indexOf

Finds the first index in the array that matches the passed in
parameter. If not found in the array, -1 is returned.

var idx = [1, 2, 3, 4, 5].indexOf(3); //Returns 2.

remove

Removes the first instance of the passed argument from the array, if
found. Note that this modifies the array.

var arr = [1, 2, 3, 4];


arr.remove(2);
var len = arr.length; // len is now 3.
String Augmentation

The String class has a single format method added. Note that it may conflict
when using Ajax.NET.

format

Allows you to define a tokenized string and pass an arbitrary number


of arguments to replace the tokens. Each token must be unique, and
must increment in the format {0}, {1}.

var s = String.format(
'Hey {0} {1}', how are you?',
'John',
'Smith'
);
//{0} is substituted with John, {1} is substituted with Smith.
About Utilities

Ext provides a series of general utility functions for working with Javascript
and JSON. They vary in their functionality, but all of them aim to make your
life as the developer easier.

apply and applyIf

apply

The apply function is used to copy the properties of one object literal
to another. The first argument is the destination object. The second
argument is the source to copy from. Note that all properties in the
source will be copied over, even if they exists in the destination. Also,
the destination object will be modified as a result of calling the
method.

var person = {
name: 'John Smith',
age: 30
};

Ext.apply(person, {
hobby: 'Coding',
city: 'London'
}); // person literal now contains hobby and city as well

applyIf

This function is very similar to apply. The only difference is that applyIf
only copies properties that don't exist in the destination object. If they
already exist in both, the destination object takes precedence and the
property is not copied.

var person = {
name: 'John Smith',
age: 30,

hobby: 'Rock Band'


};

Ext.applyIf(person, {
hobby: 'Coding',
city: 'London'
}); // hobby is not copied over

Url Encoding/Decoding

These methods are useful for transforming JSON data to a format that can
be transmitted as part of a GET string and vice versa.

urlEncode

Converts an object-literal into a string that can be passed as a


parameter using a GET request. The string will be in the format
key1=value1&key2=value2....

var params = {
foo: 'value1',
bar: 100
};

var s = Ext.encode(params); // s is now foo=value1&bar=100


urlDecode

This method is the opposite of urlEncode. It takes a string in the form


of key1=value1&key2=value and converts it into a JavaScript object.

var s = 'foo=value1&bar=100';
var o = Ext.decode(s); // o now contains 2 properties, foo and bar.
alert(o.bar);

Array Handling

The core provides methods for working with arrays and other collections
within Javascript.

each

The each method allows you to iterate over an array or other


collections (including Nodelists or CompositeElements). eac takes a
function as the first argument. This function is called for each member
in the collection. Returning false at any point stops iteration.

Ext.each([1, 2, 3, 4, 5], function(num){


alert(num);
});

toArray

This method converts an iterable collection (or single element) into an


proper javascript array.

var arr1 = Ext.toArray(1); // arr1 = [1];


// arr2 now contains an array of Ext elements.
var arr2 = Ext.toArray(Ext.select('div));
JSON

JSON stands for Javascript Object Notation. It is used as a data exchange


format, where the data looks very similar to javascript object literals. When
sending and retrieving data from the server, it is necessary to convert data
to and from it's native javascript form. These helper functions assist you to
do this. More information about JSON can be found at json.org.

encode

Takes a javascript object or array and encodes it as the string


representation of the JSON that can be passed to an external source.

var s = Ext.encode({
foo: 1,
bar: 2
}); //s now contains '{foo=1,bar=2}'

decode

The opposite of encode, this is used to convert the string


representation of JSON into a javascript object. This method is often
called when reading the response from an Ajax callback.

var s = '{foo=1,bar=2}';
var o = Ext.decode(s); o is now an object with 2 properties, foo and
bar.
Browser & OS Detection

JavaScript
Ext offers a number of browser-detection features allowing developers to
work around implementation issues due to differences between the major
browsers. Ext provides detection in both javascript and css, to allow for
greater functionality in both these areas.

The following browser detection is available for javascript:

Internet Explorer - Ext.isIE, Ext.isIE6, Ext.isIE7, Ext.isIE8


Firefox - Ext.isGecko, Ext.isGecko2, Ext.isGecko3
Opera - Ext.isOpera
Chrome - Ext.isChrome
Safari - Ext.isSafari, Ext.isSafari2, Ext.isSafari3
WebKit - Ext.isWebKit
Operating Systems - Ext.isLinux, Ext.isWindows, Ext.isMac

if(Ext.isIE){
// Do browser specific code here
}
CSS
A similar mechanism is applied in the CSS, various class names are added to
the root element and the body depending on the current operating
environment. This allows for easier style rules to get around browser quirks.
If in strict mode, ext-strict is added to the root. The rest of these are added
to the body when appropriate:

.ext-ie, .ext-ie6, .ext-ie7, .ext-ie8


.ext-gecko, .ext-gecko2, .ext-gecko3
.ext-opera
.ext-safari
.ext-chrome
.ext-mac, .ext-linux

/* When in strict mode and using safari, change the font-size. */


.ext-strict .ext-safari .sample-item{
font-size: 20px;
}
Type Detection

Since JavaScript is a loosely typed language, it is often necessary to


interrogate variables to retrieve their type. Ext provides a series of methods
for help in this regard:

isEmpty

Checks whether the passed value is empty, which includes undefined,


null or an empty string.

alert(Ext.isEmpty(''));

isArray

Checks whether the passed value is an array.

alert(Ext.isArray([1, 2, 3]));

isObject

Checks whether the passed value is an object.

alert(Ext.isObject({}));

isFunction

Checks whether the passed value is a function.

alert(Ext.isFunction(function(){
}));
Miscellaneous

id

Returns a string that contains a unique identifier. Any call to Ext.id() is


guaranteed to return a new id that hasn't been used. The first
parameter is an optional element, which the id is to be assigned to.
The second optional parameter is a prefix for the id.

var s = Ext.id(null, 'prefix'); // No element specified here


var s = Ext.id(Ext.get(document.body)); // Assign the id to an element

TaskMgr & TaskRunner

The TaskRunner class is used to execute a function at a specified interval. This is useful when doing
polling type operations, for example when reloading Ajax content every 30 seconds. The TaskMgr
object is a singleton instance of TaskRunner, it can be used for quick access to a TaskRunner.

var stop = false;


var task = {
run: function(){
if(!stop){
alert(new Date());
}else{
runner.stop(task); // we can stop the task here if we need to.
}
},
interval: 30000 // every 30 seconds
};
var runner = new Ext.util.TaskRunner();
runner.start(task);

// Using TaskMgr
Ext.TaskMgr.start({
run: function(){
},
interval: 1000
});
DelayedTask

The DelayedTask class provides a convenient way to "buffer" the execution of a method. When called,
the task will wait the specified time period before executing. If durng that time period, the task is
called again, the original call will be cancelled. This continues so that the function is only called a
single time for each iteration. This method is especially useful for things like detecting whether a user
has finished typing in a text field.

var task = new Ext.util.DelayedTask(function(){


alert(Ext.getDom('myInputField').value.length);
});
// Wait 500ms before calling our function. If the user presses another key
// during that 500ms, it will be cancelled and we'll wait another 500ms.
Ext.get('myInputField').on('keypress', function(){
task.delay(500);
});

Note that we are using a DelayedTask here to illustrate a point. The configuration option buffer for
addListener/on will also setup a delayedtask for you to buffer events.
Class System
JavaScript Classes

Javascript is prototype based, meaning that it differs from typical class


based programming languages. In javascript, creating new classes is done
by modifying the prototype of an object. Ext provides a number of functions
that make it simple to create and work with classes. There is a good
discussion on various javascript-based inheritance functions here.

Ext.extend

Ext provides a series of functions to extend or override existing javascript


classes. This means you can add behaviours and create your own classes, or
override the behaviour of a select few functions to suit your needs.

extend

Creates a new class definition. The first argument is the class to


extend. The second parameter is a list of properties/functions to add
to the prototype of the object. When using extend, Ext keeps a
reference to the superclass, as shown in the second example.

Person = Ext.extend(Object, {
constructor: function(first, last){
this.firstName = first;
this.lastName = last;
}

getName: function(){
return this.firstName + ' ' + this.lastName;
}
});
Developer = Ext.extend(Person, {
getName: function(){

if(this.isCoding){
return 'Go Away!';
}else{
// Access the superclass getName method
return Developer.superclass.getName.call(this);
}
}
});

var p = new Person('John', 'Smith');


alert(p.getName());

override

Similar to extend, however override doesn't create a new class


definition. Instead it just changes the behaviour of the existing class.
The first parameter is the class to override, the second parameter is
the list of properties/functions to add t othe prototype of the object.

// Assumes we've declared our Person class above.


Ext.override(Person, {
getName: function(){
// Override the behaviour, return the last name first.
return this.lastName + ' ' + this.firstName;
}
});
Things that go in the prototype are shared

When placing items in the prototype of the prototype, they will be shared
across all instances of the class. Unless you specifically want to do this, you
should only put "primitive" types inside the prototype definition.

MyClass = Ext.extend(Object, {
// This object literal is now shared between all instances of MyClass.
baseParams: {},

foo: function(){
this.baseParams.bar = 'baz';
}
});

Ext.onReady(function(){

var a = new MyClass();


var b = new MyClass();

a.foo();
// Modifying baseParams in a affects baseParams in b.
console.log(b.baseParams);
});
Singletons

Otherwise known as the module design pattern this pattern allows you to
create private JS Variables or methods through the clever use of closures.
The singleton is a good pattern to use when you you have a class of static
methods, or you have a class that will only be used once. A good candidate
for a singleton is the entry point into your application.

MyApp = function(){
var data; data is private and can't be accessed from outside.
return {
init: function(){
// Initialize application here
},

getData: function(){
return data;
}
};
}();
Ext.onReady(MyApp.init, MyApp);
Ext.util.Observable

The Observable (or subscriber) pattern is used to decouple objects that need
to know details about the state of other objects. It does this by using
events. When the state of the subject changes, the subject will fire an event.
Subscribers to that particular event on the subject will then be notified that
the state change has occurred. Many Ext classes extend Observable to allow
for a flexible, decoupled programming model. You can easily create classes
that fire custom events:

var MyClass = Ext.extend(Ext.util.Observable, {


constructor: function(config){
this.addEvents('datachanged'); // specify the events we're going to
fire
MyClass.constructor.call(this, config);
},

update: function(){
// do some data transformation here
// When firing an event, we can specify what parameters are
// passed to the subscribers.
this.fireEvent('datachanged', this, this.data.length);
}
});

// To subscribe to an event
var c = new MyClass();
c.on('datachanged', function(obj, num){
// react to the data changed event.
});
Namespaces

Namespaces are useful for organizing your code, they provide 2 main
benefits. The first is that you can use them to prevent polluting the global
namespace with objects, which is generally considered to be undesireable.
Ext, for example has just a single global object (the Ext object). It's good
practice to put any classes inside a namespace, a common one is the name
of your company or the name of your application. The other advantage is
that assists in keeping your code organized, you can group together similar
or co-dependent classes in the same namespace, which helps to specify your
intent to other developers.

// The following are equivalent, the latter is preferred.


Ext.namespace(
'MyCompany',
'MyCompany.Application',
'MyCompany.Application.Reports'
);
Ext.namespace('MyCompany.Application.Reports');