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

Practical prototype and scipt.aculo.us part 14 pps

6 160 0
Tài liệu đã được kiểm tra trùng lặp

Đ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

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

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

Trang 1

You might recognize this pattern from Element#setStyle, discussed earlier in the chapter

There’s only one gotcha: classand forare 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>

Trang 2

<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 classof numbergets right-aligned (so

that all the digits line up); anything with a classof code gets center-aligned

Figure 6-2.A simple, contrived data table

Drop this code into your index.htmlfile We’re done with the breakfast log, sadly, so

you can clear that stuff out, but leave the scripttag 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 htmltag in your markup And from there the tree branches to reflect the complex

rela-tionships of nodes in the document A tablenode branches into theadand tbody;tbody

branches into several trs; each of those trs branches into several tds

Now imagine you’re a lowly tdtag 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 parentNodeproperty

td.parentNode; //-> <tr>

Trang 3

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 tableelement 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 tdwith 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 upand nextreturn the parent node and the next sibling, respectively Calls to downand previousreturn nullbecause 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 nextSiblingproperty

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

Trang 4

This time, we get results in all four directions: nextand previouspoint to table rows 1

and 3, while upand downpoint 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#selectorworks 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]

Trang 5

The ancestors, descendants, and immediateDescendants Methods

These methods correspond to the groups searched by Element#upand Element#down:

• ancestorsreturns all ancestors of the node, starting with its parent node and end-ing with the htmlelement

• descendantsreturns all element descendants of the node in depth-first order This

is equivalent to calling getElementsByTagName('*')in the node’s scope

• immediateDescendantsreturns all element children of the node in the order they appear This is equivalent to the element’s childNodesproperty—but with all text nodes filtered out (childrenwould 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#previousand Element#next:

• previousSiblingsand nextSiblingsreturn 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 previousSiblingswill return a

collection in reverse DOM order.

• siblingsreturns the union of previousSiblingsand nextSiblingsarranged in DOM order This collection does not include the original node itself This is equivalent to calling immediateDescendantson 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 Elementconstructor 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—

Trang 6

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 trits 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#insertwith 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');

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