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.

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.

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:

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:

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:

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.

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:

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:

Advanced Event Handling

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

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:

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"); }
});

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
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:

Miscellaneous

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