Tải bản đầy đủ - 0 (trang)
7 Step 4: Adding Products to the Shopping Bag

7 Step 4: Adding Products to the Shopping Bag

Tải bản đầy đủ - 0trang

if (!gimmeControl) {

alert("Nothing on this screen to give you.");



for (var i = 0; i < shoppingBag.things.length; i++) {

if (categorySet[curCLoc].prodLine[curPLoc].plu ==

shoppingBag.things[i].plu) {

alert("That's already in your bag. You can change the

quantity " +

"by choosing View/Change Bag.");




shoppingBag.things[shoppingBag.things.length] =


shoppingBag.things[shoppingBag.things.length - 1].itemQty =


shoppingBag.things[shoppingBag.things.length - 1].category =


alert("OK. You put the " +

shoppingBag.things[shoppingBag.things.length - 1].name +

" in your bag.");


The first thing gimmeOne() does is to ensure that there is actually something on the screen to put

in the shopping bag. Variable gimmeControl is set to true immediately before a product is displayed.

Otherwise, any other functions displaying information on the screen set gimmeControl to false.

Therefore, if gimmeControl is false, there is no product on the screen. The user is alerted, and

gimmeOne() returns. Otherwise, gimmeOne() iterates through the elements of the things array,

which is a property of the user's shoppingBag object to check whether the product currently in view is

already in the user's bag.

gimmeOne() doesn't expect any arguments. It relies instead upon the current values of curCLoc

and curPLoc. Assuming that each product has a unique PLU number, gimmeOne() looks for a

match with any of the PLU numbers of the products currently in the bag. If it finds a match, the user is

alerted that the product is already in the bag.

If the product isn't already in the bag, gimmeOne() puts it in. This poses an interesting situation,

however. Answer this question: a product in the shopping bag is still a product object—true or false?

If you answered true, you're right. However, any product in the user's shopping bag must be an

extended, more complex product. Each product in the bag still has a name, description, PLU, and

price, but each also needs a property to represent the quantity ordered and has to "know" to which

category it belongs.

Each element in things, therefore, must have properties dynamically added to it. Lines 125-129 show

how function gimmeOne() adds these specialized products to things and adds the properties to

each object:

shoppingBag.things[shoppingBag.things.length] =


shoppingBag.things[shoppingBag.things.length - 1].itemQty = 1;

shoppingBag.things[shoppingBag.things.length - 1].category =


shoppingBag.things[shoppingBag.things.length] creates a reference to the

product object currently at categorySet[curCLoc].prodLine[curPLoc]. This adds a

"regular" product to the shopping bag. The next two lines add respective properties itemQty , initially

set to 1, and category to the name of the category in which the current product object belongs.

JavaScript Technique: Adding Object Properties

There are a couple of ways to add properties to user-defined objects. The easiest is just to

think of a property name and value, then add it to the object. Each element in things is a

product, but these products are assigned two new values, itemQty and category. The

following lines reflect that:

shoppingBag.things[shoppingBag.things.length 1].itemQty = 1;

shoppingBag.things[shoppingBag.things.length 1].category =


Those objects have already been constructed, however, so properties must be added every

time. If you want to add properties to all objects constructed in the future, use the prototype

property. Suppose you want to add a sale price to any other products made:

product.prototype.salePrice = 0.00;

Any other objects constructed will now have a salePrice property with the default value of


The last thing gimmeOne() does is to advise the user that the product was successfully

added to the shopping bag.

This process repeats itself for every product the user puts in the shopping bag until it is time to check


8.7.1 Searching for Products

You've probably noticed by now: the "Product Search" feature is a Chapter 1 transplant. The clientside search engine has been modified to suit the needs of Shopping Bag users. Everything is pretty

much the same. The search capabilities, however, have been reduced to only a default Boolean OR

search. In other words, if any of the text the user enters is found in the product information, that

product is considered a match. There is no Boolean AND search and no search by URL. Still, the

capability should be more than enough to fit the bill. There is one extra feature that the Chapter 1

engine doesn't have. Users can enter an empty string simply by pressing the Enter key. This performs

a null search, which returns all the products in the database.

We won't get into the same level of detail as Chapter 1 does, but you should read over the next few

paragraphs to see how easy it can be to extend organized JavaScript applications. After all, like any

other search engine, the user just wants to enter text to generate a list of linked results. To make this

work for Shopping Bag without causing serious code changes to either application, the search engine

needs to make the following accommodations:

Display linked results that support the product/category navigation system explained in Step 2

Be able to search the existing product database

Return links to all the products in the database

Fortunately, these changes all can be made in one file—search/nav.html. So that you don't have to

stare at another couple hundred lines of code, I'll show you only the relative code in search/nav.html.

8.7.2 Mapping the Products and Categories

We need to change things just a little for everything to operate smoothly. These changes come in the

form of two new variables and a new function, as shown by:

var ref = top.frames[1];

var prodProfiles = new Array();

function genProfile() {

for (var i = 0; i < ref.categorySet.length; i++) {

for (var j = 0; j < ref.categorySet[i].prodLine.length;

j++) {

prodProfiles[prodProfiles.length] = new Array(i, j);




Variable ref is used as an alias to top.frames[1]. Since most of the objects and variables

referenced in this search engine application are located within manager.html, the object buried within

objects will make for some pretty lengthy references with plenty of dot notation. Using ref instead of

top.frames[1] shortens the writing somewhat. prodProfiles starts as an empty array but is soon

filled with a call to function genProfile().

genProfile() has one job and one job only—establish a system to reference any product object

in any category by its category number and product number. The category number is paired with a

product number.

For example, assume that i, the category number, is 1 and j, the product number, is 2. If you check

inventory.js, you'll see that categorySet[i].prodLine[j] refers to the "Igloo" in the

"Buildings" category. It's like plotting coordinates on a map.

The nested for loops in genProfile() iterate through each category (i) and product (j).

genProfile() makes a mental note, if you will, of each products location in the category by

storing the i,j integer pair in an array of its own. When all is finished, each element in prodProfiles

represents a category/product number pair that references a unique product in a category.

You may ask: isn't that how the products are already referenced? The answer is yes. However, the

search engine function now knows all of the possible combinations. Each pair is stored as an element

in prodProfiles. This makes it very easy to refer to (and search and display) information about any

product in the database.

8.7.3 Searching the Existing Database

The original version searched a web page name, description, and URL. Shopping Bag has similar

items to search. The problem is that you have to do it according to the existing database. Fortunately,

you can make a few changes to function allowAny(). Here it is in search/nav.html:

function allowAny(t) {

var findings = new Array();

for (var i = 0; i < prodProfiles.length; i++) {

var compareElement = ref.categorySet[prodProfiles[i][0]].

prodLine[prodProfiles[i][1]].name + ' ' +



description + ' ' +



price.toString() + ' ' +




compareElement = compareElement.toUpperCase();

for (var j = 0; j < t.length; j++) {

var compareString = t[j].toUpperCase();

if (compareElement.indexOf(compareString) != -1) {

findings[findings.length] = new









Not much has really changed. The only thing we need to be concerned about is what to search. So the

user can search product name, description, price, and PLU. allowAny() concatenates those four of

each product in the database together. That makes one long string to compare against each of the

words the user has entered. If a match occurs, the next available findings element is set to a new array

with prodProfiles[i][0] and prodProfiles[i][1] as its elements. Remember that

these two elements are integers that will be used to print out the results shortly.

8.7.4 Supporting Product/Category Navigation

Suppose you perform a search that returns a result set. Now you have to get it on the page. You would

be a prime candidate for carpal tunnel syndrome if you decided to code it to display products from the

search engine while ignoring the current product/category system. That is, whatever product links are

displayed on the results page, users must be able to display the products as usual and then navigate

freely with the "Next" and "Prev" buttons. Let's simply make changes to function


function formatResults(results, reference, offset) {


docObj.writeln('\n\nSearch<br /><br />Results' +

'' +

' +



'Search Query: ' +

parent.frames[0].document.forms[0].query.value +


\n' +

'Search Results: ' + (reference + 1) + ' - ' +

(reference + offset > results.length ? results.length :

reference + offset) +

' of ' + results.length + '

' + '' +


var currentRecord = (results.length < reference + offset ?

results.length : reference + offset);

for (var i = reference; i < currentRecord; i++) {

' + '' +

'' +

ref.categorySet[results[i][0]].prodLine[results[i][1]].name +

' +


tion +

' + 'Price: $' +

prodLine[results[i][1]].price) +

      ' + 'PLU Number: ' +

ref.categorySet[results[i][0]].prodLine[results[i][1]].plu +






prevNextResults(results.length, reference, offset);

' +





>Each result displays the product name, description, price, and PLU number. This function iterates

through the elements of results and accesses the respective prodLine information using the integers in

results[i][0] and results[i][1]. In other words, if results looks like this:

results = new Array(

new Array(0, 1),

// Remember that the 0 element represents

new Array(2, 2),

// the category number and the 1 element

new Array(4, 1)

// represents the product number


then the search results would contain the hairdryer (category 0, product 1), the purse (category 2,

product 2), and the fries (category 4, product 1). Using these number pairs makes it easy to store a

small amount of information and reference them later.

JavaScript Technique: Reusing a JavaScript Database

Happy is the coder who can use a bunch of data stored as JavaScript objects and arrays. Even happier is the

coder who can access that information from a different application without re-inventing the wheel. That's

what happens with Shopping Bag and the product search feature. Because of the relatively simple design,

the database needs no changes when the search engine wants to search it.

A few lines of code changes in the search engine, and things are humming again like they always were. If

you anticipate a situation like this, where your JavaScript database might be accessed from more than one

application, keep it simple enough so that all apps can get at the data without extra coding.

All you have to do to get the product info on the screen is use the number pairs. The for loop in

formatResults() prints the name, description, price, and PLU number by inserting the number pairs

to the following variables:



ref.numberFormat (ref.categorySet [results[i]

[0]].prodLine[results[i] [1]]



Each result is displayed with the above values contained in the string. A sample result would be:


Fancy yellowish blast, and durable cord. No expense spared.

Price: $1.15 PLU Number: HAI1

8.7.5 The Code in the Link

The results have been displayed, but how can we code it so that the link utilizes the navigation system

I've been preaching?

formatResults() offers the following solution:


Each link uses a javascript: protocol to call function reCall(), which is the same function

used to view products from the "Show All Categories" list. reCall() as you may "reCall" (sorry, I

couldn't resist) expects two arguments—a category number and a product number. That's what we've

been using in the search engine. All we have to do is to include each of the elements of the number

pairs in the call, and we're set. So the hairdryer, for example would have the following link:


Look what happens to the and 1 when they show up at reCall():

function reCall(cReset, pReset) {

browseControl = true;

curCLoc = cReset;

curPLoc = pReset;

display(0, 0);


Variable curCLoc is set to the value of the category number in cReset; likewise, with curPLoc and

pReset . The search engine coexists with the rest of Shopping Bag, and there were very few

adjustments needed.

8.8 Step 5: Changing the Order/Checking Out

When the user is either out of cash or doesn't see anything else desirable, it's time to head for the door.

Clicking the "View/Change Bag" link opens the screen, similar to that in Figure 8.8. The user's

shopping bag has to do more than just display his or her selections. Consider all the requirements:

Display each product and its category, PLU number, and price per unit.

Provide an interactive form to change product quantities, delete product selections, and

recalculate product costs.

Display running totals including the total for each product and quantity, the subtotal, and any

applicable taxes.

It probably doesn't surprise you to know, then, that there are also several functions ready and waiting

to accommodate these Shopping Bag needs. They are as follows:


Display the contents of the shopping bag.


Generate dynamic select lists to change product quantities.


Manage the calculation and display of any prices or costs.


Ensure accurate calculations and consistent displays in 0.00 format.


Ensure accurate calculations.


Remove product selections from and change product quantities of the user's shopping bag.

Function showBag() gets the call as soon as the user follows the link. Look at lines 135-198:

function showBag() {

if (shoppingBag.things.length == 0) {

alert("Your bag is currently empty. Put some stuff in.");



gimmeControl = false;


var header = 'Your Shopping Bag'



var intro = '

Your Shopping Bag!!!


var tableTop = '


var itemStr = '';

for (var i = 0; i < shoppingBag.things.length; i++) {

itemStr += '' +

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

7 Step 4: Adding Products to the Shopping Bag

Tải bản đầy đủ ngay(0 tr)

Index' +

ProductCategory' +

PLUUnit Price' +

QuantityProduct Total' +

Remove' +