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

Practical prototype and scipt.aculo.us part 18 doc

6 245 0

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

THÔNG TIN TÀI LIỆU

Nội dung

Events If you’re a fan of the absurd, bizarre, and overcomplicated—and you must be if you write JavaScript—you’re probably familiar with Rube Goldberg machines. Named for their cartoonist creator, these ad hoc, convoluted contraptions humorously obfuscate simple processes like flipping a light switch or opening a door. They paint a picture of a parallel universe where simple tasks are complicated. I’m drawn to Goldberg machines because they’re the opposite of how things work in everyday life. Usually we dream of an ideal world where things that seem simple actually are simple, without reality stubbornly standing in the way. Browser-based, event-driven interfaces should be simple. Highlight an element when the user clicks on it. Disable a submit button after a form has been submitted. But reality is harsh in the world of web development. Writing event handlers can feel like building an elaborate set of pulleys to open a window. In an unyielding quest to help client-side developers manage this complexity, Proto- type sports a robust event system—one that makes simple things simple and complex things possible. State of the Browser (Or, How We Got Here) I feel like a broken record—browser wars, lack of specifications, Netscape did one thing, Internet Explorer did another. It bears repeating because we’re still feeling the effects 10 years later. Rather than subject you to a bland history lesson, though, I’ll recap through code. Pre-DOM, Part 1 Let’s travel back in time to 1996—the heyday of Netscape 2.0, the first version to imple- ment JavaScript. Back in the day, this was how you assigned events: <input type="submit" value="Post" onclick="postBreakfastLogEntry();"> 91 CHAPTER 5 The event assignment was just another attribute in the HTML. On its face, this is a simple and straightforward way to assign events: it makes simple things simple. Unfor- tunately, it also makes complex things damn near impossible. First: note that we’re inside a pair of quotation marks. What if we need to use quota- tion marks in our code? <input type="submit" value="Post" onclick="postBreakfastLogEntryWithStatus(\"draft\");"> We could use single quotes instead, but that’s just a band-aid. With sufficiently com- plex code, we’d be forced to escape quotation marks. By itself it’s not a big deal—just an illustration of how HTML and JavaScript don’t mix well. Second, what if we need to assign the event to a bunch of different things? <input type="submit" value="Save as Draft" onclick="postBreakfastLogEntryWithStatus('draft');"> <input type="submit" value="Save and Publish" onclick="postBreakfastLogEntryWithStatus('published');"> <input type="submit" value="Discard" onclick="postBreakfastLogEntryWithStatus('discarded');"> That’s a lot of typing—and a lot of code duplication for something that should be much easier. DOM scripting makes it trivial to work with arbitrary collections of ele- ments. Why, then, are we writing copy-and-paste HTML to solve this problem? Pre-DOM, Part 2 Such scary times. Let’s jump ahead one year and assign events the way Netscape 3.0 lets us: in pure JavaScript. // HTML: <input type="submit" value="Save and Publish" id="save_and_publish"> // JavaScript: var submitButton = document.getElementById('save_and_publish'); submitButton.onclick = postBreakfastLogEntry; Here we’re doing what the previous example only hinted at. Event handlers (onclick, onmouseover, onfocus, etc.) are treated as properties of the node itself. We can assign a function to this property—passing it a reference to a named function or declar ing an anonymous function on the spot. CHAPTER 5 ■ EVENTS92 Now it’s much more elegant to assign the same handler to a bunch of elements: $('save_and_publish', 'save_as_draft', 'discard').each( function(button) { button.onclick = postBreakfastLogEntry; }); But if we assign one function to a bunch of different elements, how do we figure out which one received the event? In this example, our postBreakfastLogEntry function should receive an event object as its first argument—one that will report useful information about that event’s context. Just as you can inspect a letter and know its post office of origin, an event handler is able to inspect an event and know what type it is, where it came from, and what should be done with it. function postBreakfastLogEntry(event) { var element = event.target; if (element.id === 'save_and_publish') saveAndPublish(); /* et cetera */ } Unfortunately, events have never been quite this simple. This is a portrayal of an ideal simplicity—not on Earth, but in a parallel universe where the adversarial and fast- moving browser market didn’t make simplicity impossible. The real-world example would look like this: function postBreakfastLogEntry(event) { event = event || window.event; var element = event.target || event.srcElement; if (element.id === 'save_and_publish') saveAndPublish(); /* et cetera */ } The browser wars were in full swing by 1997. Hasty to add differentiating features to their own products, and working in an area where a standards body had not yet claimed authority, Internet Explorer and Netscape developed event models that were alike enough to seem compatible, but still different enough to cause maximum confu- sion and headaches. Ten years later, the landscape is not all that different. But instead of Internet Explorer versus Netscape, it’s Internet Explorer versus the standards. The other three major browsers hav e all adopted DOM Level 2 Events, the 2000 specification that finally CHAPTER 5 ■ EVENTS 93 brought some authority to the discussion, but as of version 7, Internet Explorer still uses its proprietary event model. The strides web applications have made in the last decade only call more attention to this problem: writing cross-browser event code is just as hard now as it was in 1997. Hav- ing to reconcile these differences—in property names, in event assignment, and in the event types themselves—is the mental mildew that makes simple things hard. Events: The Crash Course Let’s go back to our site from the previous chapter. So far, we’ve neglected the UI (i.e., there is none). Unless we want our breakfast loggers to type all their commands into the Firebug console, we’ll have to build a simple form for adding entries to the log. In between chapters, I took the liberty of writing some CSS to make our page a little less ugly (see Figure 5-1). Figure 5-1. Lipstick on the pig Open up index.html and follow along. (Feel free to style your version in whatever manner you choose.) CHAPTER 5 ■ EVENTS94 We’re collecting two pieces of information: what the user ate and how good it was. The form practically writes itself. <h1>Log Your Breakfast</h1> <form id="entry" method="post" action="breakfast.php"> <p> I just ate <input type="text" id="food_type" name="food_type" size="15" />. My meal was <input type="text" id="taste" name="taste" size="15" />.</p> <input type="submit" name="submit" value="Post Entry" /> </form> The hardest part has already been done. Remember that we already have a breakfast.php script, one that expects a form submission containing these two fields. Insert this markup at the bottom of index.html, and your page should look something like Figure 5-2. Figure 5-2. Our form doesn’t do anything yet, but it looks nice. CHAPTER 5 ■ EVENTS 95 Now let’s start writing some JavaScript! First we’re going to create a new file called breakfast.js and include it from index.html. Separating HTML from JavaScript, putting each in its own file, will stave off the urge to write spaghetti code. File: index.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>Andrew's Breakfast Log</title> <link rel="stylesheet" href="breakfast.css" type="text/css" /> <script <script src="breakfast.js" type="text/javascript"></script> </head> Because we’ll be writing code that uses parts of Prototype, we must include our new script at the end. (Remember, Prototype should be the first script you include on your page.) There’s nothing in breakfast.js yet, so let’s fix that. We need to write the function that will get called when the form is submitted. Then we’ll write the glue to connect it to the actual event. function submitEntryForm() { var updater = new Ajax.Updater({ success: 'breakfast_history', failure: 'error_log' }, 'breakfast.php', { parameters: { food_type: $('food_type').value, taste: $('taste').value } }); } This code is almost identical to the code we wrote in the last chapter. Only one thing has changed: instead of specifying the values directly, we look up the values of the two text boxes. There are many ways to hook into these values, but an ID lookup is the quickest. Now the glue. It won’t take much code to connect the function and the event—we can use Prototype’s observe method: $('entry').observe('submit', submitEntryForm); CHAPTER 5 ■ EVENTS96 . type="text/javascript"></script> </head> Because we’ll be writing code that uses parts of Prototype, we must include our new script at the end. (Remember, Prototype should be the first script you. that will report useful information about that event’s context. Just as you can inspect a letter and know its post office of origin, an event handler is able to inspect an event and know what type. maximum confu- sion and headaches. Ten years later, the landscape is not all that different. But instead of Internet Explorer versus Netscape, it’s Internet Explorer versus the standards. The other

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

TỪ KHÓA LIÊN QUAN