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

Javascript bible_ Chapter 53

24 230 0
Tài liệu đã được kiểm tra trùng lặp

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Application: decision helper
Chuyên ngành JavaScript
Thể loại Chapter
Định dạng
Số trang 24
Dung lượng 187,67 KB

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

Nội dung

My first attack at this problem was to store the data as global variable data mostly arrays in the parent document that creates the frames.. Table 53-1 Files Comprising the Decision Help

Trang 1

Decision Helper

The list of key concepts for this chapter’s application

looks like the grand finale to a fireworks show As

JavaScript implementations go, the application is, in some

respects, over the top, yet not out of the question for

presenting a practical interactive application on a Web site

lacking control over the server

The Application

I wanted to implement a classic application often called a

decision support system My experience with the math

involved here goes back to the first days of Microsoft Excel

More recently, I put the concepts to work for the former

MacUser magazine in an application that assisted Macintosh

shoppers in selecting the right model for their needs Rather

than design a program that had limited appeal (covering only

one possible decision tree), I set out to make a completely

user-customizable decision helper All the user has to do is

enter values into fields on a number of screens; the program

performs the calculations to let the user know how the

various choices rank

Although I won’t be delving too deeply into the math

inside this application, it’s helpful to understand how a user

approaches this program and what the results look like The

basic scenario is a user who is trying to evaluate how well a

selection of choices measure up to his or her expectations of

performance User input includes the following:

✦ The name of the decision

✦ The names of up to five alternatives ( people, products,

ideas, and so on)

✦ The factors or features of concern to the user

✦ The importance of each of the factors to the user

✦ A user ranking of the performance of every alternative

Scripted image mapsScripted charts

✦ ✦ ✦ ✦

Trang 2

What makes this kind of application useful is that it forces the user to rate andweigh a number of often-conflicting factors By assigning hard numbers to theseelements, the user leaves the difficult process of figuring out the weights of variousfactors to the computer.

Results come in the form of floating-point numbers ranging from 0 to 100 As anextra touch, I’ve added a graphical charting component to the results display

The Design

With so much user input necessary for this application, conveying the illusion

of simplicity was important Rather than lump all text objects on a single scrollingpage, I decided to break them into five pages, each consisting of its own HTMLdocument As an added benefit, I could embed information from early screens intothe HTML of later screens, rather than having to create all changeable items out oftext objects This “good idea” presented one opportunity and one rather largechallenge

The opportunity was to turn the interface for this application into somethingresembling a multimedia application using multiple frames The largest framewould contain the forms the user fills out as well as the results page Anotherframe would contain a navigation panel with arrows for moving forward andbackward through the sequence of screens, plus buttons for going back to a homepage and getting information about the program I also thought a good idea would

be to add a frame that provides instructions or suggestions for the users at eachstep In the end, the design became a four-frame window, as shown in the firstentry screen in Figure 53-1

Figure 53-1: The Decision Helper window consists of four frames.

Trang 3

Using a navigation bar also enables me to demonstrate how to script a

client-side image map — not an obvious task with JavaScript

The challenge of this design was to find a way to maintain data globally as the

user navigates from screen to screen Every time one of the entry pages unloads,

none of its text fields are available to a script My first attack at this problem was to

store the data as global variable data (mostly arrays) in the parent document that

creates the frames Because JavaScript enables you to reference any parent

document’s object, function, or variable ( by preceding the reference with parent), I

thought this task would be a snap Unfortunately, Navigator 2 had a nasty bug that

affects the storage of parent variables that depend on data coming from their

children: if any child document unloads, the data gets jumbled The other hazard

here is that a reload of the frameset could erase the current state of those variables

My next hope was to use the document.cookieof the parent as the storage bin

for the data A major problem I faced was that this program needs to store a total

of 41 individual data points, yet you can allot no more than 20 cookies to a given

URL pathname But the cookie proved to be the primary solution for this

application (although see the “Further Thoughts” section at the end of the chapter

about a noncookie version) For some of the data points (that are related in an

array-like manner), I fashioned my own data structures so that one cookie could

contain up to five related data points That reduced my cookie demands to 17

The Files

Before I get into the code, let me explain the file structure of this application

Table 53-1 gives a rundown of the files used in the Decision Helper

Table 53-1

Files Comprising the Decision Helper Application

File Description

index.htm Framesetting parent document

dhNav.htm Navigation bar document that contains some scripting

dhNav.gif Image displayed in dhNav.htm

dhIcon.htm Document for lower-left corner frame

dhIcon.gif Icon image for lower-left frame

dh1.htm First Decision Helper entry page

dh2.htm Second Decision Helper entry page

dh3.htm Third Decision Helper entry page

dh4.htm Fourth Decision Helper entry page

dh5.htm Results page

chart.gif Tiny image file used to create bar charts in dh5.htm

dhHelp.htm Sample data and instructions document for lower-right frame

dhAbout.htm Document that loads into a second window

Trang 4

A great deal of interdependence exists among these files As you see later,assigning the names to some of these files is strategic for the implementation ofthe image map.

The Code

With so many JavaScript-enhanced HTML documents in this application, youcan expect a great deal of code To best grasp what’s going on here, first try tounderstand the structure and interplay of the documents, especially the way theentry pages rely on functions defined in the parent document My goal indescribing this structure is not to teach you how to implement this application,but rather to take the lessons I learned while building this application and applythem to the more complex ideas that may be aching to get out of your head andinto JavaScript

index.htm

Taking a top-down journey through the JavaScript and HTML of the DecisionHelper, start at the document that loads the frames Unlike a typical framesettingdocument, however, this one contains JavaScript code in its Head section — codethat many other documents rely on:

<SCRIPT LANGUAGE=”JavaScript”>

<! start // global variable settings of current dh document number var currTitle = “”

function setTitleVar(titleVal) {

currTitle = “” + titleVal }

function getCookieVal (offset) {

var endstr = document.cookie.indexOf (“;”, offset)

if ((“” + endstr) == “” || endstr == -1) endstr = document.cookie.length return unescape(document.cookie.substring(offset, endstr)) }

function getCookie (name) {

var arg = name + “=”;

Trang 5

var alen = arg.length;

var clen = document.cookie.length;

function setCookie (name, value) {

document.cookie = name + “=” + escape (value) + “;”

}

Because this application relies on the document.cookieso heavily, these

functions (slightly modified versions of Bill Dortch’s cookie functions — Chapter

16) are located in the parent document I simplified the cookie writing function

because this application uses default settings for pathname and expiration With

no expiration date, the cookies don’t survive the current Navigator session, which

is perfect for this application:

When this application loads (or a user elects to start a new decision), it’s

important to grab the cookies you need and initialize them to basic values that the

entry screens will use to fill entry fields when the user first visits them All

statements inside the initializeCookies()function call the setCookie()

function, defined in the preceding listing The parameters are the name of each

cookie and the initial value — mostly empty strings Before going on, study the

cookie structure carefully I refer to it often in discussions of other documents in

this application

Trang 6

The following functions should look familiar to you They were borrowed eitherwholesale or with minor modification from the data-entry validation section of theSocial Security number database lookup in Chapter 48 I’m glad I wrote these asgeneric functions, making them easy to incorporate into this script Because many

of the entry fields on two screens must be integers ranging from 1 to 100, I broughtthe data validation functions to the parent document rather than duplicating them

in each of the subdocuments:

// JavaScript sees numbers with leading zeros as octal values, so // strip zeros

function stripZeros(inputStr) {

var result = inputStr while (result.substring(0,1) == “0”) { result = result.substring(1,result.length) }

return result }

// general purpose function to see if a suspected numeric input // is a positive integer

function isNumber(inputStr) {

for (var i = 0; i < inputStr.length; i++) { var oneChar = charAt(i)

if (oneChar < “0” || oneChar > “9”) { return false

} } return true }

// function to determine if value is in acceptable range for this // application

function inRange(inputStr) {

num = parseInt(inputStr)

if (num < 1 || num > 100) { return false

} return true }

To control the individual data entry validation functions in the mastercontroller, I again was able to borrow heavily from the application in Chapter 48:

// Master value validator routine function isValid(inputStr) {

if (inputStr != “” ) { inputStr = stripZeros(inputStr)

if (!isNumber(inputStr)) { alert(“Please make sure entries are numbers only.”) return false

} else {

if (!inRange(inputStr)) { alert(“Entries must be numbers between 1 and 100 Try another value.”)

Trang 7

return false }

}

}

return true

}

Each of the documents containing entry forms retrieves and stores information

in the cookie Because all cookie functions are located in the parent document, it

simplifies coding in the subordinate documents to have functions in the parent

document acting as interfaces to the primary cookie functions For each category

of data stored as cookies, the parent document has a pair of functions for getting

and setting data The calling statements pass only the data to be stored when

saving information; the interface functions handle the rest, such as storing or

retrieving the cookie with the correct name

In the following pair of functions, the decision name (from the first entry

document) is passed back and forth between the cookie and the calling statement

Not only must the script store the data, but when the user returns to that screen

later for any reason, the entry field must retrieve the previously entered data:

The balance of the storage and retrieval pairs do the same thing for their

specific cookies Some cookies are named according to index values (factor1,

factor2, and so on), so their cookie-accessing functions require parameters for

determining which of the cookies to access, based on the request from the calling

statement Many of the cookie retrieval functions are called to fill in data in tables

of later screens during the user’s trip down the decision path:

Trang 8

function setPerformance(i,str) {

setCookie(“perf” + i,str) }

function getPerformance(i) {

return getCookie(“perf” + i) }

One sequence of code that runs when the parent document loads is the one thatlooks to see if a cookie structure is set up If no such structure is set up (theretrieval of a designated cookie returns a null value), the script initializes allcookies via the function described earlier:

if (getDecisionName() == null) {

initializeCookies() }

<FRAMESET COLS=”104,*”>

<FRAMESET ROWS=”250,*”>

<FRAME NAME=”navBar” SRC=”dhNav.htm” SCROLLING=no>

<FRAME NAME=”icon” SRC=”dhIcon.htm” SCROLLING=no>

dhNav.htm

Because of its crucial role in controlling the activity around this program, let’slook into the navigation bar’s document next To accomplish the look and feel of amultimedia program, this document was designed as a client-side image map thathas four regions scripted corresponding to the locations of the four buttons (seeFigure 53-1) One function is connected to each button

The first function is linked to the Home button For the listing here, I justpresent an alert dialog box replicating the action of navigating back to a real Website’s home page:

Trang 9

Each of the two arrow navigation buttons brings the user to the next or previous

entry screen in the sequence To facilitate this functionality without building tables

of document titles and names, you call upon the currTitleglobal variable in the

parent document This value contains an integer in the range of 1 through 5,

corresponding to the main content documents, dh1.htm, dh2.htm, and so on As

long as the offset number is no higher than the next-to-last document in the

sequence, the script increments the index value by one and concatenates a new

location for the frame At the same time, the script advances the help document

( lower-right frame) to the anchor corresponding to the chosen entry screen by

setting the location.hashproperty of that frame Similar action navigates to the

previous screen of the sequence This time, the index value is decremented by one,

and a dialog box appears when the current page is already the first in the sequence:

Clicking the Info button displays a smaller window containing typical About-box

data for the program ( Figure 53-2) In an earlier version of this application, the

script made two calls to the window.open()method to work around a Navigator 2

bug for the Mac and UNIX platforms:

Trang 10

Figure 53-2: The About Decision Helper

screen appears in a separate window

The Body of the document contains the part that enables you to script a side image map Using tags to define client-side image maps, as I do here, differsfrom the method used in the Netscape technical note in only one regard: thecontent of the HREF=attribute for each <AREA>tag Instead of pointing to anentirely new URL (the prescribed way), your attributes point to the JavaScriptfunctions defined in the Head portion of this document When a user clicks on therectangle specified by an <AREA>tag, the browser invokes the function instead

client-<BODY>

<MAP NAME=”navigation”>

<AREA SHAPE=”RECT” COORDS=”23,22,70,67” HREF=”javascript:goHome()”>

<AREA SHAPE=”RECT” COORDS=”25,80,66,116” HREF=”javascript:goNext()”>

<AREA SHAPE=”RECT” COORDS=”24,125,67,161” HREF=”javascript:goPrev()”>

<AREA SHAPE=”RECT” COORDS=”35,171,61,211” HREF=”javascript:goInfo()”>

<HTML>

<HEAD>

<TITLE>DH1</TITLE>

Trang 11

<SCRIPT LANGUAGE=”JavaScript”>

<! start

function loadDecisionName() {

var result = parent.getDecisionName()

result = (result == null) ? “” : result

After the document loads, it performs three tasks (in the onLoad=event

handler) The first task is to set the global variable in the parent to let it know

which number of the five main documents is currently loaded Next, the script

must fill the field with the decision name stored in the cookie This task is

important because users will want to come back to this screen to review what they

entered previously A third statement in the onLoad=event handler sets the focus

of the entire browser window to the one text object This task is especially

important in a multiframe environment such as with this design When a user

clicks on the navigation panel, that frame has the focus To begin typing into the

field, the user has to tab (repeatedly) or click it to bring the focus to the field By

setting the focus in the script when the document loads, you save the user time

<H4>Step 1 of 5: Type the name of the decision you’re making Then

click the “Next” arrow.</H4>

<P><P>

In the text field itself, an onChange=event handler saves the value of the field in

the parent’s cookie for the decision name No special Save button or other

instruction is necessary here because any navigation that the user does via the

navigation bar automatically causes the text field to lose focus and triggers the

onChange=event handler:

The copy of this file on the CD-ROM also has code that allows for plugging in

sample data (as seen on my Web site) and a textarea object that you can use for

debugging cookie data

Trang 12

For the second data-entry screen (shown in Figure 53-3), five fields invite the user toenter descriptions of the alternatives under consideration As with the decision namescreen, the scripting for this page must both retrieve and save data in the fields

In one function, the script retrieves the alternative cookies (five total) and stuffsthem into their respective text fields (as long as their values are not null) Thisfunction script uses a forloop to cycle through all five items — something thatmany scripts yet to come in this application frequently do Whenever a cookie isone of a set of five, the parent function has been written (in the following example)

to store or extract a single cookie, based on the index value Text objects holdinglike data (defined in the following listing) are all assigned the same name, so thatJavaScript lets you treat them as array objects — greatly simplifying the placement

of values into those fields inside a forloop

for (var i = 0; i < 5; i++) { var result = parent.getAlternative(i) result = (result == null) ? “” : result document.forms[0].alternative[i].value = result }

} // end >

</SCRIPT>

</HEAD>

Figure 53-3: The second data-entry screen

Ngày đăng: 16/10/2013, 12:15

TỪ KHÓA LIÊN QUAN