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

JQuery: Novice to Ninja- P23 pdf

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

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 15
Dung lượng 555,98 KB

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

Nội dung

Then we’ll add in a new element before the category title that contains a click event handler—this will open and close its branch:... Delegating events If we added a click event handler

Trang 1

Licensed to JamesCarlson@aol.com

The tree can nest as far as is needed—just repeat the structure inside the appropriate

child list item Because it’s nice and consistent, you can easily generate the HTML

on the server

With the list on the page, the next step is to pretty it up with some CSS That’s in

your court, but our code will add a few extra classes you can use to customize the

display The handle class will be assigned to the element we’ll insert to act as the

toggle handle When a branch of the tree is opened, it’ll receive the opened class;

otherwise it’ll have the closed class We’ve used these classes below to add a CSS

sprite, which will change between a plus sign and a minus sign:

chapter_08/04_expandable_tree/script.js (excerpt)

The code for the tree is remarkably simple, thanks to the recursive nature of a tree:

we just have to do one small piece of code, and attach it to each subcategory Our

plan of attack for creating the expanding/collapsing tree effect is to first hide all of

the nested ul categories Then we’ll add in a new element before the category title

that contains a click event handler—this will open and close its branch:

Trang 2

Licensed to JamesCarlson@aol.com

chapter_08/04_expandable_tree/script.js (excerpt)

Six chained actions Bet you’re feeling some of that jQuery power coursing through

your veins right about now! Here we see where consistent markup helps us out: in

each subcategory list we look for the previous spanelement—that’s the subcategory

title Then we insert a new span element right before the title

Because our handle was added before the title, we need to move back to it with the

prev action We add the handle and closed (it’s closed by default because of the

hide action) classes to it, and an event handler for when it’s clicked

At this stage the tree will be fully collapsed, with our brand-new handle prepended

to the titles All that’s left to do is toggle the branches when we click on it:

chapter_08/04_expandable_tree/script.js (excerpt)

When the handle is clicked, we toggle the closed and opened classes with

toggleClass If you specify multiple classnames with toggleClass, any specified

classthat exists on the element is removed, and any that are absent from the element

are added

Trang 3

Licensed to JamesCarlson@aol.com

Advanced toggleClass

Another neat trick of toggleClass is that it accepts a second parameter: a Boolean value that specifies whether the class should be added or removed This might sound strange, but it’s a nice shortcut Consider this code:

With the toggleClass(class, switch) syntax, we can replace the if statement with the following concise syntax:

Finding the subcategory that we need to open and close is easy, thanks to the nextAll

action jQuery will check the next sibling, see that it’s a span element (the category

title), filter it out based on our expression, and move to the next sibling … which

is a ul item Bingo! We just toggle this and the tree swings open and closed

Event Delegation

Event delegation is a topic that’s applicable everywhere, but is particularly important

if you’re dealing with large trees The idea is that instead of applying individual

event handlers to every node in your tree, you apply a single event handler to inter­

cept the click—and then figure out who the click was aimed at and run the appro­

priate action

If you’ve been following along closely this might sound a bit familiar to you We

covered the live method in the section called “Prepare for the Future: live and

die” in Chapter 6 live handles event delegation for you—that’s the magic that

makes it possible—but it comes with a potential gotcha that you need to be aware

of

To acquire a better understanding of how event delegation works and why it is im­

portant, let’s use it for real We’ll start with the following HTML that displays our

products in a categorized list:

Trang 4

Licensed to JamesCarlson@aol.com

chapter_08/05_event_delegation/index.html (excerpt)

When users clicks on a celebrity, their selection should appear above the list in the

format “category > celebrity” as in Figure 8.4 So what’s the best way to capture this

information?

Figure 8.4 Delegating events

If we added a click event handler to every single list item—$('#picker

li').click(…)—we could end up with hundreds of handlers This would severely

impact performance, as the browser would need to keep track of them all and check

Trang 5

Licensed to JamesCarlson@aol.com

them all whenever a click occurred on the page With event delegation, we add our

lone event handler to the parent of the list, and then access the target of the event

to determine the element that was actually clicked on The target property of an

event is the actual DOM element—so it needs to be wrapped in the jQuery selector

to obtain a jQuery object:

Our list acts as if each item has its own handler! Nice, but what was the gotcha

mentioned earlier? Event delegation works because of event bubbling (which we

looked at in the section called “Event Propagation” in Chapter 5)—the events will

bubble up until our parent handler catches them The problem occurs if a handler

catches the event before the parent and stops the event from propagating (with

e.stopPropagation, or "return false") If the event is stopped on its way up,

event delegation will fail! That’s why it’s important that you know how events are

being handled under the hood—it’ll save you a lot of headaches when dealing with

otherwise incomprehensible bugs

We’ve handled any clicks with a single handler, but we now need to find out a bit

more about where the element is located Specifically, how can we find out which

category the element is in? How about this:

(excerpt)

We’ve asked the closest method to find the closest element with the category

class If the element itself doesn’t have that class, closest will check its parent

… and so on until it finds a matching element This saves us having long strings of

parent().parent().parent(), and also lets us be more flexible in how we structure

our HTML

Trang 6

Licensed to JamesCarlson@aol.com

If HTML lists are the unsung heroes of the new Web, tables are that bad kid who

ends up turning out good The tables themselves were never to blame—we misused

and abused them for years as a hack to lay out our web designs in a reasonable

cross-browser manner But that’s what CSS is for, not poor old tables And now that CSS

has come of age, we can finally return to using tables solely for their original purpose:

displaying tabular data

StarTrackr! has stacks of data to display So much so that it’s growing out of hand:

the tables are becoming overly large and unreadable, the information has no paging

or sorting mechanisms, and there’s no way to edit the information easily We saw

how easy it was to add zebra striping and row highlighting to tables in Chapter 2;

this will give us a few quick wins, but to address the more serious table issues, we’re

going to need some extra help from jQuery

Fixed Table Headers

The header row of a table is of paramount importance: without it, you’d be stuck

with rows of meaningless data But if you’re dealing with a large number of rows,

you’ll find that the headers become less and less helpful, as they scroll out of sight

and out of mind Paging the data generally takes care of the problem—but if you

need to have all the data on one page at the same time, you’ll have to think of another

option

Keeping the header row fixed at the top of the table is an effective way to keep track

of what our columns are about, and it also looks really cool! As the user scrolls the

table to reveal new data, the header follows along You can see this in action in

Figure 8.5

Figure 8.5 Fixed header row

Trang 7

Licensed to JamesCarlson@aol.com

If your table is the only element on the page, position: fixed can be used to affix

the theadelement in place However, position: fixedcan only position an element

relative to the viewport, rather than its containing element This means that for

tables contained inside other elements (which will almost always be the case), we

need to turn to jQuery

Let’s have a look at how we can achieve this effect Our markup is the same

Celebrities table we added zebra-striping to back in Chapter 2:

chapter_08/06_fixed_table_headers/index.html (excerpt)

Moving the thead around is tricky Some browsers let you move it with impunity,

while in others it’s surprisingly resistant to styling So we’ll employ a trick: we’ll

duplicate the contents of the thead in the form of an unordered list, styled to look

exactly like the thead Then we’ll give that position: absolute;, and move it

around the screen as the user scrolls

We start by creating a TABLEwidget to hold our code, with a fixHeadermethod that

we’ll use for our fixed headers effect The method will expect to receive a selector

string pointing at a table on the page We start by storing a few selections inside

variables and in data, to speed up our subsequent code:

Trang 8

Licensed to JamesCarlson@aol.com

chapter_08/06_fixed_table_headers/script.js (excerpt)

➥$thead.height());

We first declare a closure to hold on to our widget’s context Then we select any

tables that match the selector passed in to our method We loop over them with

each, and store a reference to the table itself ($table), the thead ($thead), and the

collection of thelements it contains ($ths) Finally, we store the left and top offsets

of the $thead, as well as the location of the bottom of the table (to avoid the header

moving past the bottom!)

Use each When Writing Selector-based Functions

When writing this sort of utility function, you should always anticipate the pos­

sibility of your selector returning more than one element In this case, our page only has one table on it, so the method would work fine if we omitted the each loop But in the interests of preparing for the future, and making our code reusable, we’ve included the loop anyway; even if the table selector returns multiple tables, our function will handle them all with grace

Next, we create our faux header—a ul—and copy over the contents of the table

header:

Trang 9

Licensed to JamesCarlson@aol.com

chapter_08/06_fixed_table_headers/script.js (excerpt)

With the real th elements collected in $ths, we use an each action to go through

each one and craft our mimics We copy the original elements’ class, HTML con­

tents, width, and click event handlers Some of this is unnecessary in our simple

example, but it’s good to be prepared! After the list is fully populated, we hide it

and position it directly over our real thead before slipping it into the page

Append as Infrequently as Possible

You may wonder why we wait until the list is fully constructed before appending

it to the page While appending the list to the page first, and subsequently append­

ing each item to it would have the same desired effect, the method we’ve chosen

to adopt executes much more quickly in the browser

Every time you insert a new element into the DOM, the browser needs to recalculate the position of every element on the page If you do this a lot (especially if you

do it in a loop!), your script can become very slow The method we’ve used above—storing the new elements in a variable, processing them as necessary, and then appending them all in one fell swoop—ensures optimal performance

With our thead mimic now nicely in place, we need to react to the scroll event and

position it appropriately:

Trang 10

Licensed to JamesCarlson@aol.com

chapter_08/06_fixed_table_headers/script.js (excerpt)

➥$(document).scrollTop() < $tablẹdatắbottom')) {

We set the timeout for 100 milliseconds after the scrollevent fires; it’s a very short

time, but enough to ensure that we avoid constantly animating as the user scrolls

We check to see if we’ve scrolled the thead out of the viewport, but not past the

bottom of the table; if we have, we reveal our mimic and animate it to the correct

position If we’ve scrolled back high enough so that the original thead is visible, or

down past the bottom of the table, we fade out the impostor list (and position it

back at the top, so that it animates from the correct position when it reappears)

And there you have it! We can call our TABLẸfixHeader("#celebs") and scroll

the page, and the new “thead” follows along to keep the identifying labels visible

at all times

Repeating Header

Another approach to the disappearing header row problem is to simply repeat the

header at regular intervals This is particularly handy if the intention is for the data

to be printed out—as cool as it looks, our animated table header is unhelpful if you

need to sort through a dozen pages of printed tables! The goal would be to take the

first row of the table, and copy it every, say, ten rows

The result is shown in Figure 8.6

Trang 11

Licensed to JamesCarlson@aol.com

Figure 8.6 Repeating the table header Copying the header row and putting it elsewhere should be old hat for you by now

But how exactly do we add the header every ten rows? Do we loop over every row

and check its index? Well, we could … but yet again jQuery comes to the rescue

with a powerful built-in filter:

chapter_08/07_repeating_table_header/script.js (excerpt)

This solution starts out simply enough—grabbing the first table row, then cloning

it with the clonemethod Then comes the clever bit: the nth-child selector is perfect

for adding the rows right where we want them You might be a little baffled by the

way we’ve used it, though, as its syntax differs a bit from the other filters we’ve

seen At its most basic, if you give it a simple integer, it will select that index For

example, if you selected :nth-child(2), you’d receive the third child element

Trang 12

Licensed to JamesCarlson@aol.com

But the :nth-child selector also accepts other values, which cause it to select

multiple rows as the same time If you pass in the text values even or odd, you’ll

select all of the even or odd child elements Coolest of all, you can pass it an equation

to figure out which children to select!

You can use the letter “n” to indicate repetition; for example, :nth-child(10n)

will select every tenth row You can then augment this with a plus or minus to offset

which rows are selected For example, if you want to select the third row, and then

every tenth row after that, you could use :nth-child(10n+3) Finally, if you like

to think backwards, you could achieve the same result with :nth-child(10n-7)

That all works okay, but it does have a bug: if the last row of the table matches our

equation, the header row will be repeated as the final row—which looks a bit weird

Also, we want to apply the repeating header to a couple of tables, and want to avoid

having to copy/paste code Next chapter, we’ll look at making our code reusable

via plugins—but for now, we’ll keep it simple and stick with a trusty widget object:

chapter_08/07_repeating_table_header/script.js (excerpt)

We’ve created a function that accepts the selector string for our table, and a number

representing how many rows to leave between each repeat of the header We then

cycle through each element our selector finds (so our function can be applied to

more than one table on the same page) For each item, we set up a shortcut to the

$(this) element and grab the number of rows in the table It’s important to store

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

TỪ KHÓA LIÊN QUAN