Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 42 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
42
Dung lượng
831,44 KB
Nội dung
250 Chapter 13 The word true inside the cloneNode() method means that you want to clone the node and all its children. In this case it would be the table and all the contents of the table. If for some reason you didn’t want to make a copy of the children, you’d put false there. Once you’ve made your changes, you can replace the original table with the new one using the replaceNode() method. Like insertBefore() and removeChild(), this method is called by the parent of the nodes to be replaced. Given the myTable and cloneTable variables defined above, you could do this: var tableParent = myTable.parentNode; tableParent.replaceChild(cloneTable, myTable); Manipulating a Page Using the DOM As mentioned earlier, you could do most of the things described in this section with creative use of innerHTML. However, sometimes dealing with the complex strings needed to get innerHTML to be what you want can be difficult. In these cases, the DOM techniques are very helpful. When we get to the chapters on Ajax, you’ll see even more applications of the DOM manipu- lation techniques. Fancy Event Handling Dynamic web pages call for dynamic reactions to user actions. We’ve discussed how to write JavaScript that reacts when users click links, buttons, and form elements. Now it’s time to learn about more complicated event handling: how to accurately read the keyboard and the mouse. The event Object Whenever an event occurs, an event object is generated. The nature of this object depends on the event which generated it. To access the event object, simply pass the keyword event to whichever function is handling the event: <a href = "#" onClick = "handleClick(event); return false; ">Click me!</a>. The event object is most frequently accessed when you want to know which key a user has pressed, or precisely where the mouse is. Keyboard Events There are two main keyboard event handlers, the functions of which are pretty obvious: onKeyDown and onKeyUp. Triggering either of these event handlers creates an event object that stores which key has been pressed (or unpressed) and whether or not any special keys ( ALT, CTRL, or SHIFT) were pressed at the same time. The relevant properties of the event object appear in Table 13-2. Dynamic HTML 251 Figure 13-18 is short script that demonstrates how to use the event object to determine which key a user has pressed while in a text input field. <html><head><title>Demonstrating Keyboard Events</title> <script type = "text/javascript"> <! hide me from older browsers function displayEvent(evt) { var type = evt.type; X var code = evt.keyCode; Y var theChar = String.fromCharCode(code); var alt = evt.altKey; var ctrl = evt.ctrlKey; var shift = evt.shiftKey; Z var displayString = "event type: " + type + "; key code: " + code + ", which is the character " + theChar + "; ALT, CTRL, and SHIFT were: " + alt + ", " + ctrl + ", and " + shift + "\n\n"; [ if ((code >= 65) && (code <= 90)) { document.getElementById("showEvents").value += displayString; } } // show me > </script> </head> <body> <form> Type here: <input type = "text" \ onKeyDown = "displayEvent(event);" onKeyUp = "displayEvent(event);"><br> See the events here: <textarea id = "showEvents" cols = "80" rows = "20"> </textarea> </form> </body> </html> Figure 13-18: Demonstrating keyboard events Although the script in Figure 13-18 is simple, there are some subtleties. First, whenever a user types anything while in the text field, the act of pressing the key down creates one event, and the act of releasing the key creates another event. These events are captured by the event handlers in \. In either case, the displayEvent() function is called. This function creates variables for each of the event’s properties, combines them into a string, and then puts the Table 13-2: Properties for Keyboard Events Property Type Description altKey boolean True if the ALT key was down when this key was pressed ctrlKey boolean True if the CTRL key was down when this key was pressed shiftKey boolean True if the SHIFT key was down when this key was pressed keyCode integer The Unicode decimal value for the key that was pressed; use String.fromCharChode(keyCode) to convert this to a string Type string The type of event—keyup or keydown, for example 252 Chapter 13 resulting string into the textarea with the id of showEvents. The most interesting lines in this function are X, which gets a number representing the character being pressed, and Y, which converts that number into an actual character. After those lines are executed, Z creates a string representing what happened in the event and [ puts that string in the text area if the key being pressed is a letter (letters have character code numbers between 65 and 90). Figure 13-19 shows what happens when a and then A are typed into the text field. Notice that in both cases, the characterCode is 65, and the resulting character is A. In order to determine whether the user has entered a capital or lowercase letter, the shiftKey property of the event must be examined. Figure 13-19: Typing a and A into the Figure 13-18 script Mouse Events Mouse events have their own properties. Unfortunately, some cross-browser differences complicate accessing the position of the mouse and determining which mouse button was clicked. Table 13-3 shows the properties of mouse events, and it gives some details about how to deal with cross-browser differences. Table 13-3: Properties of Mouse Events Property Description button Equals 2 if it’s a right-click—otherwise, it depends on the browser clientX Internet Explorer’s X position for the mouse clientY Internet Explorer’s Y position for the mouse pageX Most other browsers’ X position for the mouse pageY Most other browsers’ Y position for the mouse Dynamic HTML 253 As you can see from Table 13-3, all the properties of mouse events are browser dependent. The button property, for example, describes which button was clicked when an onMouseDown or onMouseUp event happened. However, the meaning of the numbers provided by the button property depend on the browser being used. In Internet Explorer, 1 means the left button was clicked, 2 means the right button, and 4 means the middle button. In most other browsers, 0 means the left button, 1 means the middle button, and 2 means the right button. Because 2 means the right button was clicked in both cases and many people don’t have a middle button on their mouse, it is often safe to see if the button property of the event was 2 and call it a left-click if it was not. The position of the mouse is a bit trickier. Browsers other than Internet Explorer generally use an event’s pageX and pageY properties to give a number representing the X and Y positions (in pixels) of the event relative to the top-left corner of the browser window. These two properties take into con- sideration scrolling a window. If a window is 10,000 pixels long and the user has scrolled down to the very bottom, the pageY property will be around 10,000 at the bottom of the window. Internet Explorer, on the other hand, uses properties named clientX and clientY. These properties do not take scrolling into consideration, so to use them, you should add numbers repre- senting how far down and to the left the browser has been scrolled. Those numbers are available as document.body.scrollTop and document.body.scrollLeft. Figure 13-20 presents a script that determines the X and Y positions of a mouse and puts the results in a textarea. <html><head><title>Checking Mouse Position</title> <script type = "text/javascript"> <! hide me from older browsers function displayEvent(evt) { var x = 0; var y = 0; X if (evt.pageX) { Y x = evt.pageX; y = evt.pageY; Z } else if (evt.clientX) { [ x = evt.clientX + document.body.scrollLeft; y = evt.clientY + document.body.scrollTop; } \ document.getElementById("results").value += x + " " + y + "\n"; } // show me > </script> </head> <body> <div id = "box" style = "height:100px;width:100px;border:1px black solid;" ] onMouseMove = "displayEvent(event);" ^ onMouseOver = "document.getElementById('results').value='';"></div> <form><textarea id = "results" cols = "80" rows = "20"></textarea></form> </body> </html> Figure 13-20: Detecting the position of the mouse 254 Chapter 13 In Figure 13-20, moving inside the div calls the displayEvent() function (]), and moving the mouse onto the div clears the textarea that stores all the mouse information collected (^). The displayEvent() function first checks to see if the browser knows about the pageX property of the event (X). If so it uses pageX to get the x coordinate of the mouse, relative to the top-left corner of the browser window (Y) and pageY to get the y coordinate. If the browser does not know about the pageX property but does know about the clientX property (Z), it uses clientX and clientY. Notice in [ that the amount that the browser has been scrolled to the right or down must be added to the clientX and clientY property to account for scrolled windows. The last line in the function (\) adds the appropriate information to the textarea with the id of results. Adding Event Handlers Using JavaScript Throughout this book, whenever we have wanted to trigger an event based on a user’s behavior, we have put an event handler inside the triggering element. For example, in Chapter 4, when we wanted an alert box to pop up when a user clicked a link, we put an onClick event inside the link: <a href = "#" onClick = "alert('Thanks!');">Click me</a> Putting event handlers inside the elements that trigger the events can cause some problems: z Doing so puts JavaScript inside your HTML elements rather than inside <script> tags. This means that someone trying to understand your JavaScript (and that person may be you) will have to hunt around in the HTML to find all the various bits of JavaScript on the page. z Sometimes you want a JavaScript function to be triggered by many ele- ments. For example, if you have 20 checkboxes, each of which has an onClick, you will need to stick the same code (onClick = "doFunction();") in 20 different places. If the function’s name changes, or if you decide to add a parameter to the function, you will need to change the page in 20 different places. z You may want an event handler to be invoked in some cases, but not in others. In the case of writing drag-and-drop code, a given object, such as a div, should only be moved if the mouse has been clicked while on that object. In this case, the object’s onMouseMove event should only trigger a function when the appropriate object has been clicked. For these reasons, modern browsers provide ways for JavaScript to attach functions to the event handlers of objects. The template for this is: element.handler = function; Dynamic HTML 255 For example, to call a function named doAlert() whenever a div with the id of myDiv is clicked, use the following line: document.getElementById("myDiv").onclick = doAlert; This line is unusual for two reasons. First, the event handler (onClick) is all lowercase. This is a requirement when assigning a function to a handler in this way. Second, notice that the function does not have parentheses after it. This means that no parameters may be passed to this function. However, a function called in this way does have access to the event that called the function, and it turns out that the event is almost always the only parameter you need. As with all things related to events, there are some browser incompati- bilities involved with getting access to the event object. In Internet Explorer, the event is automatically stored in a variable named event. To access the event, just use the event variable: function doAlert() { myEvent = event; // do something with the myEvent variable alert("Got the event!"); } In most other browsers, the event is automatically passed as a parameter to the function being called. This means that the function being called, doAlert() in the example given, needs to have a parameter in its definition: function doAlert(myEvent) { // do something with the myEvent variable alert("Got the event!"); } Once the event object has been accessed inside a function, it is sometimes helpful to retrieve information about the object that created the event. To do this, Internet Explorer uses an event object property called srcElement. Most other browsers use a property named target. Figure 13-21 puts all this information together in a cross-browser script for assigning functions to events using JavaScript. <html><head><title>Cross-Browser Event Handling</title> <script type = "text/javascript"> <! hide me from older browsers function attachHandlers() { X var theElements = document.getElementById("myForm").childNodes; for (var loop = 0; loop < theElements.length; loop++) { Y if ((theElements[loop].nodeName == "input") || (theElements[loop].nodeName == "INPUT")) { Z theElements[loop].onclick = doAlert; } } 256 Chapter 13 } [ function doAlert(evt) { var thisBox; \ if (!evt) { evt = event; thisBox = evt.srcElement; ] } else { thisBox = evt.target; } alert('You clicked on ' + thisBox.name); } // show me > </script> </head> ^ <body onLoad = "attachHandlers();"> <form id = "myForm"> _ <input type = "checkbox" name = "1"><input type = "checkbox" name = "2"> <input type = "checkbox" name = "3"><br> <input type = "checkbox" name = "4"><input type = "checkbox" name = "5"> <input type = "checkbox" name = "6"><br> </form> </body> </html> Figure 13-21: Cross-browser script for attaching functions to event handlers The script in Figure 13-21 creates a set of six checkboxes, each with a different name. Clicking any of these checkboxes results in an alert box pro- viding the name of the checkbox that was just clicked. Notice that the HTML describing the checkboxes contains no onClick handlers (_). This is because the handlers are assigned using JavaScript. The onLoad handler inside the <body> tag (^) triggers the function which assigns the handlers. The function is called by the onLoad handler because an HTML element cannot have a func- tion attached to its handler until the web browser knows about the element. If a piece of JavaScript tries to attach a handler to a form element that has not yet been processed by the browser, an error will result. For this reason, it’s best to wait until all the elements have been loaded before assigning functions to their handlers. The attachHandlers() function has several interesting aspects. First, it uses the DOM methods covered earlier in the chapter to access the checkboxes. These checkboxes are child elements of the form element, and so they are accessible as the childNodes of the form (X). The childNodes property returns an array, which is then looped through. Each time through the loop, the JavaScript checks the next element in the array to see if it is an input element. Notice that both the strings INPUT and input are checked. This is because some Dynamic HTML 257 browsers capitalize element names and other browsers don’t. For each input element found, Z attaches the doAlert() function to the element’s onclick handler. Once the handlers have been attached, the page waits until a checkbox is clicked. When that happens, the onclick event is triggered, and the doAlert() function is called. Notice that the definition of doAlert() contains a parameter ([). In Firefox and most other browsers, this parameter will be filled with an event object that contains information about the event that caused the doAlert() function to be called. If that parameter is not filled in, it means the user is most likely using Internet Explorer. In this case, \ is true. The evt variable is set to the Internet Explorer variable event, and thisBox is set to the checkbox that was clicked using Internet Explorer’s srcElement property. If Firefox, or some other browser was used instead, the function’s evt parameter would already contain the event object, and we’d only need to set thisBox to the checkbox that was clicked by accessing the target property (]). One final note about assigning functions to event handlers using JavaScript: If for some reason you want to remove an event handler from an object, simply set the handler’s value to null. Here’s an example: document.getElementById("myDiv").onclick = null; Drop-Down Menus I’ll close this chapter by showing how to build a basic drop-down menu with DHTML. The menu shown in Figure 13-22 has three links: Dogs, Cats, and Birds. Mousing over Cats <html><head><title>Drop-Down Menus</title> <script type = "text/javascript"> <! hide me from older browsers X var div_array = new Array("divOne", "divTwo", "divThree"); function changeDiv(the_div, the_change) { Y document.getElementById(the_div).style.visibility = the_change; causes a submenu to drop down with the names of several cat breeds. Click- ing one of those links sends the browser to a web page about that kind of cat. Figure 13-23 shows the code that drives this drop-down menu. I’ve already covered everything you must know to understand this code, so take a look at it, and see if you can figure out how it works before reading my explanation. Figure 13-22: A drop-down menu 258 Chapter 13 } function closeAll() { Z for (var loop = 0; loop < div_array.length; loop++) { changeDiv(div_array[loop], "hidden"); } } // show me > </script> </head> <body> <div id = "top1" style = "position:absolute; top:20; left:0; z-index:1"> [ <a href = "#" onMouseOver = "closeAll(); changeDiv('divOne','visible');">Dogs</a> </div> <div id = "top2" style = "position:absolute; top:20; left:40; z-index:1"> <a href = "#" onMouseOver = "closeAll(); changeDiv('divTwo','visible');">Cats</a> </div> <div id = "top3" style = "position:absolute; top:20; left:80; z-index:1"> <a href = "#" onMouseOver = "closeAll(); changeDiv('divThree','visible');">Birds</a> </div> <div id = "rightBorder" style = "position:absolute; top:20; left:50;"> <a href = "#" onMouseOver = "closeAll();"><img src = "long_spacer.gif" border = 0></a> </div> <div id = "bottomBorder" style = "position:absolute; top:80; left:0;"> \ <a href = "#" onMouseOver = "closeAll();"><img src = "long_spacer.gif" border = 0></a> </div> ] <div id = "divOne" style = "position:absolute; top:40; left:0; visibility:hidden;"> <a href = "#">Collie</a><br> <a href = "#">Puli</a><br> <a href = "#">Corgie</a><br> </div> <div id = "divTwo" style = "position:absolute; top:40; left:80; visibility:hidden"> <a href = "#">Siamese</a><br> <a href = "#">Manx</a><br> <a href = "#">Calico</a><br> </div> <div id = "divThree" style = "position:absolute; top:60; left:80; visibility:hidden"> <a href = "#">Parakeet</a><br> <a href = "#">Finch</a><br> <a href = "#">Canary</a><br> </div> </body> </html> Figure 13-23: A basic hierarchical menu Dynamic HTML 259 Line-by-Line Analysis of Figure 13-23 A drop-down menu has a div for each menu option. The nine divs in Figure 13-23 include one div for each top-level menu element ([), one for each submenu (]), one for the bottom border, and one for the right border. Each time a visitor mouses over one of the main menu options, only the sub- menu matching the link most recently moused over is shown. If the visitor mouses over Cats, making the list of cat breeds visible, and then mouses over Dogs, the closeAll() function hides the Cats submenu and changeDiv() displays the Dogs submenu. Mousing over the bottom or right border closes all the submenus. The closeAll() Function The closeAll() function loops through the array of divs defined in X. Each time through the loop in Z, closeAll() calls the changeDiv() function to hide one of the divs. The changeDiv() Function The changeDiv() function takes two parameters: the name of a div to change, and whether to make the div hidden or visible. Line Y changes the visibility of the specified div to visible or hidden, depending on the value of the sec- ond parameter of changeDiv(). The Borders The menu’s bottom border is a long transparent (and therefore invisible) GIF (\). The code in \ dictates that mousing over this invisible GIF hides all submenus. This GIF and the blank GIFs on the right of the menus make sure the submenu vanishes if the visitor’s mouse leaves the menu area completely. Figure 13-23 offers a basic example of how you might implement a hier- archical menu. For more complete versions, check out the menu and naviga- tion section of Dynamic Drive’s website. Fortune magazine’s website used this one: http://www.dynamicdrive.com/dynamicindex1/dropmenuindex.htm. Summary DHTML is the topic of several excellent books—what we’ve discussed here should just whet your appetite. But you have learned a few DHTML basics, including the following: z How to use divs to create blocks of HTML z How to add styles to divs z How to make divs, along with the HTML they contain, visible or invisible z How to move divs [...]... webserver: either the web page named in the href attribute of the link, or the results of a program or script named in the action attribute of the tag Once the request is sent, the browser sits idly, usually animating an icon in the upper-right corner of the window, and the user waits for the webserver to respond to the request Eventually the server responds, and the web page reloads, presenting new... at the information the object has retrieved This information is stored in one or two properties of the request object: The responseText property of the object always contains a text string with the results, and if the response is an XML document, the responseXML property of the request contains an XML object representing the results (more on this in Chapters 15 and 16) If the response is not an XML document,... the request object makes the request in , which begins the process of downloading the requested text file The request object then goes through its five states, and each state change triggers the anonymous function Once the request object is in state 4, the anonymous function writes All done! into the div The magic in all of this is that while the request object is performing the query and getting the. .. enjoying the page Figure 14-3: Ajax versus traditional communications between a web browser and a webserver In the Ajax style, on the other hand, the browser makes a request from the webserver without the user knowing about the request The icon in the browser’s corner doesn’t spin, and the browser can still be used When the response comes back from the webserver, the information displayed in the web... downloaded into the request object We’ll see examples of this soon Sending the Request Once you’ve told the request object where to send the request and what to do when the request has been answered, it’s time to tell the request object to send the request, like so: request.send(null); 268 Chapter 14 This command sends the request using the request object’s send method The single parameter of the send method... part of the Ajax story In Chapter 15 you’ll learn about the X in Ajax (which stands for the data transfer standard XML), and how to read and navigate XML documents in JavaScript and use them in Ajax applications A Real-World Example of Ajax The best-known example of Ajax may be Google Maps (maps.google.com) Figure 14-1 shows you the map which results from searching for the office of No Starch Press The. .. simultaneously, and the browser deals with the responses as they come from the webserver In contrast, the traditional style of browser-server communication described in the Before Ajax part of Figure 14-3 is synchronous; that is, the browser submits a request to a webserver and then waits for a reply, unable to send any other requests until the server responds 264 Chapter 14 An example of asynchronicity... that’s the order in which they were requested) However, because these files are loaded asynchronously, all requests happen simultaneously This means that shortWait will be downloaded before longWait Each line in the figure shows the name of the file being downloaded and the number of seconds it took to download What you can’t see in the figure is that each of the lines appeared on the web page as the. .. describing objects in 3D, and SportsML, which the International Press Telecommunications Council uses to publish sports information Each of these uses the rules of XML and a set of predefined element and attribute names When using XML, you can either use existing vocabulary or create your own The format of an XML document is just the tip of the XML iceberg There are many useful technologies built around... ActiveXObject("Microsoft.XMLHTTP"); } Once this block of JavaScript has executed, the request variable will contain a request object Telling the Object Where to Send the Request The request object will request information from some resource Usually, that resource will be the webserver that served up the web page containing the JavaScript making the request In this case, the request object needs to know the URL of a . covered earlier in the chapter to access the checkboxes. These checkboxes are child elements of the form element, and so they are accessible as the childNodes of the form (X). The childNodes property. coordinate of the mouse, relative to the top-left corner of the browser window (Y) and pageY to get the y coordinate. If the browser does not know about the pageX property but does know about the. button on their mouse, it is often safe to see if the button property of the event was 2 and call it a left-click if it was not. The position of the mouse is a bit trickier. Browsers other than