1. Trang chủ
  2. » Công Nghệ Thông Tin

Practical prototype and scipt.aculo.us part 14 pps

6 159 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 6
Dung lượng 93,49 KB

Nội dung

You might recognize this pattern from Element#setStyle, discussed earlier in the chapter. There’s only one gotcha: class and for are reserved words in JavaScript (they have special meaning), so be sure to wrap them in quotes, as in the preceding example. Later in the chapter, you’ll use this pattern as part of a powerful element-creation API. Traversing and Collecting The tasks we’re about to cover could broadly be defined as “getting nodes from other nodes.” Traversal is getting from one node to another; collection is asking for a group of nodes that relates to the node you’re on in some way. Navigating Nodes Since traversal is all about swiftly navigating complex node structures, let’s create a com- plex node structure: <table id="cities"> <caption>Major Texas Cities</caption> <thead> <tr> <th scope="col">Name</th> <th scope="col" class="number">Population (Metro Area)</th> <th scope="col">Airport Code</th> </tr> </thead> <tbody> <tr id="dallas"> <td>Dallas</td> <td class="number">6003967</td> <td class="code">DAL</td> </tr> <tr id="houston"> <td>Houston</td> <td class="number">5539949</td> <td class="code">IAH</td> </tr> <tr id="san_antonio"> <td>San Antonio</td> <td class="number">1942217</td> <td class="code">SAT</td> </tr> CHAPTER 6 ■ WORKING WITH THE DOM128 <tr id="austin"> <td>Austin</td> <td class="number">1513615</td> <td class="code">AUS</td> </tr> <tr id="el_paso"> <td>El Paso</td> <td class="number">736310</td> <td class="code">ELP</td> </tr> </tbody> </table> Nothing too fancy here—just an ordinary data table (see Figure 6-2). But I’ve taken a couple liberties with the styling. Anything with a class of number gets right-aligned (so that all the digits line up); anything with a class of code gets center-aligned. Figure 6-2. A simple, contrived data table Drop this code into your index.html file. We’re done with the breakfast log, sadly, so you can clear that stuff out, but leave the script tag that loads Prototype. The up, down, next, and previous Methods Visualize a DOM tree. The root element, document, is at the top, roughly corresponding to the html tag in your markup. And from there the tree branches to reflect the complex rela- tionships of nodes in the document. A table node branches into thead and tbody; tbody branches into several trs; each of those trs branches into several tds. Now imagine you’re a lowly td tag in the body of our table. You know that your parent node is a tr, and that you’ve got a reference to that table row in your parentNode property. td.parentNode; //-> <tr> CHAPTER 6 ■ WORKING WITH THE DOM 129 You don’t know who your grandparent node is, but you can ask the tr: td.parentNode.parentNode; //-> <tbody> And so on, up the line: td.parentNode.parentNode.parentNode; //-> <table> Tedious, isn’t it? Makes me want to be an orphan. But it’s even worse in the opposite direction: imagine you’re a table element and you want to find one of your td grandchil- dren. The DOM foresees these needs, but addresses them only partially. We need better ways to jump from one node to another, no matter which direction we’re going. With Element#up, Element#down, Element#next, and Element#previous, we have the fine control that the DOM lacks. Each method returns one element in the specified direction. Imagine we’ve got a reference to the td with the content “Houston.” From there, we can traverse with ease: td.up(); //-> <tr> td.next(); //-> <td class="number"> td.previous(); //-> null td.down(); //-> null Calls to up and next return the parent node and the next sibling, respectively. Calls to down and previous return null because no element is found in that direction. ■Note These four methods ignore text nodes entirely. When you call next, you’re asking for the next element sibling, which may not be the same as the node’s nextSibling property. Now let’s jump up one level: var tr = td.up(); tr.up(); //-> tbody tr.next(); //-> tr#san_antonio tr.previous(); //-> tr#dallas tr.down(); //-> td CHAPTER 6 ■ WORKING WITH THE DOM130 This time, we get results in all four directions: next and previous point to table rows 1 and 3, while up and down point to the parent node and the first child node. To repeat, each of these methods returns one result. If there is more than one ele- ment to choose from, it will pick the first one that satisfies its search. These traversal methods become even more useful when given arguments. All four take two types of arguments: A CSS selector string: Checks potential matches against the selector; accepts the same wide range of selectors as $$. A numeric index: Specifies how many matches should be skipped. (Or think of it this way: if all the matches were returned in an array, this would be the index of the one you want.) tr.up('table'); //-> table tr.next(1); //-> tr#austin tr.down('td.code'); //-> td.code tr.down('td', 1); //-> td.number As you can see, both arguments are optional, and the order is flexible. You can pass in an index or a selector as the first argument; but if you pass both, the selector needs to come first. The select Method Don’t forget about our old friend from Chapter 2. $$, the CSS selector function, searches the entire document, but it has an instance-method counterpart ( select) that can search any subset of a DOM tree. Element#selector works like Element#down, except it returns an array of elements. tr.select('.code'); // -> [td.code, td.code, td.code, td.code, td.code] tr.up('table').select('.number'); // -> [th.number, td.number, td.number, td.number, td.number, td.number] tr.up('table').select('td:last-child'); // -> [td.code, td.code, td.code, td.code, td.code] CHAPTER 6 ■ WORKING WITH THE DOM 131 The ancestors, descendants, and immediateDescendants Methods These methods correspond to the groups searched by Element#up and Element#down: • ancestors returns all ancestors of the node, starting with its parent node and end- ing with the html element. • descendants returns all element descendants of the node in depth-first order. This is equivalent to calling getElementsByTagName('*') in the node’s scope. • immediateDescendants returns all element children of the node in the order they appear. This is equivalent to the element’s childNodes property—but with all text nodes filtered out. ( children would be a better name, but Safari uses that property name for something else.) The siblings, previousSiblings, and nextSiblings Methods These methods correspond to the groups searched by Element#previous and Element#next: • previousSiblings and nextSiblings return all the element nodes that come before and after the given node, respectively. The returned collections are ordered based on proximity to the original element, meaning that previousSiblings will return a collection in reverse DOM order. • siblings returns the union of previousSiblings and nextSiblings arranged in DOM order. This collection does not include the original node itself. This is equivalent to calling immediateDescendants on the node’s parent node, and then removing the original node from the returned collection. Creating Nodes Individually, all these methods are simply helpers—convenience methods for repetitive tasks. But when they combine, they form a strong platform that allows for a whole new level of coding. The Element constructor is the Captain Planet of the Prototype DOM extensions—a force greater than the sum of its parts. Think of the example we’ve been using in a specific context. Suppose we were build- ing a site where a user could select any number of cities and compare some of their qualities. To make the UI snappy, we’d load city data via Ajax and stuff it into our compar- ison table dynamically. The data itself has to come from the server, but we can offload some of the easier stuff to the client side. Most of this falls outside the scope of this chapter, but there’s one part we can extract into a simple example. Let’s say we want to build a new row at the bottom of our table— CHAPTER 6 ■ WORKING WITH THE DOM132 one that will add up all the populations of the cities and display a total. In HTML form, the row would look something like this: <tr class="total"> <td>Total</td> <td class="number">15,736,058</td> <td class="code"></td> </tr> We’ll give the tr its own class so we can style it to look different from the other rows. And we’ll leave the last cell empty because it’s not applicable to this row, of course. But now we’ve got to decide between two equally ugly ways of generating this HTML dynamically. We could use Element#insert with a string: var html = "<tr class='total'>"; html += "<td>Total</td>"; html += "<td class='number'>" + totalPopulation + "</td>"; html += "<td class='code'></td>"; html += "</tr>"; $('cities').down('tbody').insert(html, 'bottom'); But I hate building long strings like that. It’s a syntax error minefield. So, we could stick to the DOM way: // First, create the row. var tr = document.createElement('tr'); // We need to "extend" the element manually if we want to use // instance methods. $(tr).addClassName('total'); // Next, create each cell individually. var td1 = document.createElement('td'); td1.appendChild(document.createTextNode('Total')); var td2 = document.createElement('td'); $(td2).writeAttribute('class', 'number'); td2.appendChild(document.createTextNode(totalPopulation)); var td3 = document.createElement('td'); $(td3).writeAttribute('class', 'code'); CHAPTER 6 ■ WORKING WITH THE DOM 133 . class="number"> td.previous(); //-> null td.down(); //-> null Calls to up and next return the parent node and the next sibling, respectively. Calls to down and previous return null because no element. tr#san_antonio tr.previous(); //-> tr#dallas tr.down(); //-> td CHAPTER 6 ■ WORKING WITH THE DOM130 This time, we get results in all four directions: next and previous point to table rows 1 and 3, while up and. but Safari uses that property name for something else.) The siblings, previousSiblings, and nextSiblings Methods These methods correspond to the groups searched by Element#previous and Element#next: • previousSiblings

Ngày đăng: 03/07/2014, 01:20