Приглашаем посетить
Чулков (chulkov.lit-info.ru)

Accessing Meta Information About the Document

Accessing Meta Information About the Document

In addition to providing access to the contents of the document, Dynamic HTML exposes information that is derived from the document while it is downloading. This meta information includes the initial file size of the document and the dates it was created, last modified, and last cached. Date information can be used to determine the age of the document to enable scripts to warn the user if the contents are out of date.

The document also exposes information about the client's cookies. Cookies are somewhat controversial because they allow a Web site to store a small piece of information on the client's machine that can later be referenced and updated by the site. This information is restricted in that the data can be accessed only by the Web sites that created the data.

While not really meta information, information about the state of any embedded object—including whether the downloading of the document or object is complete—is also exposed by the document. This information is essential when you are writing scripts that might execute before the page is completely available.

File Size

The document exposes a fileSize property that returns the initial size of the document in kilobytes. The returned value represents the number of bytes in the file that was downloaded and doesn't reflect any changes that scripts might have made to the document.

Title

The title property of the document is assigned a value in the HTML Head element as follows:

<HTML>
   <HEAD>
      <TITLE>Document Title</TITLE>
   </HEAD>
</HTML>

The title contains standard text; it cannot contain HTML. The document's title property returns the contents of the Title element as a string. You can assign a new value to this string to change the title displayed in the title bar. On windowed systems, the title is usually rendered as the window caption.


NOTE: Netscape Navigator 3.0 and Internet Explorer 3.0 generate an error when a page attempts to assign a value to the title property. Internet Explorer 4.0 exposes this property as read/write.

Source Location

The document exposes two properties that represent the source location for the page: location and URL. The location property on the document is an alias for the window's location property—both return objects that expose the same set of properties. Chapter 4, "The Browser Window," discusses the window's location property in detail.

The document's URL property is an alias to the href property on the location object. It is exposed for compatibility with earlier browsers. The location property on the window or document is useful for determining and changing the currently displayed page.

Date

Three dates are relevant for any document: the date the document was initially created, the date the document was last updated by the author, and the date the document was last downloaded into the cache. This information is exposed through the following properties on the document:

The fileCreatedDate property is self-explanatory. The remaining properties are described in the sections that follow.

The fileModifiedDate and lastModified Properties

The fileModifiedDate and lastModified properties both contain the date the document was last modified. The value of either property can be combined with information stored in the cookie property to check whether the document has changed since the user's last visit. Internet Explorer 3.0 and Netscape Navigator support the lastModified property, but they do not support fileModifiedDate. Internet Explorer 4.0 supports the new variation to maintain name consistency with the other meta information that is newly exposed in Dynamic HTML.

The following code outputs the date a file was last modified:

<HTML>
   <HEAD>
      <TITLE>Last Modified Date</TITLE> 
   </HEAD>
   <BODY>
      <P>Last Modified:
         <SCRIPT LANGUAGE="JavaScript">
            document.write(document.lastModified);
         </SCRIPT>
      </P>
   </BODY>
</HTML>

The write method is used to write into the stream of the document while the page is loaded. This technique is discussed in greater detail in the section "Writing HTML into the Stream" later in this chapter.

The fileUpdatedDate Property

During browsing, files may become cached on the local user's machine. The fileUpdatedDate property returns the date the file was last updated from the server. Using this property, you can write code that notifies the user if he or she is using a page that has existed in the cache for more than a specified amount of time:

<HTML>
   <HEAD>
      <TITLE>fileUpdatedDate Example</TITLE>
      <SCRIPT LANGUAGE="JavaScript">
         /* Number of days that can elapse before 
            a new page is requested. */
         var intAge = 7;

         // Be sure there is an updated date.
         if ("" != document.fileUpdatedDate) {
            var dCreate = new Date(document.fileUpdatedDate);
            var dToday = new Date();
            /* Calculate number of days elapsed. getTime 
               returns the number of milliseconds between
               midnight (GMT) on 1/1/1970 and the supplied 
               date and time. */
            var intDays = Math.floor((dToday.getTime() 
               - dCreate.getTime()) / (1000 * 60 * 60 * 24));
            if (intAge < intDays) 
               if (confirm("Your cached page is " + intDays + 
                  " day(s) old.\n"
                  + "Do you want to download a new page?"))
                  // Force a reload from the server.
                  location.reload(true);  
         } 
      </SCRIPT>
   </HEAD>
   <BODY>
      Document contents
   </BODY>
</HTML>

MIME Type

The mimeType property returns the document's MIME type. For all HTML documents (including framesets), the mimeType property returns the value Internet Document (HTML).

Cookies

An HTML page has the ability to save a small amount of information in a special file on the client's machine. This information is called a cookie. Many people consider cookies to be a potential security risk because cookies allow a page to write to the hard disk; browsers offer a way to disable this functionality. For this reason, no page should be written with the assumption that cookies are available. When they are supported, however, cookies are useful for maintaining state information used by multiple pages on the same site.

Assigning a value to a cookie is different from retrieving the value. This section shows you how to use cookies and provides helper functions for manipulating them. At the end of the section is a demonstration of using a cookie to create a client-side visit counter.


NOTE: Internet Explorer 3.0 did not allow cookies to be modified when the page was accessed using the file: protocol. This limitation was removed in Internet Explorer 4.0.

Reading the Cookie

Multiple cookies can be associated with a single document or domain. When the cookie property is read, all the cookies associated with the document are returned as a semicolon-delimited list of name-value pairs. Therefore, a routine is needed that can parse a list of cookies. JavaScript exposes some useful methods for easily splitting delimited lists into arrays. The following function uses these methods to parse the cookie string and return it as an array of name-value pairs:

<SCRIPT LANGUAGE="JavaScript">
   function parseCookie() {
      // Separate each cookie.
      var cookieList = document.cookie.split("; ");
      // Array for each cookie in cookieList
      var cookieArray = new Array();
      for (var i = 0; i < cookieList.length; i++) {
         // Separate name-value pairs.
         var name = cookieList[i].split("=");
         // Decode and add to cookie array.
         cookieArray[unescape(name[0])] = unescape(name[1]);
      }
      return cookieArray;
   }
</SCRIPT>

The following code demonstrates how to use the cookie array that parseCookie returns:

var cookie;
var cookies = parseCookie();
// Output each cookie.
for (cookie in cookies)
   alert(cookie + "=" + cookies[cookie]);
// Check whether a cookie named foo exists.
if (null == cookies.foo) {
   // No cookie named foo
}

The name-value pairs you assign to cookies cannot contain white spaces, commas, or semicolons. Any such characters must be replaced with appropriate escape sequences. JavaScript provides two convenient functions that handle escape sequences for you: escape, for replacing characters by escape sequences in a string before assigning it to a cookie, and unescape, for reversing the operation when retrieving the cookie.

A stored cookie also contains expiration date, path, domain, and security information. You can supply this information when you create a cookie, but you can't retrieve it. This is one of the differences between assigning values to a cookie and retrieving the cookie.

Writing a Cookie

The cookie property takes a string value in the following format:

name=value; [expires=date; [path=path; [domain=domain [secure;]]]]

The name-value pair is the only required parameter when you assign information to the cookie. The name can be any valid string with which to associate a value. Supplying a name-value pair without any of the additional information creates a cookie that lasts only for the length of the current browser session. For example, the following code creates a simple cookie that stores the time and date a page was loaded:

<SCRIPT LANGUAGE="JavaScript">
   var strLoaded = new Date();
   document.cookie = "Loaded=" + escape(strLoaded);
</SCRIPT>

Assigning another value to the cookie does not necessarily overwrite the cookie—it overwrites the cookie only if you use the same name. In the preceding example, the name Loaded would be reused each time the page was loaded. In the following example, adding a new name adds a new entry to the cookie.

<SCRIPT LANGUAGE="JavaScript">
   document.cookie = "First=Hello;";
   document.cookie = "Second=Hello;";
   alert(document.cookie);   // First=Hello; Second=Hello
</SCRIPT>

To force a cookie to be deleted, you must specify an expiration date. To delete a cookie, create a new cookie using an existing name and any arbitrary value, but assign an expiration date that has already passed. When you use this technique, the cookie might not be immediately removed—it might remain until the current instance of the browser is shut down.

The expiration date must be specified in GMT in the following format:

wkd, day Mon Year hh:mm:ss GMT

For example, the following date has this format:

Sat, 28 Sep 1998 19:01:05 GMT

In JavaScript, the easiest way to convert to GMT is to use the toGMTString method exposed on the Date object.

If you set an expiration date in the future, the cookie will remain on the client's machine until it expires. There is no guarantee that supplying an expiration date will keep the cookie around because there is a limit to how many cookies the client can store and the user may at any time delete the cookie file.

By default, all cookies are saved with a path and domain, even if these settings are not specified explicitly. This is how security is maintained on the cookie. A cookie is accessible only to the path and domain that created it. Furthermore, when you create a cookie, you cannot specify an arbitrary domain. This restriction eliminates the possibility of secretly transferring information from one domain to another. However, multiple pages from the same domain can share a single cookie.

Using the Cookie

A cookie can be used to create custom pages for the user. The following code demonstrates how to use a cookie to count the number of times the user has visited a Web page. The code uses the parseCookie function introduced earlier.

<HTML>
   <HEAD>
      <TITLE>Cookie Counter</TITLE>
   </HEAD>
   <BODY>
      <SCRIPT LANGUAGE="JavaScript">
         // This code requires the parseCookie function.

         function setCookie(visits) {
            /* This routine sets up the cookie by setting its value
               to the number of visits and setting its expiration date
               to 1 year from now. */
            var expireDate = new Date();
            var today = new Date();
            // Set an expiration date in the future.
            expireDate.setDate(365 + expireDate.getDate());

            // Save the number of visits.
            document.cookie = "Visits=" + visits + "; expires=" +
               expireDate.toGMTString() + ";";
   
            // Save today's time and date as the last visit.
            document.cookie = "LastVisit=" + 
               escape(today.toGMTString()) + 
               "; expires=" + expireDate.toGMTString() + ";";
         }

         if ("" == document.cookie) {
            // Initialize the cookie.
            setCookie(1);
            document.write("<H2>This is your first visit to our " +
               "humble home page.</H2>");
         }
         else {
            // Parse the cookie.
            var cookies = parseCookie();

            // Output the Welcome Back message, and increment the 
            // visit counter.
            document.write("<H2>Welcome Back! You have visited us " +
               cookies.Visits++ + " time(s)!</H2>");
            document.write("<H3>Your last visit was on " + 
               cookies.LastVisit + ".</H3>");
            // Replace existing cookie with an updated one.
            setCookie(cookies.Visits);
         }
      </SCRIPT>
   </BODY>
</HTML>

Parent Window

Just as you can navigate from the window to the document, you can navigate from the document back to its containing window. The window containing the document is exposed through the parentWindow property. This property is useful for determining the containing object when only the document object is available.

Two additional properties are available for accessing the window from the document: Script and frames. The Script property is exposed for backward compatibility with Internet Explorer 3.0 and should no longer be used. The frames property returns a collection of inline frames in the document. This frames collection returns the window because it is an alias to the window's frames collection, which in turn is an alias to the window object. Manipulating collections is discussed in more detail in Chapter 7, "Document Element Collections." To clarify the relationships between these properties, the following code demonstrates several ways of returning the same window object:

window == self == window.frames == frames == 
   window.document.parentWindow == window.document.Script == 
   window.document.frames

Document Availability

As it loads, a document or an embedded object progresses through four states: uninitialized, loading, interactive, and complete. The object's readyState property contains the object's current state. When the object changes state, it fires an onreadystatechange event. By using these tools in your scripts, you can make your page behave appropriately for the states of the document and embedded objects and react to changes in states. Most important, your code can avoid accessing objects that haven't completely downloaded.

The following table describes the states that the document and embedded objects progress through.


State Description
uninitialized The page or object is not yet initialized. Once it starts loading, it immediately progresses to the loading state.
loading The page or object is currently being loaded.
interactive The user can interact with the page or object even though it is still loading—for example, anchors may be live and loaded elements may begin to fire events.
complete The page or object is entirely loaded.

When the document begins loading, it immediately progresses to the loading state. It progresses to the interactive state when the browser encounters the first Script, Body, or Frameset element. The document progresses to the complete state when the entire document is parsed and all embedded objects are loaded.

The readyState Property

The document's readyState property contains the current state of the document as a string. Each embedded object has its own readyState property reflecting its own status.

Because a document will be in the interactive state before any of its scripts execute, the only readyState values its scripts will obtain are interactive and complete. A script in another frame or window might obtain a value of loading; this will happen if the script accesses the document's readyState property during the parsing of the document's Head element and before any scripts in the Head element have been encountered. Any script might obtain any of the four values as the readyState of an embedded object.

JavaScript event handlers are hooked up asynchronously during the parsing of the page. Such a handler might execute before the entire page is loaded. If the handler performs operations that require the page to be fully downloaded, it can test the document's readyState property before proceeding, as shown in the following example:

<SCRIPT LANGUAGE="JavaScript" EVENT="onclick" FOR="window">
   if ("complete" == document.readyState) {
      // Handle the event.
   }
   else
      alert("This action is not available until the document " +
         "finishes downloading.");
</SCRIPT>

Alternatively, the handler can test the readyState properties of only those elements it needs to access.

VBScript event handlers are hooked up as a last step before the document progresses to the complete state. Therefore, handlers written in VBScript don't need to test the document's readyState—except, of course, if a handler accesses elements in another document.

The onreadystatechange Event

The onreadystatechange event fires whenever the state of the document or of an embedded object changes. Each of these events can fire multiple times during the downloading of a document or an element.

If you bind a handler to the document's onreadystatechange event, the handler will not be hooked up until the document is already in the interactive state. Your handler will be called only once—namely, for the document's transition to the complete state. In this situation, the onreadystatechange event is essentially an alias for the window's onload event, and the two can be used interchangeably. Because Internet Explorer 4.0 is the only browser currently supporting onreadystatechange, you can use this event if you want to exclude other browsers; you can use the onload event if you want cross-browser execution.

Embedded objects in the document also fire the onreadystatechange event. For example, the Object and IMG elements have onreadystatechange events. For these elements, your code can receive the event for several state transitions, depending on when the event handler is hooked up. In general, however, you should not write code that depends on any state transition to occur other than the transition to the complete state.

[Содержание]