Figure 4   browse-inventory.htm


 <HTML>
 <HEAD>
 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
 <TITLE>Browse Book Inventory</TITLE>
 <LINK rel="stylesheet" type="text/css" href="global.css">
 <STYLE>
   .userData { behavior: url(#default#userData) }
 </STYLE>
 <SCRIPT ID=clientEventHandlersJS LANGUAGE=javascript>
 <!--
 
 function AddToShoppingCart(isbn)
 {
     if (window.confirm("Are you sure you wish to add ISBN #" + isbn +
         " to your shopping cart?"))
     {
         var pattern = "//Book[@ISBN='" + isbn + "']";
         var oNode = divInventory.XMLDocument.selectSingleNode(pattern);
         // if the book is already in the shopping cart, increment the number
         // of copies to purchase
         if (oNode)
         {
             numCopies = new Number(oNode.getAttribute("NumberOfCopies"));
             oNode.setAttribute("NumberOfCopies", numCopies + 1);
         }
         else
         {
             // clone the selected node, add the NumberOfCopies attribute, 
            // add to cart
             oNode = xmlBookInventory.selectSingleNode(pattern);
             var oClone = oNode.cloneNode(true);
             oClone.setAttribute("NumberOfCopies", 1);
             divInventory.XMLDocument.documentElement.appendChild(oClone);
         }
         // save the shopping cart to disk
         divInventory.save("ShoppingCart");    
     }
 }
 
 function window_onload() {    
     // load the shopping cart from disk
     divInventory.load("ShoppingCart");
     // transform the XML inventory to HTML
     divInventory.innerHTML = 
         xmlBookInventory.transformNode(xslBookInventory.documentElement);
 }
 
 //-->
 </SCRIPT>
 </HEAD>
 <BODY LANGUAGE=javascript onload="return window_onload()">
 
 <!-- XML files for book inventory & transform -->
 <XML ID=xmlBookInventory SRC="books.xml"></XML>
 <XML ID=xslBookInventory SRC="books.xsl"></XML>
 
 <H1>Browse Book Inventory</H1>
 <DIV class=header>
 <A HREF="default.htm">[Home]</A>&nbsp;
 <A HREF="shopping-cart.htm">[View Shopping Cart]</A>&nbsp;
 <A HREF="browse-inventory.htm">[Browse Book Inventory]</A>
 </DIV>
 <HR>
 <DIV CLASS=userData ID=divInventory></DIV>
 <HR>
 <DIV CLASS=footer>
 &copy; Copyright 1999, Microsoft Interactive Developer and Aaron Skonnard
 <A HREF="http://www.skonnard.com">http://www.skonnard.com</A>
 </DIV>
 </BODY>
 </HTML>
 

Figure 5   Shopping-cart.htm


 <HTML>
 <HEAD>
 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
 <TITLE>View Shopping Cart</TITLE>
 <LINK rel="stylesheet" type="text/css" href="global.css">
 <STYLE>
   .userData { behavior: url(#default#userData) }
 </STYLE>
 <SCRIPT ID=clientEventHandlersJS LANGUAGE=javascript>
 <!--
 
 function updateTotal() {
     
     // get all price nodes
     var books = divShoppingCart.XMLDocument.selectNodes("//Book");
     var total = 0.0;
     // calculate the total price of the order
     for (i=0; i<books.length; i++)
     {
         var bookNode = books[i];
         copies = new Number(bookNode.getAttribute("NumberOfCopies"));
         var priceNode = bookNode.selectSingleNode("Price");
         price = new Number(priceNode.getAttribute("Retail"));
         total += copies*price;
     }
     // update the total DIV element
     spanTotal.innerHTML = "Total Price: $" + total;    
 }
 
 function deleteItem(isbn)
 {
     if (window.confirm("Are you sure you wish to delete ISBN #" + isbn +
         " from your shopping cart?"))
     {
         // get the node reference and delete
         var pattern = "//Book[@ISBN='" + isbn + "']";
         var oNode = divShoppingCart.XMLDocument.selectSingleNode(pattern);
         oNode.parentNode.removeChild(oNode);
         // save the shopping cart to disk
         divShoppingCart.save("ShoppingCart");
         refresh();
     }        
 }
 
 function refresh() {
     // update all UI
     divShoppingCart.innerHTML = 
         divShoppingCart.XMLDocument.transformNode(xslShoppingCart.documentElement);
     updateTotal();
 }
 
 function window_onload() {
     // load the shopping cart from disk
     divShoppingCart.load("ShoppingCart");
     refresh();
 }
 
 function checkout() {
     // post the shopping cart data to the web server
     var xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
     xmlRequest.open("POST", "checkout.asp", false, null, null);
     xmlRequest.send(divShoppingCart.XMLDocument);
     // update HTML with response data
     divShoppingCart.innerHTML = xmlRequest.responseText;
     divTotal.innerHTML = spanTotal.innerHTML;
     // clear shopping cart
     divShoppingCart.XMLDocument.removeChild(divShoppingCart.XMLDocument.documentElement);
     divShoppingCart.save("ShoppingCart");
 }
 
 //-->
 </SCRIPT>
 </HEAD>
 <BODY LANGUAGE=javascript onload="return window_onload()">
 
 <!-- XSL file for shopping cart transform -->
 <XML ID=xslShoppingCart SRC="shopping-cart.xsl"></XML>
 
 <H1>View Shopping Cart</H1>
 <DIV class=header>
 <A HREF="default.htm">[Home]</A>&nbsp;
 <A HREF="shopping-cart.htm">[View Shopping Cart]</A>&nbsp;
 <A HREF="browse-inventory.htm">[Browse Book Inventory]</A>
 </DIV>
 <HR>
 <DIV CLASS=userData ID=divShoppingCart></DIV>
 <HR>
 <DIV ID=divTotal CLASS=total><SPAN ID=spanTotal></SPAN>&nbsp;&nbsp;&nbsp;
 <A HREF="javascript:checkout()">Purchase All Items</A></DIV>
 <HR>
 <DIV CLASS=footer>
 &copy; Copyright 1999, Microsoft Internet Developer and Aaron Skonnard 
 <A HREF="http://www.skonnard.com">http://www.skonnard.com</A>
 </DIV>
 </BODY>
 </HTML>
 

Figure 6   Checkout.asp


 <%@ Language=VBScript %>
 <%
     set xmlRequest = Server.CreateObject("MSXML.DOMDocument")
     if (xmlRequest.load(Request)) then
         set xslResults = Server.CreateObject("MSXML.DOMDocument")
         xslPath = Server.MapPath("results.xsl")
         if (xslResults.load(xslPath)) then
             Response.Write xmlRequest.transformNode(xslResults.documentElement)
         else
             Response.Write "<H2>Error processing shopping cart</H2>"
         end if
     else
         Response.Write "<H2>Error processing shopping cart</H2>"
     end if
 %>
 

Figure 7   Persistence Behaviors

Behavior
Description
saveFavorite
Persists an object across sessions when the page has been saved as a favorite. This behavior is ideal for persisting user-selected styles within a favorite or shortcut. The persisted information is stored within each favorite, allowing multiple favorites with different persisted information to exist.
saveHistory
Persists an object in memory during the current session. Ideal for storing information only while the browser is open, such as page state for collapsible content or dynamic styles.
saveSnapshot
Persists an object across sessions when a page has been saved as Web Page, HTML Only. Form elements will persist automatically. Script blocks that contain only variables can also persist. The saveSnapshot behavior is ideal for persisting Web application information to the client's disk for later retrieval.
userData
Persists an object across sessions in a userData store (an arbitrary storage facility) when the object has been explicitly saved. Ideal for persisting information across sessions and storing information in a hierarchical structure. It provides a good alternative to using cookies. The capacity of the userData store is 64KB per page, with a limit of 640KB per domain. For security reasons, a userData store is available only in the same directory and with the same protocol used to persist the store.


Figure 8   Behavior Members

Member
Description
getAttribute
Retrieves the value of the specified attribute.
onload
Fires from a persistent element when the page is reloaded.
onsave
Fires from a persisted element when the Web page is saved or bookmarked, or when the user navigates away from the page.
removeAttribute
Removes the given attribute from the object.
setAttribute
Sets the value of the specified attribute. If the attribute is not already present, the method adds the attribute to the object and sets the value.
XMLDocument
Returns a reference to the XML Document Object Model (DOM) exposed by the object.


Figure 9   SaveFavorite Implementation


 <HTML>
 <HEAD>
 <META NAME="save" CONTENT="favorite">
 <STYLE>
    .saveFavorite {behavior:url(#default#saveFavorite);}
 </STYLE>
 <SCRIPT>
    function fnSaveInput(){
       oPersist.setAttribute("myValue",oPersist.value);
    }
    function fnLoadInput(){
       oPersist.value=oPersist.getAttribute("myValue");
    }
 </SCRIPT>
 </HEAD>
 <BODY>
 <INPUT class=saveFavorite onsave="fnSaveInput()" 
    onload="fnLoadInput()" type=text id=oPersist>
 </BODY>
 </HTML>

Figure 10   Using XMLDocument


 <HTML>
 <HEAD>
 <META NAME="save" CONTENT="history">
 <STYLE>
    .saveHistory {behavior:url(#default#savehistory);}
 </STYLE>
 <SCRIPT>
 function fnSave(){
    var oXMLDoc=oPersistObject.XMLDocument;
 
    var oNode=oXMLDoc.createNode(1,"Book", "");
    oNode.setAttribute("Title", "Essential WinInet");
    oNode.setAttribute("NumberOfCopies", "1");
    oNode.setAttribute("ISBN", "0201379368");
    oXMLDoc.documentElement.appendChild(oNode);
 
    var oChild=oXMLDoc.createNode(1,"Author", "");
    oChild.text="Aaron Skonnard";
    oChild.setAttribute("authid", "aarons");
    oNode.appendChild(oChild);
 
    // add more child elements, more attributes, etc...
 }
 
 function fnLoad(){
    var oXMLDoc=oPersistObject.XMLDocument;
    var oItem=oXMLDoc.documentElement.childNodes.item(1);
    var numberOfCopies = oItem.getAttribute("NumberOfCopies");
    var isbn = oItem.getAttribute("ISBN");
 
    // do something with the data...
 }
 </SCRIPT>
 </HEAD>
 <BODY>
 <A HREF="navigate-away.htm">
    Leave The Page
 </A>
 <DIV ID="oPersist" CLASS="saveHistory" ONSAVE="fnSave()" 
    ONLOAD="fnLoad()">
 </DIV>
 </BODY>
 </HTML>

Figure 11   userData Members

Member
Description
expires
Sets or retrieves the expiration date of data persisted with the userData behavior.
getAttribute
Retrieves the value of the specified attribute.
load
Loads an object participating in userData persistence from a userData store.
removeAttribute
Removes the given attribute from the object.
save
Saves an object participating in userData persistence to a userData store.
setAttribute
Sets the value of the specified attribute. If the attribute is not already present, the method adds the attribute to the object and sets the value.
XMLDocument
Returns a reference to the XML Document Object Model (DOM) exposed by the object.


Figure 12   Shopping Cart Data


 <ROOTSTUB>
    <Book ISBN="0201379368" NumberOfCopies="3">
       <Title>
          <Main>Essential WinInet</Main>
          <Sub>Developing Applications Using the Windows Internet API With RAS,
 ISAPI, ASP, and COM</Sub>
       </Title>
       <Quotes>
          <Quote From="Richard Firth">If you are developing Internet-enabled applications
 using Internet Explorer components, you need this book.</Quote>
       </Quotes>
       <Authors>
          <Author ID="aarons" Name="Aaron Skonnard"/>
       </Authors>
       <Price Retail="44.00" Wholesale="24.95"/>
       <Abstract>A guide to Microsoft's software package designed to simplify the
 process of creating Internet-enabled applications using its Windows platform.
 Describes the basics, the protocol-specific functions for Internet tasks, and
 more advanced topics such as other Internet tools and client/server
 technologies.</Abstract>
    </Book>
    <Book ISBN="0201634465" NumberOfCopies="2">
       <Title>
          <Main>Essential COM</Main>
          <Sub>The Addison-Wesley Object Technology Series</Sub>
       </Title>
       <Quotes>
          <Quote From="Charlie Kindel">Nobody explains COM better than Don Box.</Quote>
       </Quotes>
       <Authors>
          <Author ID="dbox" Name="Don Box"/>
       </Authors>
       <Price Retail="37.00" Wholesale="20.95"/>
       <Abstract>Endorsed by object-orientation guru Grady Booch and Microsoft
 COM expert Charlie Kindel, Box's book takes the reader from an elucidating
 discussion of why a demand exists for COM and how it fits into the progression
 of C++ technology to a cool exhibition of some COM programs he's written. Along
 the way, Box covers the four corners of COM interfaces, classes, apartments, and
 security--all explained in developer's detail.</Abstract>
    </Book>
 </ROOTSTUB>