Приглашаем посетить
Пушкин (pushkin-lit.ru)

Dynamic Contents and document.write

Dynamic Contents and document.write

The dynamic contents model is a powerful tool for manipulating a loaded document, but it does not completely eliminate the need for the document.write method. In fact, these two features complement each other extremely well. In the following examples, dynamic contents techniques are used to locate specific text that is then output into a new window using the document.write method. The first scenario creates a banner frame when the document is contained within a frameset, and the second scenario demonstrates two techniques for indexing a page.

Creating a Header Bar

Web authors have long desired a feature whereby an HTML page can supply a banner to be displayed in a header bar above it. In earlier browsers, this feature could only be simulated by creating a frameset that loads two files at a time, one file for the document and another file for its banner. Using two files per document adds complexity as the files need to be synchronized. The following code simplifies matters by including the banner in the document's contents. If the page is loaded outside a frameset, the code displays the banner inside the document, so no document fidelity is lost.

<HTML>
   <HEAD>
      <TITLE>Banner Document</TITLE>
      <STYLE TYPE="text/css">  
         DIV#bannerContents {display:none}
      </STYLE>
      <SCRIPT LANGUAGE="JavaScript">
         function outputBanner() {
            if (null != parent.frames[0]) {
               parent.frames[0].document.open();
               parent.frames[0].document.write(
                  document.all.bannerContents.outerHTML);
               parent.frames[0].document.close();
            }
            else  // Not in a frameset; turn on the banner.
               document.all.bannerContents.style.display = "block";
         }

         window.onload = outputBanner;
      </SCRIPT>
   </HEAD>
   <BODY>
      <DIV ID=bannerContents>
         <H1>Inside Dynamic HTML</H1>
      </DIV>
      <P><EM>Inside Dynamic HTML</EM> teaches the Web developer 
         how to create interactive and live Web pages.</P>
   </BODY>
</HTML>

The contents of the banner DIV can be any HTML, including scripts. The entire contents will be copied to the other frame.

To complete this example, the following frameset document contains code that automatically sizes the frameset once the banner is loaded. This code changes the dimensions of the rows by assigning the scrollHeight property of the banner to the height of the frame so that the banner frame is appropriately sized.

<HTML>
   <HEAD>
      <TITLE>Banner Frameset</TITLE>
      <SCRIPT LANGUAGE="JavaScript">
         function fixup() {
            // Auto-size banner frame.
            document.all.FS.rows =
               window.frames.Banner.document.body.scrollHeight +
               ", *";
         }

         window.onload = fixup;
      </SCRIPT>
   </HEAD>
   <FRAMESET ROWS="100, *" ID="FS" FRAMEBORDER=0>
      <FRAME NAME="Banner" SCROLLING=NO NORESIZE>
      <FRAME SRC="Banner.htm">
   </FRAMESET>
</HTML>

This frameset code sizes the header bar for the first document that loads, but it doesn't automatically resize the header bar when the user navigates to another page that has a different size banner. You can add code to such other pages to call the parent window's fixup function to resize the header bar.

Enhanced Indexes and Tables of Contents

The most common use of framesets is to display a list of document options in one frame and the selected document in another frame. The following examples demonstrate more interesting uses of framesets. The first example automatically generates an anchor index, and the second example automatically generates a table of contents. The index or table of contents is best displayed in a sibling frame.

The first example includes custom code to determine where to display the index. If the document is loaded inside a frameset and a sibling frame has the ID menu, the document displays the index in that frame. Otherwise, the document opens a new window to display the index. The second example includes similar code to determine where to display the table of contents.

Link and Bookmark Indexes

The following quick indexer example creates an index window containing copies of all the document's Anchor elements. The code uses each anchor's innerHTML property to copy its contents so that images can be appropriately rendered in the index window.

<HTML>
   <HEAD>
      <TITLE>Auto Indexing</TITLE>
      <SCRIPT LANGUAGE="JavaScript">  
         function setupIndex() {
            // Open new window.
            var winIndex = null;
   
            /* If in a frameset and a menu frame exists, output to
               that frame; otherwise, output to a new window. */
            if (window.parent != self)
               if (null != parent.menu)
                  winIndex = parent.menu;
            if (null == winIndex)
               winIndex = window.open("", "Index",
                  "width=300; height=500");
            // Start writing index document.
            winIndex.document.open();
            winIndex.document.write("<HTML>");
            winIndex.document.write("<TITLE>Index</TITLE>");

            // Determine the base HREF and base target.
            var baseHREF = null;
            var baseTarget = null;
            // Check whether any <BASE> tags are present in
            // the document.
            var base = document.all.tags("BASE");
            for (var i = 0; i < base.length; i++) {
               // Retrieve the base HREF and target if specified.
               if (null != base[i].href)
                  baseHREF = base[i].href;
               if (null != base[i].target)
                  baseTarget = base[i].target;
            }
  
            // Set up window name to act as target if no base exists.
            if ((null == baseTarget) || ("" == baseTarget)) {
               if ("" == window.name)  
                  window.name = "outputhere";
               baseTarget = window.name;
            }
  
            // If base HREF doesn't exist, set to current path.
            if ((null == baseHREF) || ("" == baseHREF)) {
               baseHREF = location.protocol + location.pathname;
            }

            // Output base into window.
            winIndex.document.writeln("<BASE TARGET=" +
               "`" + baseTarget + "`" + "HREF=`" + baseHREF + "`>");
            winIndex.document.writeln("<H1>Links</H1>");
            // innerHTML is used so that images and rich HTML
            // are automatically retrieved.
            // Enumerate all Anchor elements; skip image maps.
            for (var i = 0; i < document.links.length; i++) {
               var el = document.links[i];
               if ("A" == el.tagName) {
                  var hText = el.outerHTML;
                  winIndex.document.writeln("<P>" + hText);
               }
            }

            winIndex.document.writeln("<H1>Bookmarks</H1>");
            // Enumerate all bookmarks.
            for (var i = 0; i < document.anchors.length; i++) {
               var el = document.anchors[i];
               if ("A" == el.tagName) {
                  var hText = el.innerHTML;
                  winIndex.document.writeln(
                     "<P><A HREF=`#" + el.name + "`>" + hText +
                     "</A>");
               }
            }
            
            winIndex.document.close();
         }
         window.onload = setupIndex;
      </SCRIPT>
   </HEAD>
   <BODY>
      <H1><A NAME="top">Auto Indexing</A></H1>
      <H2><A NAME="links">Link Demonstrations</A></H2>
      <P>The following links will appear in the link index:</P>
      <P><A HREF="http://www.insideDHTML.com">Inside Dynamic HTML</A>
      <P><A HREF="http://www.microsoft.com">Microsoft's Web Site</A>
      <P>Images also work:
      <P><A HREF="http://www.insideDHTML.com"><IMG SRC="open.gif"></A>
      <P>Rich HTML anchors are automatically picked up:
      <P><A HREF="http://www.insideDHTML.com">Inside <EM>Dynamic</EM>
         HTML</A>
   </BODY>
</HTML>

Table of Contents

This example, which is similar to the link indexing code, automatically numbers all headers and creates links to them in a separate table of contents window. Letting Dynamic HTML number the headers eliminates the need to renumber them by hand every time you insert a new one. If the table of contents is in a separate window, the window closes when the user navigates away from the page.

<HTML>
   <HEAD>
      <TITLE>Manipulating Headings</TITLE>
      <SCRIPT LANGUAGE="JavaScript">  
         // Variable for the table of contents window
         var winTOC = null;

         function setupHeaders() {
            var levels = new Object;
            var level = 0;

            if (window.parent != self)
               if (null != parent.menu)
                  winTOC = parent.menu;
            if (null == winTOC)
               winTOC = window.open("", "Index",
                  "width=300; height=500");
      
            winTOC.document.open();
            winTOC.document.write("<HTML>");

            winTOC.document.writeln("<TITLE>Contents</TITLE>");
            // Write click event handler to scroll element into view.
            winTOC.document.writeln("<SCRIPT> function gotoHeader()" +
               "{if (event.srcElement.linkTo != null)" +
               "event.srcElement.linkTo.scrollIntoView(true)} </" +
               "SCRIPT>");
            winTOC.document.writeln("<BODY ONCLICK=`gotoHeader()'" +
               "STYLE=`cursor:hand'" +
               "onmouseover=`if (event.srcElement.tagName ==" +
               "&quot;SPAN&quot;)" +
               "event.srcElement.style.textDecorationUnderline " +
               "= true' onmouseout = " +
               "`event.srcElement.style.textDecorationUnderline " +
               "= false'>");
            winTOC.document.writeln("<H1>Contents</H1>");
            var level = 0;

            // Enumerate all elements for Heading elements.
            for (var i = 0; i < document.all.length; i++) {
               var el = document.all[i];
               var char1 = el.tagName.substring(0, 1);
               var val2 = parseInt(el.tagName.substring(1, 2));
               if (("H" == char1) && (2 == el.tagName.length) &&
                     (val2 > 0) && (val2 < 7)) {
                  // Nest or unnest the list.
                  if (val2 > level)
                     for (; level < val2; level++) {
                        if (levels[level] == null)
                           levels[level] = 0;
                        winTOC.document.writeln("<DL>");
                     }
                  else if (level > val2)
                     for (; level > val2; level--) {
                        levels[level - 1] = 0;
                        winTOC.document.writeln("</DL>");
                     }
                  levels[level - 1]++;
                  var hText = document.all[i].innerText;
                  winTOC.document.writeln("<DT><SPAN>");
                  var strNum = "";
                  for (var iOut = 0; iOut < level; iOut++) {
                     winTOC.document.write(levels[iOut].toString() +
                        ".");
                     strNum += levels[iOut] + ".";
                  }
                  document.all[i].insertAdjacentText("afterBegin",
                     strNum + " ");
                  winTOC.document.writeln(" " + hText + "</SPAN>");

                  // Add a property with a reference to the header.
                  winTOC.document.all[winTOC.document.all.length _
                     1].linkTo = el; 
               }
            }
            winTOC.document.close();
         }

         window.onload = setupHeaders;
         // If outputting to a frame, remove this unload event
         // handler.
         window.onunload = new Function
            ("if (!winTOC.closed) winTOC.close()");
      </SCRIPT>
   </HEAD>
   <BODY ONLOAD="setupHeaders();">
      <H1>Dynamic HTML Auto-Numbering</H1>
      <P>All the headers are automatically numbered and
         a table of contents is generated.</P>
      <P>Below are sample headings to be numbered.
      <H2>Finds all the headers.</H2>
      <P>All done automatically!</P>
      <H2>Automatically fills in a heading number.</H2>
      <H1>Better Performance and Less Maintenance</H1>
      <H2>Just maintain the page.</H2>
      <H2>Don't worry about renumbering headings.</H2>
      <H3>Test header 3</H3>
      <H2>No need to maintain separate contents document.</H2>
   </BODY>
</HTML>

Inserting code from this document into any long Web page makes the page more interactive and easier to navigate. This example also demonstrates why proper nesting of headers is valuable. While the code can handle incorrectly nested headings, the results are more meaningful when the headers are properly ordered.

Figure 13-4 shows the Table of Contents application in action. The table of contents and numbered headers are automatically generated after the page is loaded.

Dynamic Contents and document.write

Figure 13-4. A table of contents and numbered headers.

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