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

JavaScript Bible, Gold Edition part 114 pot

10 48 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 115,85 KB

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

Nội dung

Perhaps you need to calculate a date at some fixed number of days or weeks in the future or figure out the number of days between two dates.. Here is an example that establishes some pra

Trang 1

Date and time arithmetic

You may need to perform some math with dates for any number of reasons Perhaps you need to calculate a date at some fixed number of days or weeks in the future or figure out the number of days between two dates When calculations of

these types are required, remember the lingua franca of JavaScript date values:

milliseconds

What you may need to do in your date-intensive scripts is establish some variable values representing the number of milliseconds for minutes, hours, days, or weeks, and then use those variables in your calculations Here is an example that establishes some practical variable values, building on each other:

var oneMinute = 60 * 1000 var oneHour = oneMinute * 60 var oneDay = oneHour * 24 var oneWeek = oneDay * 7

With these values established in a script, I can use one to calculate the date one week from today:

var targetDate = new Date() var dateInMs = targetDate.getTime() dateInMs += oneWeek

targetDate.setTime(dateInMs)

Another example uses components of a date object to assist in deciding what kind of greeting message to place in a document, based on the local time of the user’s PC clock Listing 36-2 adds to the scripting from Listing 36-1, bringing some quasi-intelligence to the proceedings Again, this script uses the older array creation mechanism to be compatible with Navigator 2 and Internet Explorer 3

Listing 36-2: A Dynamic Welcome Message

<HTML>

<HEAD>

<TITLE>Date String Maker</TITLE>

<SCRIPT LANGUAGE=”JavaScript”>

function MakeArray(n) { this.length = n return this }

monthNames = new MakeArray(12) monthNames[1] = “January”

monthNames[2] = “February”

monthNames[3] = “March”

monthNames[4] = “April”

monthNames[5] = “May”

monthNames[6] = “June”

monthNames[7] = “July”

monthNames[8] = “August”

monthNames[9] = “September”

monthNames[10] = “October”

monthNames[11] = “November”

monthNames[12] = “December”

Trang 2

dayNames = new MakeArray(7)

dayNames[1] = “Sunday”

dayNames[2] = “Monday”

dayNames[3] = “Tuesday”

dayNames[4] = “Wednesday”

dayNames[5] = “Thursday”

dayNames[6] = “Friday”

dayNames[7] = “Saturday”

function customDateString(oneDate) {

var theDay = dayNames[oneDate.getDay() + 1]

var theMonth = monthNames[oneDate.getMonth() + 1]

var theYear = oneDate.getYear()

theYear += (theYear < 100) ? 1900 : 0

return theDay + “, “ + theMonth + “ “ + oneDate.getDate() + “, “ + theYear

}

function dayPart(oneDate) {

var theHour = oneDate.getHours()

if (theHour <6 )

return “wee hours”

if (theHour < 12)

return “morning”

if (theHour < 18)

return “afternoon”

return “evening”

}

</SCRIPT>

</HEAD>

<BODY>

<H1> Welcome!</H1>

<SCRIPT LANGUAGE=”JavaScript”>

today = new Date()

var header = (customDateString(today)).italics()

header += “<BR>We hope you are enjoying the “

header += dayPart(today) + “.”

document.write(header)

</SCRIPT>

<HR>

</BODY>

</HTML>

The script divides the day into four parts and presents a different greeting for

each part of the day The greeting that plays is based, simply enough, on the hour

element of a date object representing the time the page is loaded into the browser

Because this greeting is embedded in the page, the greeting does not change no

matter how long the user stays logged on to the page

Counting the days

You may find one or two more date arithmetic applications useful One displays

the number of shopping days left until Christmas (in the user’s time zone); the

other is a countdown timer to the start of the year 2100

Trang 3

Listing 36-3 demonstrates how to calculate the number of days between the current day and some fixed date in the future The assumption in this application is that all calculations take place in the user’s time zone The example shows the display of the number of shopping days before the next Christmas day (December 25) The basic operation entails converting the current date and the next December

25 to milliseconds, calculating the number of days represented by the difference in milliseconds If you let the millisecond values represent the dates, JavaScript auto-matically takes care of leap years

The only somewhat tricky part is setting the year of the next Christmas day correctly You can’t just slap the fixed date with the current year, because if the program is run on December 26, the year of the next Christmas must be incremented

by one That’s why the constructor for the Christmas date object doesn’t supply a fixed date as its parameters but, rather, sets individual components of the object

Listing 36-3: How Many Days Until Christmas

<HTML>

<HEAD>

<TITLE>Christmas Countdown</TITLE>

<SCRIPT LANGUAGE=”JavaScript”>

function getDaysUntilXmas() { var oneMinute = 60 * 1000 var oneHour = oneMinute * 60 var oneDay = oneHour * 24 var today = new Date() var nextXmas = new Date() nextXmas.setMonth(11) nextXmas.setDate(25)

if (today.getMonth() == 11 && today.getDate() > 25) { nextXmas.setFullYear(nextXmas.getFullYear() + 1) }

var diff = nextXmas.getTime() - today.getTime() diff = Math.floor(diff/oneDay)

return diff }

</SCRIPT>

</HEAD>

<BODY>

<H1>

<SCRIPT LANGUAGE=”JavaScript”>

var header = “You have <I>” + getDaysUntilXmas() + “</I> “ header += “shopping days until Christmas.”

document.write(header)

</SCRIPT>

</H1><HR>

</BODY>

</HTML>

Trang 4

The second variation on calculating the amount of time before a certain event

takes time zones into account For this demonstration, the page is supposed to

display a countdown timer to the precise moment when the flame for the 2004

Summer Games in Athens is to be lit That event takes place in a time zone that

may be different from that of the page’s viewer, so the countdown timer must

calculate the time difference accordingly

Listing 36-4 shows a simplified version that simply displays the ticking timer in

a text field The output, of course, could be customized in any number of ways,

depending on the amount of dynamic HTML you want to employ on a page The

time of the lighting for this demo is set at 17:00 GMT on August 13, 2004 (the date

is certainly accurate, but the officials may set a different time closer to the actual

event)

Because this application is implemented as a live ticking clock, the code starts

by setting some global variables that should be calculated only once so that the

function that gets invoked repeatedly has a minimum of calculating to do (to be

more efficient) The Date.UTC()method provides the target time and date in

standard time The getTimeUntil()function accepts a millisecond value (as

provided by the targetDatevariable) and calculates the difference between the

target date and the actual internal millisecond value of the client’s PC clock

The core of the getCountDown()function peels off the number of whole days,

hours, minutes, and seconds from the total number of milliseconds difference

between now and the target date Notice that each chunk is subtracted from the

total so that the next smaller chunk can be calculated from the leftover milliseconds

One extra touch on this page is that users of Windows operating systems have a

display of the local date and time of the actual event The Mac is excluded because

it does not provide accurate daylight saving time adjustments for local dates Some

UNIX flavors may do the right thing, but they were not tested for this example

Listing 36-4: Summer Games Countdown

<HTML>

<HEAD>

<TITLE>Summer Games Countdown</TITLE>

<SCRIPT LANGUAGE=”JavaScript”>

// globals calculate only once

// set target date to 1700GMT on August 13, 2004

var targetDate = Date.UTC(2004, 7, 13, 17, 0, 0, 0)

var oneMinute = 60 * 1000

var oneHour = oneMinute * 60

var oneDay = oneHour * 24

function getTimeUntil(targetMS) {

var today = new Date()

var diff = targetMS - today.valueOf()

return Math.floor(diff)

}

function getCountDown() {

var ms = getTimeUntil(targetDate)

var output = “”

var days, hrs, mins, secs

if (ms >= 0) {

Continued

Trang 5

Listing 36-4 (continued)

days = Math.floor(ms/oneDay)

ms -= oneDay * days hrs = Math.floor(ms/oneHour)

ms -= oneHour * hrs mins = Math.floor(ms/oneMinute)

ms -= oneMinute * mins secs = Math.floor(ms/1000) output += days + “ Days, “ +

hrs + “ Hours, “ + mins + “ Minutes, “ + secs + “ Seconds”

} else { output += “The time has passed.”

} return output }

function updateCountDown() { document.forms[0].timer.value = getCountDown() setTimeout(“updateCountDown()”, 1000)

}

</SCRIPT>

</HEAD>

<BODY onLoad=”updateCountDown()”>

<H1>Athens Games Torch Lighting Countdown</H1>

<P>

<SCRIPT LANGUAGE=”JavaScript”>

if (navigator.userAgent.indexOf(“Win”) >= 0) { document.write(“(“ + (new Date(targetDate)).toLocaleString()) document.write(“ in your time zone.)”)

}

</SCRIPT>

</P>

<FORM>

<INPUT TYPE=”text” NAME=”timer” SIZE=60>

</FORM>

<HR>

</BODY>

</HTML>

Date bugs and gremlins

Each new browser generation improves the stability and reliability of scripted date objects Unfortunately, Navigator 2 has enough bugs and crash problems across many platforms to make scripting complex world-time applications for this browser impossible The Macintosh version also has bugs that throw off dates by

as much as a full day I recommend avoiding NN2 on all platforms for serious date and time scripting

Trang 6

The situation is much improved for NN3 Still, some bugs persist One bug in

particular affects Macintosh versions of NN3 Whenever you create a new date

object with daylight saving time engaged in the Date and Time control panel, the

browser automatically adds one hour to the object See the time-based application

in Chapter 54 for an example of how to counteract the effects of typical time bugs

Also afflicting the Macintosh in NN3 is a faulty calculation of the time zone offset for

all time zones east of GMT Instead of generating these values as negative numbers

(getting lower and lower as you head east), the offset values increase continuously

as you head west from Greenwich While the Western Hemisphere is fine, the values

continue to increase past the international date line, rather than switch over to the

negative values

Internet Explorer 3 isn’t free of problems It cannot handle dates before January

1, 1970 (GMT) Attempts to generate a date before that one result in that base date

as the value IE3 also completely miscalculates the time zone offset, following the

erroneous pattern of Navigator 2 Even Navigators 3 and 4 have problems with

historic dates You are asking for trouble if the date extends earlier than January 1,

A.D 1 Internet Explorer 4, on the other hand, appears to sail very well into ancient

history

You should be aware of one more discrepancy between Mac and Windows

versions of Navigator through Version 4 In Windows, if you generate a date object

for a date in another part of the year, the browser sets the time zone offset for that

object according to the time zone setting for that time of year On the Mac, the

current setting of the control panel governs whether the normal or daylight saving

time offset is applied to the date, regardless of the actual date within the year This

discrepancy affects Navigator 3 and 4 and can throw off calculations from other

parts of the year by one hour

It may sound as though the road to Dateobject scripting is filled with land mines

While date and time scripting is far from hassle free, you can put it to good use with

careful planning and a lot of testing

Validating Date Entries in Forms

Given the bug horror stories in the previous section, you may wonder how you

can ever perform data entry validation for dates in forms The problem is not so

much in the calculations as it is in the wide variety of acceptable date formats

around the world No matter how well you instruct users to enter dates in a

particular format, many will follow their own habits and conventions Moreover,

how can you know whether an entry of 03/04/2002 is the North American March 4,

2002, or the European April 3, 2002? The answer: You can’t

My recommendation is to divide a date field into three components: month, day,

and year Let the user enter values into each field and validate each field individually

for its valid range Listing 36-5 shows an example of how this is done The page

includes a form that is to be validated before it is submitted Each component field

does its own range checking on the fly as the user enters values But because this

kind of validation can be defeated, the page includes one further check triggered by

the form’s onSubmitevent handler If any field is out of whack, the form submission

is canceled

Trang 7

Listing 36-5: Date Validation in a Form

<HTML>

<HEAD>

<TITLE>Date Entry Validation</TITLE>

<SCRIPT LANGUAGE=”JavaScript”>

<! // **BEGIN GENERIC VALIDATION FUNCTIONS**

// general purpose function to see if an input value has been entered at all function isEmpty(inputStr) {

if (inputStr == “” || inputStr == null) { return true

} return false }

// function to determine if value is in acceptable range for this application function inRange(inputStr, lo, hi) {

var num = parseInt(inputStr, 10)

if (num < lo || num > hi) { return false

} return true }

// **END GENERIC VALIDATION FUNCTIONS**

function validateMonth(field, bypassUpdate) { var input = field.value

if (isEmpty(input)) { alert(“Be sure to enter a month value.”) select(field)

return false } else {

input = parseInt(field.value, 10)

if (isNaN(input)) { alert(“Entries must be numbers only.”) select(field)

return false } else {

if (!inRange(input,1,12)) { alert(“Enter a number between 1 (January) and 12 (December).”) select(field)

return false }

} }

if (!bypassUpdate) { calcDate() }

return true }

function validateDate(field) { var input = field.value

Trang 8

if (isEmpty(input)) {

alert(“Be sure to enter a date value.”)

select(field)

return false

} else {

input = parseInt(field.value, 10)

if (isNaN(input)) {

alert(“Entries must be numbers only.”)

select(field)

return false

} else {

var monthField = document.birthdate.month

if (!validateMonth(monthField, true)) return false

var monthVal = parseInt(monthField.value, 10)

var monthMax = new Array(31,31,29,31,30,31,30,31,31,30,31,30,31)

var top = monthMax[monthVal]

if (!inRange(input,1,top)) {

alert(“Enter a number between 1 and “ + top + “.”) select(field)

return false }

}

}

calcDate()

return true

}

function validateYear(field) {

var input = field.value

if (isEmpty(input)) {

alert(“Be sure to enter a year value.”)

select(field)

return false

} else {

input = parseInt(field.value, 10)

if (isNaN(input)) {

alert(“Entries must be numbers only.”)

select(field)

return false

} else {

if (!inRange(input,1900,2005)) {

alert(“Enter a number between 1900 and 2005.”) select(field)

return false }

}

}

calcDate()

return true

}

function select(field) {

field.focus()

field.select()

}

Continued

Trang 9

Listing 36-5 (continued)

function calcDate() { var mm = parseInt(document.birthdate.month.value, 10) var dd = parseInt(document.birthdate.date.value, 10) var yy = parseInt(document.birthdate.year.value, 10) document.birthdate.fullDate.value = mm + “/” + dd + “/” + yy }

function checkForm(form) {

if (validateMonth(form.month)) {

if (validateDate(form.date)) {

if (validateYear(form.year)) { return true

} } } return false }

// >

</SCRIPT>

</HEAD>

<BODY>

<FORM NAME=”birthdate” ACTION=”mailto:fun@dannyg.com” METHOD=POST onSubmit=”return checkForm(this)”>

Please enter your birthdate <BR>

Month:<INPUT TYPE=”text” NAME=”month” VALUE=1 SIZE=2 onChange=”validateMonth(this)”>

Date:<INPUT TYPE=”text” NAME=”date” VALUE=1 SIZE=2 onChange=”validateDate(this)”>

Year:<INPUT TYPE=”text” NAME=”year” VALUE=1900 SIZE=4 onChange=”validateYear(this)”>

<P>

Thank you for entering:<INPUT TYPE=”text” NAME=”fullDate” SIZE=10><P>

<INPUT TYPE=”submit”> <INPUT TYPE=”Reset”>

</FORM>

</BODY>

</HTML>

The page shows the three entry fields as well as a field that is normally hidden

on a form to be submitted to a CGI program On the server end, the CGI program responds only to the hidden field with the complete date, which is in a format for entry into, for example, an Informix database

Not every date entry validation must be divided in this way For example, an intranet application can be more demanding in the way users are to enter data Therefore, you can have a single field for date entry, but the parsing required for such a validation is quite different from that shown in Listing 36-5 See Chapter 43 for an example of such a one-field date validation routine

Trang 10

The Array Object

An array is the sole JavaScript data structure provided

for storing and manipulating ordered collections of

data But unlike some other programming languages,

JavaScript’s arrays are very forgiving as to the kind of data

you store in each cell or entry of the array This allows, for

example, an array of arrays, providing the equivalent of

multi-dimensional arrays customized to the kind of data your

appli-cation needs

If you have not done a lot of programming in the past, the

notion of arrays may seem like an advanced topic But if you

ignore their capabilities, you set yourself up for a harder job

when implementing many kinds of tasks Whenever I

approach a script, one of my first thoughts is about the data

being controlled by the application and whether handling it as

an array will offer some shortcuts for creating the document

and handling interactivity with the user

I hope that by the end of this chapter, you will not only be

familiar with the properties and methods of JavaScript arrays,

but you will begin to look for ways to make arrays work for you

Structured Data

In programming, an array is defined as an ordered

collec-tion of data You can best visualize an array as a table, not

much different from a spreadsheet In JavaScript, arrays are

limited to a table holding one column of data, with as many

rows as needed to hold your data As you have seen in many

chapters in Part III, a JavaScript-enabled browser creates a

number of internal arrays for the objects in your HTML

docu-ments and browser properties For example, if your document

contains five links, the browser maintains a table of those

links You access them by number (with 0 being the first link)

in the array syntax: the array name is followed by the index

number in square brackets, as in document.links[0], which

represents the first link in the document

For many JavaScript applications, you will want to use an

array as an organized warehouse for data that users of your

page access, depending on their interaction with form

ele-ments In the application shown in Chapter 50, for example, I

demonstrate an extended version of this usage in a page that

lets users search a small table of data for a match between the

37

In This Chapter

Working with ordered collections of data

Simulating multidimensional arrays

Manipulating information stored in

an array

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