February 28, 2011

Manipulating DOM elements and styles

Manipulating elements
Once you have access to an element, you can manipulate it using assignment of object properties or DOM methods. Let's take a look at the examples:

HTML
<img src="small-dog.png" id="img-dog">
JavaScript
var myImage = document.getElementById('img-dog');

// Object property
myImage.src = 'big-dog.png';

// DOM method
myImage.setAttribute('src', 'big-dog.png');

In both examples we're changing the src of our image element. It's recommended to use the first example, it's easier, shorter, faster and works across browsers. If, for some reason, you can't use it, use the second one. Here's a link to quirksmode.org with more information.



Style
You can also change an element's style dynamically . You can do so by changing the className property or applying a style directly into the style object.

HTML
<span id="my-span">Some text here</span>
JavaScript
var mySpan = document.getElementById('my-span');

mySpan.className = 'big'; // the CSS class 'big' makes the text big
mySpan.style.textAlign = 'center'; // centers the text

Both, className and style, are read/write. But, the style object will only reflect styles that are directly applied to the element (i.e. in the markup), not the ones from the cascade. To get those you need go a little bit further:

HTML
<span id="my-span">Some text here</span>
CSS
#my-span { font-weight: bold; }
JavaScript
var mySpan = document.getElementById('my-span');

mySpan.style.fontWeight; // returns an empty string
mySpan.currentStyle['fontWeight']; // returns 'bold', works only in IE
document.defaultView.
        getComputedStyle(mySpan, null).
        getPropertyValue('font-weight'); // returns 'bold', doesn't work in IE
As you can see:

  • The CSS property on the style object didn't have anything and returned an empty string.
  • IE's proprietary method is very nice and readable (you could also use the dot notation, e.g. mySpan.currentStyle.fontWeight).
  • The standard way is very verbose and complicated but works on all standards compliant browsers.
If you need to get styles individually I suggest creating a utility function to deal with the cross browser issues (an example from quirksmode.org).
But in general, I recommend using CSS classes for dynamic styling. It is way easier and faster to add/modify/delete CSS classes. It's a style agnostic practice, in case you don't have control over the styles, and also encourages layer separation.

Thanks for reading and let me know your comments.

Source: Douglas Crockford: "Theory of the Dom" (2 of 3)

February 7, 2011

The script tag and the DOM

Today I'm going to talk about the DOM. Things you might not know, tricks, nuances and some best practices (I think). So, let's get to it.

The <script> tag
It first appeared in Netscape Navigator 2 as a way to put programs in HTML documents and it then became part of the HTML standard in version 4.
<script type="text/javascript">...</script>



<!-- // -->
The <!-- // --> hack was a workaround to prevent HTML documents from displaying code on the page by older browsers like Mosaic. You can still see this pattern in pages but it's no longer necessary as today's browsers understand both the script tag and JavaScript.
<script type="text/javascript">
<!--
  code here
// -->
</script>



The language attribute
Microsoft came up with it as a way to select what kind of language (e.g. VBScript) you wanted to use for your program. The W3C deprecated this in favor of the type attribute. Avoid the language attribute.
<script language="javascript" type="text/javascript">...</script>



The src attribute
It allows you to load a script from an external file. Great, because you don't want to put JavaScript in your HTML, for a large number of reasons: it makes the HTML file heavier, it becomes less maintainable, it becomes less scalable, it's not cachable, it becomes hard to minify or inspect, etc. It is highly recommended that you do not write JavaScript in your HTML and instead use the src attribute.
<script type="text/javascript" scr="js/script.js"></script>



The type attribute
The W3C added the type attribute to replace the language one. It takes a MIME type instead of the name of the language. The official MIME type for JavaScript is application/javascript or application/ecmascript and the most up to date browsers understand this, but not IE. So, if you want cross-browser support (and you should) you have to use type="text/javascript", at least for now. This is a required attribute for HTML validation, but in practice you can just leave this out, the default language on all major browsers is JavaScript and besides if you're using src, it ignores it.
<script type="text/javascript">...</script>
<script>...</script>
<script type="text/javascript" src="js/script.js">...</script>
<script src="js/script.js">...</script>



Loading time
Because of the way the browser works, loading of a page's assets is incremental and single-threaded, it is recommended that the script tags be placed as low in the body as possible. It is also recommended to place your CSS i.e. link, as high in the head as possible, this will greatly improve the user experience.
You should also minify, gzip and join your script files into one. These will reduce file size and the number of HTTP requests and thus, the time it takes for the browser to load the page.
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="css/styles.css">
    <!-- head contents here -->
  </head>
  <body>
    <!-- body contents here -->
    <script type="text/javascript" src="js/script.js"></script>
  </body>
</html>



document.write
If you call this before the onload event triggers it will insert stuff into your document, but if you do it after it, it destroys your document and replace it with new stuff. You should avoid using document.write, there are better alternatives now.



Collections
  • document.anchors
  • document.applets
  • document.embeds
  • document.forms
  • document.frames
  • document.images
  • document.plugins
  • document.scripts
  • document.stylesheets
Netscape provided these as a way to get and modify elements easier. These are still available but obsolete and you should avoid using them as there are better alternatives now.



The name and id attributes
If an element didn't have an id but it had a name with the same value, you could still get access to it via DOM methods. They used to be interchangeable but they are not anymore.

The HTML:
<input type="text" name="firstname" value="my value">
The JavaScript:
var input = document.getElementById('firstname');
input.value = 'another value'; // sets a value to "firstname" field



document.all
Microsoft came up with this as a type of super collection that contained any tag that had a name or id. Since this is propriety thing and not cross-browser, it is best to not use it.



Some of the topics that I did not cover in this post were browser history, how a browser works and document tree structure. If you're interested, click the link below to watch the video.

Thanks for reading and let me know your comments.

Source: Douglas Crockford: "Theory of the DOM" (1 of 3)