Taming the browser with the YUI Dom Component

Preview:

DESCRIPTION

A quick introduction to the YUI Dom Component and some of its lesser known parts. This is not really *that* useful without the explanations but there will be a video later on.

Citation preview

Using YUI Dom

to tame the Browser

Christian HeilmannYahoo! F2E Summit Asia 2007

Quick reminder

• Development according to web standards means first and foremost separation.

• Specifically separation of web development layers.

addClass batch generateId get getAncestorBy getAncestorByClassNamegetAncestorByTagName getChildrengetChildrenBy getClientHeightgetClientWidth getDocumentHeightgetDocumentScrollLeftgetDocumentScrollTop getDocumentWidthgetElementsBy getElementsByClassNamegetFirstChild getFirstChildBygetLastChild getLastChildBygetNextSibling getNextSiblingBygetPreviousSibling getPreviousSiblingBygetRegion getStyle getViewportHeightgetViewportWidth getX getXY getYhasClass inDocument insertAfterinsertBefore isAncestor removeClassreplaceClass setStyle setX setXY setY

Use cases for the DOM utility

• Using CSS Classes• Getting elements from the DOM • Using the browser dimensions• Using element dimensions• Styling elements

Using CSS Classes

• addClass()• removeClass()• hasClass()• replaceClass()• getElementsByClassName()

Why?

Why?

• CSS is the supercharged DOM Scripting.• CSS is much closer connected to the

HTML• Therefore it is more likely to change at the

same time.• I hate loops.

Why?

• CSS is the supercharged DOM Scripting.• CSS is much closer connected to the

HTML• Therefore it is more likely to change at the

same time.• I hate loops.

Why?

• CSS is the supercharged DOM Scripting.• CSS is much closer connected to the

HTML• Therefore it is more likely to change at the

same time.• I hate loops.

Why?

• CSS is the supercharged DOM Scripting.• CSS is much closer connected to the

HTML• Therefore it is more likely to change at the

same time.• I hate loops.

Example:

Hiding all “trigger” links in a main section when JS is available.

Example:

var main = document.getElementById('main');if(main){

var triggers = main.getElementsByTagName('a');for(var i=0,j=triggers.length;i<j;i++){

if(triggers[i].className === 'trigger'){triggers[i].style.display = 'none';

}}

}

Example:

var main = document.getElementById('main');if(main){

var triggers = main.getElementsByTagName('a');for(var i=0,j=triggers.length;i<j;i++){

if(triggers[i].className === 'trigger'){triggers[i].style.display = 'none';

} }

}

display:none is a bad plan!

Example:

var main = document.getElementById('main');if(main){

var triggers = main.getElementsByTagName('a');for(var i=0,j=triggers.length;i<j;i++){

if(triggers[i].className === 'trigger'){triggers[i].style.display = 'none';

} }

}

Off-left is better.

Example:

var main = document.getElementById('main');if(main){

var triggers = main.getElementsByTagName('a');for(var i=0,j=triggers.length;i<j;i++){

if(triggers[i].className === 'trigger'){triggers[i].style.position = 'absolute'; triggers[i].style.left = '-6000px';

} }

}

Magic JavaScript Pixy Solution

$('#main a.trigger').hide();

My fave:

document.body.className = 'js';

// or var b = document.body;var bc = b.className;b.className = bc ? bc + ' js' : 'js';

Getting elements from the DOM

• inDocument()• isAncestor()• getElementsByClassName• getElementsBy• get• batch

Using the browser dimensions

• getViewportWidth()• getViewportHeight()• getDocumentWidth()• getDocumentHeight()

Using element dimensions

• getX(), getY(), getXY()• setX(), setY(), setXY()• getRegion()

– Region union– Region intersect – Region contains

Using element dimensions

Using element dimensions

• Each of these methods can take an ID, a reference of an HTMLelement or an array of elements as the parameter.

• This allows you to easily access a lot of elements.

Using element dimensions

• The Dom utility does not care if the element is positioned absolute, relative or static.

• It also sorts out differences in render mode for you.

• However, each element needs to be part of the Dom and not hidden with display:none!

Using element dimensions

• The get and set methods of x and y are very straight forward.

• They return the left, the top or both values in pixels or an array with this data for each element you parsed in.

• You can also set the position in pixels with the setter methods.

Using element dimensions

var xy = YAHOO.util.Dom.getXY('hd');

// = [128, 0];YAHOO.util.Dom.setXY('hd',[128,-

10]);// shifts header 10 pixels up

Using element dimensions

• By using the getRegion() method you can read out the screen estate the element occupies.

• This is incredibly useful for positioning elements or avoiding overlap.

• The return is an object with several properties.

Using element dimensions

var h = YAHOO.util.Dom.getRegion('hd');

// h = // {0:128// 1:0,// top:0,// right:878, // bottom:79, // left:128}

Using element dimensions

• top, left, right, bottom are the pixel locations on the page.

• There are shortcuts for left and top named 0 and 1 to allow for compatibility with setX,setY and setXY.

Using element dimensions

• Using these properties you can also calculate the dimensions of the element.

• Simply subtract left from right for the width.• And top from bottom for the height.

Using element dimensions

• The Region() component does a lot more for you though.

• By calculating the region occupied by two elements, you can find out:– if one element contains the other – how big the area containing both of them is

and– if and where they intersect

Using element dimensions

YD = YAHOO.util.Dom;reg1 = YD.getRegion('r1');reg2 = YD.getRegion('r2');contains = reg1.contains(reg2);

Region #1 Region #2

Using element dimensions

YD = YAHOO.util.Dom;reg1 = YD.getRegion('r1');reg2 = YD.getRegion('r2');contains = reg1.contains(reg2);

false

Region #1 Region #2

Using element dimensions

YD = YAHOO.util.Dom;reg1 = YD.getRegion('r1');reg2 = YD.getRegion('r2');contains = reg1.contains(reg2);

Region #1

Region #2

Using element dimensions

YD = YAHOO.util.Dom;reg1 = YD.getRegion('r1');reg2 = YD.getRegion('r2');contains = reg1.contains(reg2);

true

Region #1

Region #2

Using element dimensions

YD = YAHOO.util.Dom;reg1 = YD.getRegion('r1');reg2 = YD.getRegion('r2');is = reg1.intersect(reg2);

Region #1

Region #2

Using element dimensions

YD = YAHOO.util.Dom;reg1 = YD.getRegion('r1');reg2 = YD.getRegion('r2');is = reg1.intersect(reg2);

Region #1

Region #2

Using element dimensions

YD = YAHOO.util.Dom;reg1 = YD.getRegion('r1');reg2 = YD.getRegion('r2');is = reg1.union(reg2);

Region #1

Region #2

Region #1

Region #2

Using element dimensions

YD = YAHOO.util.Dom;reg1 = YD.getRegion('r1');reg2 = YD.getRegion('r2');is = reg1.union(reg2);

Region #1

Region #2

Region #1

Region #2

Styling elements

• getStyle()• setStyle()

Styling Elements

• You might wonder why you’d need these two methods as seemingly element.style.property = valuewould do the same.

• The two methods however work around several browser problems and differences between computedStyle and currentStyle.

Styling Elements

• The other benefit is that you can use the CSS selector names instead of the camelCased JavaScript ones.

• Furthermore you can use the opacityproperty without needing to branch for different browsers.

CSS normalization

obj.style.marginTop = '10px';

vs.

YAHOO.util.Dom.setStyle(obj, 'margin-top','10px');

CSS normalization

• Furthermore, opacity is not a nightmare any longer:

YAHOO.util.Dom.setStyle(obj, 'opacity','.2');

CSS normalization

• And last but not least, float can be used:

YAHOO.util.Dom.setStyle(obj, 'float','left');

Thanks!