Three sheets to the Web
Content on the Web can be wrapped up in three successive layers that are readable by
web browsers:
Structure
Presentation
Behavior
The style property
Every element in a document is an object. Every one of these objects has a whole collection
of properties. Some properties contain information about the element’s position in
the node tree. Properties like parentNode, nextSibling, previousSibling, childNodes,
firstChild, and lastChild all supply information about related nodes in the document.
Other properties, like nodeType and nodeName, contain information about the element
itself. Querying the nodeName property of an element will return a string like “p”.
There’s another property called style. Every element node has this property. It contains
information about the styles attached to the element. Querying this property doesn’t
return a simple string; it returns an object. Style information is stored as properties of this
style object:
element.style.property
文本如下:
<p id="example" style="color: grey; font-family: 'Arial',sans-serif;">
An example of a paragraph
</p>
First of all, you need to be able to reference the element. I’ve given the paragraph a
unique id value of “example”. Pass this id to the getElementById method. Assign a variable,
para, so that you have a handle on the element that’s easy to reference:
var para = document.getElementById("example");
Before retrieving any information about the presentation of this element, I want to show
you that the style property is in fact an object. You can use the typeof keyword to
retrieve this information. Compare the results of applying typeof to a property like
nodeName and applying typeof to the style property.
样式属性实际上是一个object(对象)。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Example</title> <script type="text/javascript"> window.onload = function() { var para = document.getElementById("example"); alert(typeof para.nodeName); alert(typeof para.style); } </script> </head> <body> <p id="example" style="color: grey; font-family:'Arial',sans-serif;"> An example of a paragraph </p> </body> </html>
会输出:string 第二个 object
So, not only is every element an object, every element has a property called style, which is also an object.
Getting styles
You can retrieve the styles attached to para. To find out what color has been applied to an
element, use the color property of the style object:
element.style.color
检索字体不能用 element.style.font-family (原因:-会翻译成负号)
The dash between the word “font” and “family” is the same character as the subtraction
operator. JavaScript will interpret this as a minus sign. You will get an error if you
try to retrieve a property called “font-family”:
element.style.font-family
JavaScript will look at everything up to the minus sign as, “The font property of the style
property of the element.” It will then attempt to subtract a variable called family. That
wasn’t your intention at all!
Operators like the minus sign and the plus sign are reserved characters that can’t be used
in function names or variable names. That means they also can’t be used for the names of
methods or properties (remember that methods and properties are really just functions
and variables attached to an object).
The DOM solves this problem by camel-casing骆峰式style properties that have more than one
word. The CSS property “font-family” becomes the DOM property fontFamily:
element.style.fontFamily
The value of the DOM fontFamily property is the same as the CSS “font-family” property.
In this case, it’s
'Arial',sans-serif
The camel-casing convention applies to just about any CSS property that contains one or
more dashes. The CSS property “background-color” becomes the DOM property
backgroundColor. The CSS property “font-weight” is fontWeight in the DOM. The DOM
property marginTopWidth is equivalent to “margin-top-width” in CSS.
Style properties aren’t always returned with the same measurements and units with which
they were set.这点值得注意:
In the example paragraph, the CSS “color” property has been set with the word “grey”. The
DOM color property returns a value of “grey”. Edit the paragraph so that the CSS “color”
property is set with the hexadecimal value #999999:
<p id="example" style="color: #999999; font-family: 'Arial',sans-serif">
Now edit the JavaScript so that the DOM color property is output in an alert statement:
alert("The color is " + para.style.color);
In some browsers, the color property will be returned in RGB (Red Green Blue): 153,153,153:(chrome 就是)
This is an exceptional circumstance. Usually values are returned in the same units with
which they are set. If
Inline only
There’s a big caveat警告 to retrieving stylistic information with the style property.
The style property only returns inline style information.仅仅返回内联 的样式信息 If you apply styling information
by inserting style attributes into your markup, you can query that information using the
DOM style property:
<p id="example" style="color: grey; font: 12px 'Arial',sans-serif;">
This is not a very good way of applying styles. Presentational information is mixed in with
structure. It’s much better to apply styles in an external style sheet:
p#example {
color: grey;
font: 12px 'Arial', sans-serif;
}
Save that CSS in a file called styles.css. Now update example.html, removing the inline
styling to leave the following instead:
<p id="example">
An example of a paragraph
</p>
alert("The font size is " + para.style.fontSize);
The DOM style property doesn’t retrieve styles declared externally。
The DOM style property won’t pick up that information.
The style object doesn’t include stylistic information that has been declared in an external
style sheet. It also doesn’t include stylistic information that has been declared in the
head of a document. dom只会检索inline内联的样式信息。
The style object does pick up stylistic information that has been declared inline using the
style attribute. But this is of little practical use because styles should be applied separately
from the markup.
At this point, you might be thinking that using the DOM to manipulate CSS seems next to
useless. However, there is one other situation where the DOM style object correctly
reflects stylistic information that you have applied. If you apply styles using the DOM, you
will be able to retrieve those styles.
Setting styles
Many DOM properties are read-only. That means you can use them to retrieve information,
but you can’t use them to set or update information. Properties like
previousSibling, nextSibling, parentNode, firstChild, and lastChild are invaluable
for gathering information about an element’s position in the document’s node tree, but
they can’t be used to update information.
The properties of the style object, on the other hand, are read/write. That means you can
use an element’s style property to retrieve information, and you can also use it to update
information. You can do this using the assignment operator: the equals sign:
element.style.property = value
The value of a style property is always a string.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Example</title> <script type="text/javascript"> window.onload = function() { var para = document.getElementById("example"); para.style.color = "black"; } </script> </head> <body> <p id="example" style="color: grey; ➥ font-family: 'Arial',sans-serif;"> An example of a paragraph </p> </body> </html>
The value must be placed within quotes. You can use either double quotes or single
quotes, whichever you prefer:
para.style.color = 'black';
If you don’t use quotes, JavaScript will assume that the value is a variable:
para.style.color = black;
If you haven’t defined a variable called black, the code won’t work.
You can set any style property using the assignment operator. You can even use shorthand
properties like font:
para.style.font = "2em 'Times',serif";
This will set the fontSize property to “2em”
and the fontFamily property to “‘Times’,serif”:
Knowing when to use DOM styling
You’ve seen how easy it is to set styles using the DOM. But just because you can do
something doesn’t mean you should. Nine times out of ten, you should be using CSS to
declare styles. Just as you should never use the DOM to create important content, you also
shouldn’t use the DOM to set the majority of styles for a document.
Occasionally however, you can use the DOM to add some small stylistic enhancements to
documents where it would be unwieldy笨拙的 to use CSS.
css很难做到的(其实也很简单,只不过举个例子)如:“Apply the following styles to the next sibling of all h1 elements.”用dom来做
The DOM, on the other hand, makes it quite easy to target elements based on their familial
relationships with other elements. Using the DOM, you could quite easily find all the h1
elements in a document and then find out what element immediately follows each h1 and
apply styles specifically to those elements.
First of all, get all the h1 elements using getElementsByTagName:
var headers = document.getElementsByTagName("h1");
Loop through all the elements in the node set:
for (var i=0; i<headers.length; i++) {
You can find the next node in the document using nextSibling:
headers[i].nextSibling
But in this case you actually want to find not just the next node, but specifically the next
element node. This is easily done using a function called getNextElement:
function getNextElement(node) { if(node.nodeType == 1) { return node; } if (node.nextSibling) { return getNextElement(node.nextSibling); } return null; }
Pass this function the nextSibling node of an h1 element as the argument. Assign the
result to a variable called elem:
var elem = getNextElement(headers[i].nextSibling);完整代码如下:
function styleHeaderSiblings() { if (!document.getElementsByTagName) return false; var headers = document.getElementsByTagName("h1"); for (var i=0; i<headers.length; i++) { var elem = getNextElement(headers[i].nextSibling); elem.style.fontWeight = "bold"; elem.style.fontSize = "1.2em"; } }
如果我们新建一个table:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Cities</title> <style> body{ background-color:#fff; } table{ margin:auto; border:1px solid #699; } caption{ margin:auto; padding:.2em; font-size:1.2em; font-weight:bold; } th{ font-weight:normal; font-style:italic; text-align:left; border:1px dotted #6999; background-color:#9cc; color:#000; } th,td{ width:10em; padding:0.5em; } </style> </head> <body> <table> <caption>itineray</caption> <thead> <tr> <th>when</th> <th>where</th> </tr> </thead> <tbody> <tr> <td>june 9th</td> <td>Portland, <abbr title="Oregon">OR</abbr></td> </tr> <tr> <td>June 10th</td> <td>Seattle, <abbr title="Washington">WA</abbr></td> </tr> <tr> <td>June 12th</td> <td>Sacramento, <abbr title="California">CA</abbr></td> </tr> </tbody> </table> </body> </html>
想要隔行就改变每行的背景,在css3中可以做到,但是在一些低的浏览器中不兼容。用dom可以方便做到。
Using CSS, there’s no easy way of saying, “Apply a style to every second item in this list.”
JavaScript, on the other hand, is very good at handling repetitive tasks. You can easily loop
through a long list using a while or for loop.
You can write a function to stripe your tables by applying styles to every second row:
1. Get all the table elements in the document.
2. For each table, create a variable called odd set to false.
3. Loop through all the rows in the table.
4. If odd is true, apply styles and change odd to false.
5. If odd is false, don’t apply styles but change odd to true.
Call the function stripeTables. The function doesn’t need to take any arguments, so the
parentheses after the function name will be empty. Don’t forget to start your function by
testing the DOM compliance of the browser:
function stripeTables() { if (!document.getElementsByTagName) return false; var tables = document.getElementsByTagName("table"); for (var i=0; i<tables.length; i++) { var odd = false; var rows = tables[i].getElementsByTagName("tr"); for (var j=0; j<rows.length; j++) { if (odd == true) { rows[j].style.backgroundColor = "#ffc"; odd = false; } else { odd = true; } } } }
Responding to events
想要设置鼠标mouseover和mouseout的效果,如下:
function highlightRows() { if(!document.getElementsByTagName) return false; var rows = document.getElementsByTagName("tr"); for (var i=0; i<rows.length; i++) { rows[i].onmouseover = function() { this.style.fontWeight = "bold"; } rows[i].onmouseout = function() { this.style.fontWeight = "normal"; } } }
className
In the examples you’ve seen so far in this chapter, the DOM has been used to explicitly set
stylistic information. This is less than ideal because the behavior layer is doing the work of
the presentation layer. If you change your mind about the styles being set, you’ll need to
dig down into your JavaScript functions and update the relevant statements. It would be
better if you could make those kinds of changes in your style sheets.
There’s a simple solution. Instead of changing the presentation of an element directly with
the DOM, use JavaScript to update the class attribute attached to that element.
Take a look at how the styleHeaderSiblings function is adding stylistic information:
function styleHeaderSiblings() { if (!document.getElementsByTagName) return false; var headers = document.getElementsByTagName("h1"); for (var i=0; i<headers.length; i++) { var elem = getNextElement(headers[i].nextSibling); elem.style.fontWeight = "bold"; elem.style.fontSize = "1.2em"; } }
It would be better if your style sheet had a declaration for a class named something like
“intro”:
.intro {
font-weight: bold;
font-size: 1.2em;
}
Now all that the styleHeaderSiblings function needs to do is to apply this class to the
element immediately following a level one heading.
You can do this using the setAttribute method.
elem.setAttribute("class","intro"); 还有一个更简单的方案,使用className
An easier solution is to update a property called className. This is a read/write property
of any element node.
You can use className to get the class of an element.
You can do this by concatenating a space and the name of the new class to the className
property:
elem.className += " intro";
我们可以增加一个class,通过+=" 类名“;注意要有一个空格。
Whenever you want to add a new class to an element, you can run through these steps:
1. Is the value of className null?
2. If so, assign the class value to the className property.
3. If not, concatenate a space and the class value to the className property.
You can encapsulate those steps in a function. Call the function addClass. It will need to
take two arguments: the element to which you want to add the class and the name of the
class you want to add. You can call these arguments element and value
function addClass(element,value) { if (!element.className) { element.className = value; } else { newClassName = element.className; newClassName+= " "; newClassName+= value; element.className = newClassName; } }