Pro javascript for web apps pdf download


















This book covers the latest features of JavaScript, and advanced concepts including modularity, testing, and asynchronous programming. You will be able to cut development time by using one stack to serve all your development needs. All three of these books are published by Apress. You can see the effect in Figure Using events to apply a class to an elementUsing the Event ObjectThe two functions that I passed as arguments to the hover method in the previous example are largelythe same.

I can collapse these two functions into a single handler that can process both events, as shownin Listing The callback function in this example takes an argument, e. This argument is an Event objectprovided by the browser to give you in for mation about the event you are handling. I have used theEvent. The typeproperty returns a string that contains the event name.

If the event name is mouseenter, then I call theaddClass method. If not, I call the removeClass method that has the effect of removing the specified classfrom the class attribute of the elements in the jQuery object, the opposite effect of the addClass method.

Forexample, the browser will navigate to the URL specified by the href attribute of an a element in responseto the click event. This is the basis for navigation in a web page. I cheated a little by setting the href attribute to. Listing provides a demonstration, where I havechanged the href attribute for the a element to a real web page. Managing Default Actions To fix this, a call to the preventDefault method on the Event object passed to the event handlerfunction is required.

This disables the default action for the event, meaning that only the code in theevent handler function will be used. You can see the use of this method in Listing Preventing the Default Action There is no default action for the mouseenter and mouseleave events on an a element, so in thislisting, I need only to call the preventDefault method when handling the click event.

Adding Dynamic Basket DataYou have seen how you can improve a web application simply by adding and modifying elements andhandling events. In this section, I go one step further to demonstrate how you can use these simpletechniques to create a more responsive version of the cheese shop by incorporating the in for mationdisplayed in the basket phase alongside the product selection.

I have called this a dynamic basketbecause I will be updating the in for mation shown to users when they change the quantities of individualcheese products, rather than the static basket, which is shown when users submit their selections usingthe unenhanced version of this web app.

Adding the Basket ElementsThe first step is to add the additional elements I need to the document. I could add the elements usingHTML fragments and the appendTo method, but for variety I am going to use another technique, knownas latent content.

Listing shows the addition of the latent content to the HTML document. They are all assigned to the latent class,which has the following definition in the styles. I showed you earlier in the chapter that the jQuery hide method sets the CSS display property tonone to hide elements from the user, and I have followed the same approach when setting up this class. The elements are in the document but not visible to the user.

Showing the Latent ContentNow that the latent elements are in place, I can work with them using jQuery. The first step is to revealthem to the user. Since I am manipulating the elements using JavaScript , they will be revealed only tousers who have JavaScript enabled.

Listing shows the addition to the script element. Revealing the Latent Content The highlighted statement selects all of the elements that are members of the latent class and thencalls the show method.

The show method adds a style attribute to each selected element that sets thedisplay property to inline, which has the effect of revealing the elements. The elements are stillmembers of the latent class, but values defined in a style attribute override those that are defined in astyle element, and so the elements become visible.

Responding to User InputTo create a dynamic basket, I want to be able to display subtotals for each item and an overall totalwhenever the user changes a quantity for a product. I am going to handle two events to get the effect Iwant. The first event is change, which is triggered when the user enters a new value and then moves thefocus to another element.

The second event is keyup, which is triggered when the user releases a key,having previously pressed it. The combination of these two events means I can be confident that I will beable to respond smoothly to new values. Binding to the change and keyup Events The advantage of the bind method is that it lets me handle multiple events using the sameanonymous JavaScript function.

To do this, I have selected the input elements in the document to get ajQuery object and called the bind method on it. The first argument to the bind method is a stringcontaining the names of the events to handle, where event names are separated by the space character. The second argument is the function that will handle the events when they are triggered.

There are onlytwo statements in the event handler function, but they are worth unpacking because they contain aninteresting mix of jQuery, the DOM API, and pure JavaScript.

I tendtoward accepting this duplication as the cost of ensuring a fluid user experience. Calculating the SubtotalThe first statement in the function is responsible for calculating the subtotal for the cheese productwhose input value has changed. Basic HTMLElement Pro perties Pro pertyclassNameidtagNameDescriptionGets or sets the list of classes that the element belongs toGets or sets the value of the id attributeReturns the tag name indicating the element type The core properties are supplemented to accommodate the unique characteristics of differentelement types.

An example of this is the name property, which returns the value of the name attribute onthose elements that support it, including the input element.

In this statement, I call the val method, whichreturns the value of the value attribute of the first element in the jQuery object. When you use a method like val to read some value from the element, you get the value from the firstelement in the selection, but when you use the same method to set the value by passing the value as anargument , all of the selected elements are modified. Using the this variable, I have been able to get the value of the input element that triggered theevent and the price for the product associated with it.

I then multiply the price and the quantity togetherto determine the subtotal, which I assign to a local variable called, simply enough, subtotal. Displaying the SubtotalThe second statement in the handler function is responsible for displaying the subtotal to the user. Thisstatement also operates in two parts. I make a call to the siblings method,which returns a jQuery object that contains any sibling to the elements in the original jQuery object thatmatches the specified CSS selector.

This method returns a jQuery object that contains the latent spanelement next to the input element that triggered the event. I chain a call to the children method, which returns a jQuery object that contains any children of theelement in the previous jQuery object that match the specified selector. I end up with a jQuery objectthat contains the nested span element. I could have simplified the selectors in this example, but I wantedto demonstrate how jQuery supports navigation through the elements in a document and how thecontents of the jQuery object in a chain of method calls changes.

These changes are described inTable The second part of the statement is a call to the text method, which sets the text content of theelements in a jQuery object. Calculating the Overall TotalTo complete the basket, I need to generate an overall total each time a subtotal changes.

I have defined anew function in the script element and added a call to it in the event handler function for the inputelements. Listing shows the additions. Calculating the Overall Total The first statement in the calculateTotal function defines a local variable and initializes to zero. Iuse this variable to sum the individual subtotals. The next statement is the most interesting one in thisfunction. The first part of the statement selects a set of elementswww.

I start by selecting all span elements that are descendants of span elements that are part of thesubtotal class. This is another way of selecting the subtotal elements. I then use the not method toremove elements from the selection. In this case, I remove the element whose id is total. Having selected the items, I then use the each method.

This method calls a function once for eachelement in a jQuery object. I get the content of each subtotal element using the text method. Changing the Form TargetBy adding a dynamic basket, I have pulled the functionality of the basket web page into the main page ofthe application.

I am going tochange the target of the for m element so that submitting the for m goes straight to the shipping page,skipping over the basket page entirely. Listing shows the statement that changes the target. Changing the Target for the for m Element By this point, it should be obvious how the new statement works.

I select the for m element by type since there is only one such element in the document and call the attr method to set a new value for the action attribute.

The user is taken to the shipping details page when the for m is submitted, skippingthe basket page entirely. Changing the flow of the applicationAs this example demonstrates, you can change the flow of a web application as well as theappearance and interactivity of individual pages. Of course, the back-end services need to understandthe various paths that different kinds of user can follow through a web app, but this is easy to achievewith a little for ethought and planning.

Understanding Pro gressive EnhancementThe techniques I have demonstrated in this chapter are basic but very effective. But—and this is important—because these changes are done through JavaScript , the basic natureand structure of the web app remain unchanged for non- JavaScript users.

Figure shows the mainweb app page when JavaScript is enabled and disabled. The web app as shown when JavaScript is disabled and enabledThe version that non- JavaScript users experience remains fully functional but is clunkier to use andrequires more steps to place an order. Creating a base level of functionality and then selectively enriching it is an example of progressiveenhancement.

However, when creating web apps, the most common for m ofprogressive enhancement is driven by whether the user has JavaScript enabled. The easiest way to do this is by using the noscript and metaelements to redirect the browser to a page that explains the situation, as shown in Listing Dealing with Non- JavaScript Users JavaScript code goes here This combination of elements redirects the user to a page called noscript.

You can find this page in the source code download that accompanies this book and see the result inFigure This is especially true for users in large corporations,where computers are usually locked down and where features that are common in the generalpopulation are disabled in the name of security, including, sadly, JavaScript in browsers.

In my ownprojects, I try to support non- JavaScript users whenever possible, even when it requires a lot of additional ef for t. The techniques I used previously demonstrated how youcan manipulate the DOM and respond to events to tailor the appearance and behavior of elements,which is the main premise in this chapter. That said, for professional development, it a good principle to never write what you can obtain froma good JavaScript library, and when I want to create visually rich elements, I use a UI toolkit.

The first stage is to create a theme, which defines the CSSstyles that are used by the jQuery UI widgets which is the name given to the styled elements that a UItoolkit creates. As you make changes, the samplewidgets on the right side of the screen will update to reflect the new settings.

It took me about fiveminutes and a bit of trial and error to create a theme that matches the appearance of the example webapp. This can beuseful if you are not trying to match an existing app design, although the colors used in some of gallery styles arequite alarming.

When you are done, click the Download Theme button. You will see a screen that allows you toselect which components of jQuery UI are included in the download. You can create a smaller downloadif you get into the detail of jQuery UI, but for this book ensure that all of the components are selectedand click the Download button.

Your browser will download a. The second part of the setup is to copy the following files from the. As I write this, the current version is1. Youwill find the minimized version in the js folder of the. Listing shows the additions required to import jQuery UI into the document and to createa button. This ordering is important since jQuery UI depends on jQuery. I have made one additional method call, using the css method.

This method applies a CSS propertydirectly to the selected elements using the style attribute, and I have used it to set the font-familyproperty on the input element. I have set up web fonts from the Google Fonts www. You can see the result of using jQuery UI to create a button in Figure Theresult is, as you can see, consistent with the rest of the web app but much simpler to create in JavaScript.

These libraries are comprehensively tested, andthey save you from having to write and debug custom code, allowing you to spend more time on thefeatures that set your web app apart from the competition.

There is nothing intrinsically wrong with using these approachesif the app is so small that there can never be any issue about maintaining it because every aspect of itsbehavior is immediately obvious to a programmer. However, if you are reading this book, you want to go further and create web apps that are large, arecomplex, and have many moving parts. And when applied to such web apps, these techniques createsome fundamental problems. The underlying issue is that the different aspects of the web app are allmixed together.

The application data the products and the basket , the presentation of that data theHTML elements , and the interactions between them the JavaScript events and handler functions aredistributed throughout the document. This makes it hard to add additional data, extend thefunctionality, or fix bugs without introducing errors. In the chapters that follow, I show you how to apply heavy-duty techniques from the world ofserver-side development to the web app.

Client-side development has been the poor cousin of serversidework for many years, but as browsers become more capable and as web app programmers becomemore ambitious , we can no longer pretend that the client side is anything other than a full-fledgedplat for m in its own right. It is time to take web app development seriously, and in the chapters thatfollow, I show you how to create a solid, robust, and scalable foundation for your web app.

I amnot going to describe either pattern in any detail, other than to say that the core concept in both isseparating the data, operations, and presentation of an application into separate components. There is a lot of benefit in applying the same basic principles to a web application. I am not going toget bogged down in the design patterns and terminology. Instead, I am going to focus on demonstratingthe process for structuring a web app and explaining the benefits that are gained from doing so.

Resetting the ExampleThe best way to understand how to apply a view model and the benefits that doing so confers is tosimply do it. The first thing to do is cut everything but the basics out of the application so that I have aclean slate to start from. As you can see in Listing , I have removed everything but the basic structureof the document. To get started, Ihave added an object that describes the products in the cheese shop, as shown in Listing One of the biggest benefits of embracing a view model is that it makeschanges easier, and that includes changes to the structure of the underlying data.

Select the most recent version which is 2. Other structure libraries are available. Theimplementation details in these alternative libraries may differ, but the underlying principles remain the same. In the sections that follow, I will bring my view model and the view model library together todecouple parts of the example application. Generating Content from the View ModelTo begin, I am going to use the data to generate elements in the document so that I can display theproducts to the user.

This is a simple use of the view model, but it reproduces the basic functionality ofthe implementation in Chapter 2 and gives me a good foundation for the rest of the chapter. Listing shows the addition of the KO library to the document and the generation of the elements from the data.

The first is importing the KO JavaScript library intothe document with a script element. The second addition tells KO to use my view model object:ko. You can see the result of these bindings in Figure , andI explain how they work in the sections that follow. Creating content from the view modelUnderstanding Value BindingsA value binding is a relationship between a property in the view model and an HTML element.

This isthe simplest kind of binding available. This is an example of a text binding,which has the effect of setting the text content of the HTML element to the value of the specified viewmodel property, in this case, the category property.

There is a simple library available that supports unobtrusive KO data bindings, meaningthat the bindings are set up using jQuery in the script element. In fact, value bindings justinsert a single value into the document, and that means that extra elements are often needed as targets for value bindings. The way to get the desired effect is simple enough, albeit it adds somecomplexity to the HTML structure. An alternative is to create custom bindings, which I explain inChapter 4.

I use the visible binding later in the chapter and the css binding in Chapter 4,but you should consult the KO documentation at knockoutjs. Understanding Flow Control BindingsFlow control bindings provide the means to use the view model to control which elements are includedin the document.

In the listing, I used the for each binding to enumerate the items view model property. The for each binding is used on view model properties that are arrays and duplicates the set of childelements for each item in the array Value bindings on the child elements can refer to the properties of the individual array items, whichis how I am able to specify the id property for the attr binding on the input element: KO knows whicharray item is being processed and inserts the appropriate value from that item.

I describe the if and ifnot bindings later in thischapter, but you should consult the KO documentation at knockoutjs. I will start with some basic feature and then step things up to show you some more advancedtechniques.

Adding More Pro ducts to the View ModelThe first benefit that a view model brings is the ability to make changes more quickly and with fewererrors than would otherwise be possible. The simplest demonstration of this is to add more products tothe cheese shop catalog. Listing shows the changes required to add cheeses from other countries.

I changed the structure of the data object so thateach category of products is an element in an array assigned to the products property and, of course, Iadded two new categories. In terms of the HTML content, I just had to add a for each flow controlbinding so that the elements contained within are duplicated for each category.

This is not an ideal way of displaying data, butas I said in Chapter 1, this is a book about advanced programming and not a book about design. There are lots ofways to present this data more usefully, and I suggest starting by looking at the tabs widgets offered by UI toolkitssuch as jQuery UI or jQuery Tools. Creating Observable Data ItemsIn the previous example, I used KO like a simple template engine; I took the values from the view modeland used them to generate a set of elements.

I like using template engines because they simplify markupand reduce errors. But a bigger benefit of view models comes when you create observable data items. Putsimply, an observable data item is a property in the view model that, when updated, causes all of theHTML elements that have value bindings to that property to update as well.

Listing shows how tocreate and use an observable data item. This function uses the jQuery each method, which executes a function for every item inan array. By using the each function twice, I can reach the inner array of cheese products in eachcategory. All that remains is to set up a situation that will cause a change to occur. Since this is an observable data item, the new value will bepushed out to the value bindings and cause the document to be updated.

Notice the slightly odd syntax I use when altering the value. The original price property was a JavaScript Number, which meant I could change the value like this:item. This means you read the value of an observable data itemby calling the function in other words, by calling item. This can take a little while toget used to, and I still for get to do this. Figure shows the effect of the observable data item.

When the Apply Discount button is clicked,all of the prices displayed to the user are updated, as Figure shows. Using an observable data itemThe power and flexibility of an observable data item is significant; it creates an application wherechanges from the view mode, irrespective of how they arise, cause the data bindings in the document tobe updated immediately.

Creating Bidirectional BindingsA bidirectional binding is a two-way relationship between a for m element and an observable data item. When the view model is updated, so is the value shown in the element, just as for a regular observable. Inaddition, changing the element value causes an update to go in the other direction: the property in theview model is updated. So, for example, if I use a bidirectional binding for an input element, KO ensuresthat the model is updated when the user enters a new value.

By using bidirectional relationshipsbetween multiple elements and the same model property, you can easily keep a complex web appsynchronized and consistent. To demonstrate a bidirectional binding, I will add a Special Offers section to the cheese shop.

Listing contains the changes to the web app to support the special offers. To set up abidirectional binding, I am going to do two other interesting things: extend the view model and use KOtemplates to generate elements. I like being able to take the initial data and reshape it to create something that is more closelytailored to the needs of the web app, in this case, to add support for special offers.

To start with, I add aproperty called specials to the view model, defining it as an object that has category and itemsproperties like the rest of the model but with some useful additionswww. The specials. To populate the array, I enumerate theproducts array to find those products that are in the specials. The inArray method is another jQuery utility, and it returns the indexof an item if it is contained within an array and -1 if it is not. This is a quick and easy way for me to checkto see whether the current item is one that I am interested in as a special offer.

If an item is on the specials list, then I reduce the value of the price property by the discountamount and use the push method to insert the item into the specials.

In this example, I have made the quantity property into an observable data item:item. By using an observable data item and bidirectional bindings on the input elements, Ican easily make sure that the quantities entered for a cheese are consistently displayed, irrespective ofwhich input element is used.

Generating the ContentAll that remains now is to generate the content from the view model. I want to generate the same set ofelements for the special offers as for the regular categories, so I have used the KO template feature, whichallows me to generate the same set of elements at multiple points in the document. Here is the templatefrom the listingwww. Most of the bindings in the template arethe same text and attr bindings I used in the previous example.

The important addition is to the inputelement, as follows:The data-bind attribute for this element defines two bindings, separated by a comma. The first is aregular attr binding, but the second is a value binding, which is one of the bidirectional bindings thatKO defines.

In this listing, I create a two-way binding to the quantity observable data item. I generate content from the template using the template binding. When using a template, KOduplicates the elements that it contains and inserts them as children of the element that has thetemplate binding. There are two points in the document where I use the template, and they are slightlydifferent:When using the template binding, the name property specifies the id attribute value of the templateelement.

If you want to generate only one set of elements, then you can use the data property to specifywhich view model property will be used. I used data to specify the specials property in the listing, whichcreates a section of content for my special-offer products.

You can use the for each property if you want to generate a set of elements for each item in an array. I have done this for the regular product categories by specifying the products array.

In this way, I canapply the template to each element in an array to generate content consistently. The input elements for thespecial-offer products will have the same name attribute value as the corresponding input element in the regularproduct category.

By inserting the special-offer elements outside the for m, I prevent duplicate entries from beingsent to the server when the for m is submitted.

Reviewing the ResultNow that I have explained each of the changes I made to set up the bidirectional bindings, it is time tolook at the results, which you can see in Figure The result of extending the view model, creating a live binding, and using templatesThis is good demonstration of how using a view model can save time and reduce errors. Even though the price property is not observable, the combination of theview model and the template ensures that the correct prices are displayed throughout the documentwhen the elements are initially generated.

The bidirectional binding is the most interesting and useful feature in this example. All of the inputelements have bidirectional bindings with their corresponding quantity property, and since there aretwo input elements in the document for each of the Special Offer cheeses, entering a value into one will63www. So, with very little ef for t, I have been able to enhance the view model and use those enhancementsto keep a for m consistent and responsive, while adding new features to the application.

This is,of course, because I applied the discount only in the browser. In a real application, the server would also need toknow about the special offers, but I am going to skip over this, since this book focuses on client-side development. Adding a Dynamic BasketNow that I have explained and demonstrated how changes are detected and propagated with value andbidirectional bindings, I can complete the example so that all of the functionality present in Chapter 2 isavailable to the user.

This means I need to implement a dynamic shopping basket, which I do in thesections that follow. Adding SubtotalsWith a view model, new features can be added quickly.

The changes to add per-item subtotals aresurprisingly simple, although I need to use some additional KO features. By using these techniques, you can build web apps that are easier to write, are easier to maintain, and offer better and richer functionality to your users. Do you like this book? Please share with your friends, let's read it!! Search Ebook here:.

Food To Love May WebUser 06 February Playboy Denmark March Playboy South Africa November



0コメント

  • 1000 / 1000