• 沒有找到結果。

Some old-school methods

在文檔中 Second Edition (頁 108-113)

Creating Markup on the Fly

What this chapter covers:

• A quick look at the “old-school” techniques: document.write and innerHTML

• An in-depth look at the DOM methods createElement, createTextNode, appendChild, and insertBefore

• An introduction to Ajax and asynchronous requests

Most of the DOM methods you’ve seen so far are useful for identifying elements. Both

getElementById and getElementsByTagName allow you to quickly and easily target specific element nodes in a document. These elements can then be manipulated using methods and properties like

setAttribute (to change the value of an attribute) or nodeValue (to change the text contained by an element node). That’s how the image gallery works. The showPic function identifies two elements, with the IDs "placeholder" and "description", and then updates their contents. The src attribute of the

"placeholder" element is changed using setAttribute. The text within "description" is changed using nodeValue. In both cases, changes are being made to elements that already exist.

This is the way that the majority of JavaScript functions work. The structure of the web page is created with markup. JavaScript is then used to change some of the details without altering the underlying structure. It is also possible to use JavaScript to change the structure and contents of a web page. In this chapter, you’ll learn about some DOM methods that can alter the structure of a web page by creating new elements and modifying existing ones.

Some old-school methods

Before we look at DOM methods for adding markup to a document in the web browser, let’s briefly review a couple techniques that developers have used in the past: document.write and innerHTML.

document.write

The write method of the document object provides a quick and easy way to insert a string into a document. Let’s see how this works.

Save the following markup as a file. Call it something like test.html.

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8" />

<title>Test</title>

</head>

<body>

<script>

document.write("<p>This is inserted.</p>");

</script>

</body>

</html>

If you load test.html in a web browser, you will see a paragraph of text that reads This is inserted.

The major drawback to using document.write is that it goes against the principle of unobtrusive JavaScript. Even if you place the document.write statement in an external function, you’ll still need to insert <script> tags into the body of your markup in order to call the function in the location where you want the write to occur.

The following is a function that takes a string as its argument. This function concatenates an opening <p> tag, the string, and a closing </p> tag. This concatenated string is stored in a variable called str, which is then written out.

function insertParagraph(text) { var str = "<p>";

str += text;

str += "</p>";

document.write(str);

}

You can store this function in an external file called example.js. In order to call this function, you need to insert <script> tags into your markup:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8" />

<title>Test</title>

</script>

</head>

<body>

<script src="example.js">

<script>

insertParagraph("This is inserted.");

</script>

</body>

</html>

Mixing up JavaScript and markup like this is a bad idea. Editing the markup becomes trickier, and the benefits of separating behavior from structure are lost.

You could also very easily introduce validation errors. For instance, in the first example, it appears as though a <p> tag has been opened after a <script> tag, which is invalid. In fact, the <p> and </p> form part of the string being inserted into the document.

If you are writing XHTML documents that are being served up with the MIME type application/xhtml+xml, then document.write simply won’t work.

In some ways, using document.write is a bit like using <font> tags to specify font size and color. Both techniques work fine in HTML documents, but neither of them is very elegant.

It’s always a good idea to separate structure, behavior, and style. It’s much better to specify and maintain styling information by using external CSS files instead of <font> tags. It’s also much better to control behavior with external JavaScript files. You should avoid cluttering your markup with <script>

tags in your <body>. That rules out using document.write.

innerHTML

Most browsers today include support for a property called innerHTML. This property is not part of the DOM specification from the W3C, although it has been included in the current HTML5 specification. It was first introduced by Microsoft, in Internet Explorer 4, and has since been adopted by other browsers.

innerHTML can be used to read and write the HTML in an element. To see how this works, insert the following piece of markup into the <body> of test.html:

<div id="testdiv">

<p>This is <em>my</em> content.</p>

</div>

This is how the DOM sees the markup inside "testdiv".

The div element with the id attribute "testdiv" contains an element node—the p element. This p element, in turn, has a number of child nodes. There are two text nodes. These text nodes have the values This is and content. There’s also an element node, em, which itself contains a text node with the value my.

The DOM provides a very detailed picture of the markup. Using DOM methods and properties, you can access any of those nodes individually. The innerHTML property takes a much simpler view. As shown in the following diagram, it sees the markup inside "testdiv" as a string of HTML with the value <p>This is <em>my</em> content.</p>.

You can test this by updating example.js with a new function, as follows:

window.onload = function() {

var testdiv = document.getElementById("testdiv");

alert(testdiv.innerHTML);

}

Refresh test.html in a web browser. You will see an alert box with the innerHTML value of "testdiv".

Clearly, innerHTML doesn’t offer the fine detail that you can get from DOM methods and properties.

Using the standardized DOM is like using a scalpel. Using innerHTML is like using a sledgehammer.

There are times when you might want to use a sledgehammer. If you have a chunk of HTML that you would like to insert verbatim into a web page, innerHTML can do that. It is a read/write property, which means you can use it not only to get the HTML inside an element, but also to set the HTML inside an element.

Edit the test.html file so that the element with the id value of "testdiv" is empty:

<div id="testdiv">

</div>

If you put this JavaScript into example.js, you can insert a chunk of HTML into the <div>:

window.onload = function() {

var testdiv = document.getElementById("testdiv");

testdiv.innerHTML = "<p>I inserted <em>this</em> content.</p>";

}

To view the result, refresh test.html in a web browser.

This technique makes no distinction between inserting a chunk of HTML and replacing a chunk of HTML. It doesn’t matter whether or not the testdiv element has HTML inside it. Once you use innerHTML, its entire contents will be replaced.

In the test.html file, change the contents of the element identified as "testdiv" back to the original version:

<div id="testdiv">

<p>This is <em>my</em> content.</p>

</div>

Leave the example.js file as it is. If you refresh test.html in a web browser, the result will be the same as before. The HTML contained within the testdiv element has been set by innerHTML. The HTML that was previously there has been obliterated.

The innerHTML property can be quite useful when you want a quick and easy way to insert a chunk of HTML into a document. Unfortunately, innerHTML doesn’t return any references to the content you insert. If you want to manipulate the inserted content, you’ll need the precision offered by DOM methods.

innerHTML compares favorably to document.write. Using innerHTML, you can keep your JavaScript separate from your markup. There’s no need to insert <script> tags throughout your markup.

Like document.write, innerHTML is HTML-specific. You won’t be able to use it on any other kind of markup document. That means if you are serving up XHTML with the correct MIME type, innerHTML won’t work.

In any case, the standardized DOM can be used instead of innerHTML. It may take slightly more code to achieve the same results, but as you’ll see, it offers more precision and power.

在文檔中 Second Edition (頁 108-113)