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

Phát triển Javascript - part 25 potx

10 317 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 10
Dung lượng 2,32 MB

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

Nội dung

To practice feature detection, I encourage you to take this method for a spin, find more browser quirks, and smooth them over by detecting erroneous behavior and correcting it.. Using uno

Trang 1

return dom.customEvents[event](element, listener);

}

return _addEventHandler(element, event, listener);

}

dom.addEventHandler = addEventHandler;

}());

The mouseenter implementation keeps track of whether the mouse is

cur-rently hovering the target element, and fires anytime a mouseover is fired and the

mouse wasn’t previously hovering it The method uses dom.contains(parent,

child), which returns true if an element contains another The try-catch

pro-tects against a bug in Firefox, which will sometimes provide an XUL element as

relatedTarget This can happen when mousing over for instance a scroll bar,

and unfortunately XUL elements throw exceptions on any property access

Addi-tionally, the relatedTarget may be a text node, fetching its parentNode gets

us back on track

To practice feature detection, I encourage you to take this method for a spin,

find more browser quirks, and smooth them over by detecting erroneous behavior

and correcting it

10.6 Using Feature Detection

Feature detection is a powerful tool in cross-browser scripting It can allow many

features to be implemented for a very wide array of browsers; old, current, and future

ones That does not necessarily mean that employing feature detection implies that

you should provide fallback solutions for any feature that may not be supported

Sometimes, dropping support for old browsers can be a statement in itself, but we

should be able to do so without sniffing out the browsers we want to send down

the degradation path

10.6.1 Moving Forward

If supporting a troublesome old browser, oh say Internet Explorer 6, costs more

than the benefits can defend, businesses sometimes actively decide to drop

sup-port Doing so does not mean we should pretend “unsupported” browsers don’t

exist Using unobtrusive JavaScript and feature detection can ensure that when a

browser is no longer actively developed for, it will receive the usable but possibly

Trang 2

basic fallback solution In such cases, feature detection can be used to discriminate

incapable browsers

Going back to the strftime example, if we don’t want to support

enhanced features in browsers that cannot handle a function argument to

String.prototype.replace, we simply abort the definition of the method in

browsers in which this feature test fails Interfaces that use this method may choose

to do the same, i.e., if the strftime method is not available, higher level

enhance-ments that depend on it can choose to abort as well As long as feature detection

is built into every layer of the application, avoiding some or all enhancements in

inadequate browsers should not be too complicated The upside of this approach

is that it will work with all browsers that don’t support the required functionality,

old and new alike, and even those we aren’t aware of

10.6.2 Undetectable Features

Some features are hard to detect An example can be found in how Internet

Ex-plorer 6 renders certain replaced elements, such as select lists Displaying another

element over such a list will cause the list to show through the overlaid element

The quirk can be fixed by layering an iframe behind the overlay Even if we cannot

detect this problem, the fix is not known to cause problems in other browsers, and

so can be safely employed in all browsers If the fix to a problem won’t have ill

effects in any browsers, applying the fix for everyone can often be simpler than

de-tecting the problem Before applying a fix preemptively, it’s a good idea to consider

performance implications

Designing the problem away is another technique that is highly effective at

avoiding cross-browser woes For instance, IE’s implementation of

getElement-ByIdwill gladly return elements whose name property matches the provided id

This problem is simple to detect and work around, yet it is even simpler to make

sure HTML elements never use ids that match some name property on the page,

perhaps by prefixing ids

10.7 Summary

In this chapter we dove into feature detection, the most reliable and future proof

technique available for writing cross-browser JavaScript Browser sniffing in various

forms has several pitfalls, and cannot be trusted Not only is this technique unreliable

and brittle, but it also requires knowledge about specific browsers in a way that make

it a maintainability nightmare

From the Library of WoweBook.Com Download from www.eBookTM.com

Trang 3

Feature detection—self testing code—was explored as an alternative to browser

sniffing, and we have seen examples of testing both native and host objects and

meth-ods, as well prodding for supported events and CSS properties and even supported

CSS values

Feature detection is an art, and it is not an easy one to master Fully mastering

feature detection requires knowledge and experience as well as good judgment

Rarely is there a single answer, so we must apply our best sense and always be on

the lookout for better ways to harden our scripts Even though feature detection

is well fit to create scripts with the widest possible support surface, it need not be

used for that purpose The main motivation when producing scripts for the general

web should stay on avoiding broken web pages, and feature detection can help in

this regard by aborting scripts that are unlikely to succeed

This chapter concludes our selective tour of the JavaScript language In Part III,

Real-World Test-Driven Development in JavaScript, we will use test-driven

devel-opment to work through five small projects that combined produce a small chat

application implemented entirely in JavaScript

Trang 4

This page intentionally left blank

From the Library of WoweBook.Com Download from www.eBookTM.com

Trang 5

Part III

Real-World Test-Driven

Development in

JavaScript

Trang 6

This page intentionally left blank

From the Library of WoweBook.Com Download from www.eBookTM.com

Trang 7

11

The Observer Pattern

The Observer pattern (also known as Publish/Subscribe, or simply pub/sub)

is a design pattern that allows us to observe the state of an object and be notified

when it changes The pattern can provide objects with powerful extension points

while maintaining loose coupling

In this chapter we will let tests drive us through our first library By focusing on

a low-level library that deals with communication between JavaScript objects, we

avoid the world of the DOM, staying clear of the nastiest browser inconsistencies

Working through this chapter will show you how to

• Design an API using tests

• Continuously improve design by refactoring—both tests and production

code

• Add functionality one tiny step at a time

• Solve simple browser inconsistencies with the help of unit tests

• Evolve from classical language idioms to idioms that make better use of

JavaScript’s dynamic features

There are two roles in The Observer—observable and observer The observer is

an object or function that will be notified when the state of the observable changes

The observable decides when to update its observers and what data to provide

them with In classical languages like Java, notification happens through a call to

Trang 8

observable.notifyObservers(), which has a single optional argument

(which in turn can be any object, often the observable itself) The

notifyOb-serversmethod in turn calls the update method on each observer, allowing

them to act in response

11.1 The Observer in JavaScript

JavaScript traditionally lives in the browser, where it is used to power dynamic user

interfaces In the browser, user actions are handled asynchronously by way of DOM

event handlers In fact, the DOM event system we already know is a great example

of the Observer pattern in practice We register some function (the observer) as

an event handler with a given DOM element (the observable) Whenever

some-thing interesting happens to the DOM element, i.e., someone clicks or drags it, the

event handler is called, allowing us to make magic happen in response to the user’s

actions

Events appear many other places in JavaScript programming as well Consider

an object that adds live search to an input field Live search is the kind that uses

the XMLHttpRequest object to continuously perform server-side searches as the

user types, narrowing down the list of hits as the search phrase is typed out The

object would need to subscribe handlers to DOM events fired by keyboard typing

in order to know when to search It would also assign a handler to the

onreadys-tatechangeevent of the XMLHttpRequest object to know when results are

ready

When the server comes back with some search results, the live search object

may choose to update its result view by way of an animation To allow further

customization, the object may offer clients a few custom callbacks These callbacks

can be hard-coded to the object or, preferably, it can make use of a generic solution

for handling observers

11.1.1 The Observable Library

As discussed in Chapter 2, The Test-Driven Development Process, the test-driven

development process allows us to move in very small steps when needed In this first

real-world example we will start out with the tiniest of steps As we gain confidence

in our code and the process, we will gradually increase the size of our steps when

circumstances allow it (i.e., the code to implement is trivial enough) Writing code

in small frequent iterations will help us design our API piece-by-piece, as well as

help us make fewer mistakes When mistakes occur, we will be able to fix them

From the Library of WoweBook.Com Download from www.eBookTM.com

Trang 9

quickly as errors will be easy to track down when we run tests every time we add a

handful of lines of code

The library needs to define the role of the observer as well as the observable.

However, in contrast to the Java solution mentioned earlier, JavaScript observers

need not be objects that conform to a certain interface Functions are first class

objects in JavaScript, so we can simply subscribe functions directly This means our

work consists of defining the Observable API

11.1.2 Setting up the Environment

For this chapter we will use JsTestDriver and its default assertion framework

Refer to Chapter 3, Tools of the Trade, if you have not yet set up JsTestDriver in your

development environment

Listing 11.1 shows the initial project layout

Listing 11.1 Directory layout for the observable project

chris@laptop:~/projects/observable $ tree

| jsTestDriver.conf

| lib

| ` tdd.js

| src

| ` observable.js

` test

` observable_test.js

The lib/tdd.js contains the tddjs object and the namespace method

developed in Chapter 6, Applied Functions and Closures We will use these to develop

the observable interface namespaced inside tddjs

The configuration file is just a plain default jsTestDriver configuration file that

runs the server on port 4224 and includes all script files, as seen in Listing 11.2

Listing 11.2 The jsTestDriver.conf file

server: http://localhost:4224

load:

- lib/*.js

- src/*.js

- test/*.js

Trang 10

11.2 Adding Observers

We will kick off the project by implementing a means to add observers to an object

Doing so will take us through writing the first test, watching it fail, passing it in the

dirtiest possible way, and finally refactoring it into something more sensible

11.2.1 The First Test

To keep us going through the initial stages of developing the observable library,

we will keep to the Java parallel This means that the first test will create an

ob-servable object with the Obob-servable constructor and add an observer by calling

the addObserver method on it To verify that this works, we will be blunt and

assume that Observable stores its observers in an array, and check that the

ob-server is the only item in that array The test can be seen in Listing 11.3 Save it in

test/observable_test.js

Listing 11.3 Expecting addObserver to add observer to internal array

TestCase("ObservableAddObserverTest", {

"test should store function": function () {

var observable = new tddjs.util.Observable();

var observer = function () {};

observable.addObserver(observer);

assertEquals(observer, observable.observers[0]);

}

});

11.2.1.1 Running the Test and Watching it Fail

At first glance the results of running our very first test, in Listing 11.4, is devastating

Listing 11.4 Running the test

chris@laptop:~/projects/observable$ jstestdriver tests all

E

Total 1 tests (Passed: 0; Fails: 0; Errors: 1) (0.00 ms)

Firefox 3.6.3 Linux: Run 1 tests \

(Passed: 0; Fails: 0; Errors 1) (0.00 ms)

Observable.addObserver.test \

should store function error (1.00 ms): \

From the Library of WoweBook.Com Download from www.eBookTM.com

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

TỪ KHÓA LIÊN QUAN