查看: 7404|回复: 1
打印 上一主题 下一主题

用XML和ASP实现一个灵活的购物车

[复制链接]
跳转到指定楼层
1#
发表于 2007-9-27 17:01:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
台州网址导航
在线购物已经变得很平常了,而在使用购物车的时候,用户期望在其身上能够获得(足够的)灵活性。看看你能够如何把ASP和XML结合起来提供所用户需要的功能。

创建虚拟购物车的方法从来都不是单一的。最近,我碰到一个机会重新编写了一个经典的ASP购物车,让它成为一个拥有与原来类似的外观和感觉,但是更加灵活和更加快速的购物车。我决定利用XML,并开发一个跨浏览器的解决方案。现在让我来告诉你我自己碰到的一些问题,以及我是如何改进原有设计的。

原来的购物车
由于原来的购物车是针对特定的一组客户的,所以它更多地依赖于对用户的培训而非易用性。除了完全清空购物车,没有其他的机制用来对(所购的)内容进行更改。如果你往购物车里放入了错误的东西或者错误的数量,你不得不从头开始才能够更正这一错误。

而不为人知的是,原来的购物车再也无法变得更好。有限数量的行被显示出来,而客户会一页一页地翻阅购物车里的内容。这种方法的问题是,所有的东西都被保存在一个以ASP会话ID为基础的表格里。当客户浏览购物车内容的时候,就会进行一次查询。此外,如果会话超时,购物车的内容将会一直保留在表格里,直到有人手动删除它。

新的方法
我不想重复以前的错误,所以新的购物车将会基于XML会话而不会基于表格。这种方法有多个好处。首先,整个购物车以XML数据岛(Data Island)的形式保存在客户端上,如下面列表A所示。在进行简单浏览的时候,这就不再需要对表格进行查询了。但是用到了MozillaDSO()和xmlPage()函数。

列表A

<root>     
<row>         
<selected></selected>         
<line>1</line>         
<quantity>1</quantity>         
<item>W01</item>         
<description>Swept hilt rapier</description>         
<weight>3.6</weight>         
<unitprice>195.95</unitprice>     
</row>
   
<row>         
<selected></selected>         
<line>2</line>         
<quantity>2</quantity>         
<item>W02</item>         
<description>Hand-and-a-half sword</description>         
<weight>5.8</weight>         
<unitprice>250.95</unitprice>     
</row>  
   
<row>         
<selected></selected>         
<line>3</line>         
<quantity>1</quantity>         
<item>W03</item>         
<description>Wood long bow</description>         
<weight>2.7</weight>         
<unitprice>190.00</unitprice>     
</row>
     
<row>         
<selected></selected>         
<line>4</line>         
<quantity>1</quantity>         
<item>W04</item>         
<description>Wizard staff</description>         
<weight>3.1</weight>         
<unitprice>89.25</unitprice>     
</row>
   
<row>         
<selected></selected>         
<line>5</line>         
<quantity>1</quantity>         
<item>C01</item>         
<description>Gauntlets</description>         
<weight>0.7</weight>         
<unitprice>25.00</unitprice>     
</row>     

<row>         
<selected></selected>         
<line>6</line>         
<quantity>5</quantity>         
<item>C02</item>         
<description>Knee-high boots</description>         
<weight>1.9</weight>         
<unitprice>95.00</unitprice>     
</row>     

<row>         
<selected></selected>         
<line>7</line>         
<quantity>9</quantity>         
<item>C04</item>         
<description>Cloak</description>         
<weight>1.0</weight>         
<unitprice>125.00</unitprice>     
</row>     

<row>         
<selected></selected>         
<line>8</line>         
<quantity>22</quantity>         
<item>C05</item>         
<description>Orc repellent</description>         
<weight>1.0</weight>         
<unitprice>8.95</unitprice>     
</row>     

<row>         
<selected></selected>         
<line>9</line>         
<quantity>1</quantity>         
<item>W05</item>         
<description>Dwarf axe</description>         
<weight>8.0</weight>         
<unitprice>358.95</unitprice>     
</row>     

<row>         
<selected></selected>         
<line>10</line>         
<quantity>1</quantity>         
<item>A01</item>         
<description>Steel cap</description>         
<weight>2.8</weight>         
<unitprice>219.95</unitprice>     
</row>   

<row>         
<selected></selected>         
<line>11</line>         
<quantity>1</quantity>         
<item>A02</item>         
<description>Chainmail shirt</description>         
<weight>15.3</weight>         
<unitprice>487.22</unitprice>     
</row>     

<row>         
<selected></selected>         
<line>12</line>         
<quantity>1</quantity>         
<item>A03</item>         
<description>Mithril shirt</description>         
<weight>0.4</weight>         
<unitprice>87236.03</unitprice>     
</row>     

<row>         
<selected></selected>         
<line>13</line>         
<quantity>1</quantity>         
<item>W07</item>         
<description>Elvish long sword</description>         
<weight>1.9</weight>         
<unitprice>794.99</unitprice>     
</row>     

<row>         
<selected></selected>         
<line>14</line>         
<quantity>1</quantity>         
<item>W08</item>         
<description>Elvish short sword</description>         
<weight>0.8</weight>         
<unitprice>435.99</unitprice>     
</row>     

<row>         
<selected></selected>         
<line>15</line>         
<quantity>3</quantity>         
<item>W09</item>         
<description>Short sword</description>         
<weight>1.5</weight>         
<unitprice>89.95</unitprice>     
</row>
</root>



除了浏览,xmlPage()方法还提供了原来的购物车不具备的功能——更改数量和删除物品的能力。由于它使用了两个XML数据岛——一个是绑定,另一个是非绑定——所以对绑定数据岛的更改不会影响到非绑定数据岛,直到点击更新键。一旦更新按钮被点击,就会有一种机制,比如XMLHTTP,把变化传送给服务器。如果由于某种原因你无法完全信任微软Internet Explorer和Mozilla里的XMLHTTP,那么一个带有隐藏式框架(例如iframe)和输入框的表单可以被用来实现同样的目的。下面的列表B显示了更新函数背后的JavaScript。


列表B

function update() {
  /* Function:      update
     Creation Date: May 5, 2003
     Programmer:    Edmond Woychowsky
     Purpose:       The purpose of this function is to apply bound Data

Island  changes to the full Data Island.  This is

accomplished by matching line numbers in both Data

Islands.  Once this has been completed the full Data

Island is sent to the server via XMLHTTP.

     Update Date:       Programmer:              Description:
  */


var objXMLHTTP;

//     XMLHTTP request object

var reWork = new RegExp('internet explorer','gi');


document.body.style.cursor = 'wait';     //     Set cursor


for(var i=0;i < objPage.bound.getElementsByTagName('row').length;i++)

for(var j=0;j < objPage.full.getElementsByTagName('row').length;j++)

if(objPage.bound.getElementsByTagName('line').item(i).firstChild.nodeValue == objPage.full.getElementsByTagName('line').item(j).firstChild.nodeValue) {

for(var k=0;k < objPage.bound.getElementsByTagName('row').item(i).childNodes.length;k++)

if(objPage.bound.getElementsByTagName('row').item(i).childNodes.item(k).nodeName != '#text')

switch(objPage.bound.getElementsByTagName('row').item(i).childNodes.item(k).nodeName.toLowerCase()) {

case('quantity'):

case('selected'):

try {

objPage.full.getElementsByTagName('row').item(j).childNodes.item(k).firstChild.nodeValue = objPage.bound.getElementsByTagName('row').item(i).childNodes.item(k).firstChild.nodeValue;

}

catch(e) {

try {

objPage.full.getElementsByTagName('row').item(j).childNodes.item(k).appendChild(objPage.bound.getElementsByTagName('row').item(i).childNodes.item(k).firstChild.cloneNode(true));

}

catch(e) { }

}


break;

}

break;

}

//     Send updates

if(reWork.test(navigator.appName))

objXMLHTTP = new ActiveXObject('Microsoft.XMLHTTP');

else

objXMLHTTP = new XMLHttpRequest();

objXMLHTTP.open('GET','xmlServer.asp',true);

objXMLHTTP.setRequestHeader('content-type','text/xml');

objXMLHTTP.onreadystatechange = function() {

var reWork = new RegExp('internet explorer','gi');

if(objXMLHTTP.readyState == 4) {

if(reWork.test(navigator.appName))

objPage.full.XMLDocument.loadXML(unescape(objXMLHTTP.responseText));

else

objPage.full.innerHTML = unescape(objXMLHTTP.responseText);

//Handle empty page

if(objPage.page() > objPage.pagecount())

objPage.showPrevious();

else

objPage.showPage();

// Display page info

document.getElementById('currentpage').lastChild.nodeValue = objPage.page();

document.getElementById('totalpages').lastChild.nodeValue = objPage.pagecount();

document.body.style.cursor = 'auto';

} }

// IE work around

try {

objPage.full.innerHTML = objPage.full.XMLDocument.xml;

}

catch(e) { }

if(reWork.test(navigator.appName))

objXMLHTTP.setRequestHeader('request',escape(objPage.full.XMLDocument.xml));

else

objXMLHTTP.setRequestHeader('request',escape(objPage.full.innerHTML));

objXMLHTTP.send(null);

}


在做进一步讲解之前,我会在同一个句子里使用Mozilla和XMLHTTP。有书面的证据表明Mozilla支持XMLHTTP。尽管其句法与Internet Explorer所用的句法稍有不同,但这并不是JavaScript无法处理的东西。完整的客户端解决方案见图A,而ASP见下面的列表C。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 转播转播 分享分享 分享淘帖
台州维博网络(www.tzweb.com)专门运用PHP+MYSQL/ASP.NET+MSSQL技术开发网站门户平台系统等。
2#
 楼主| 发表于 2007-9-27 17:02:09 | 只看该作者
台州网址导航
图A



列表C

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>New Page 2</title>
</head>

<body>

<table cellPadding="0" width="100%" border="0" id="table1">
        <tr>
                <td class="subhead1">Listing C</td>
        </tr>
        <tr bgColor="#ff0000">
                <td height="1">
                <img height="1" src="http://builder.com.com/i/tr/spacer.gif" width="1"></td>
        </tr>
        <tr>
                <td height="5">
                <img height="5" src="http://builder.com.com/i/tr/spacer.gif" width="1"></td>
        </tr>
        <tr>
                <td>
                <%@ Language=JScript %>

<%
     Response.Buffer = true;

     var strTitle = 'Honest Ed's Adventure Emporium';

     Session('shoppingcart') = '<root>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>1</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>W01</item>';
     Session('shoppingcart') += '<description>Swept hilt rapier</description>';
     Session('shoppingcart') += '<weight>3.6</weight>';
     Session('shoppingcart') += '<unitprice>195.95</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>2</line>';
     Session('shoppingcart') += '<quantity>2</quantity>';
     Session('shoppingcart') += '<item>W02</item>';
    Session('shoppingcart') += '<description>Hand-and-a-half sword</description>';
     Session('shoppingcart') += '<weight>5.8</weight>';
     Session('shoppingcart') += '<unitprice>250.95</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>3</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>W03</item>';
     Session('shoppingcart') += '<description>Wood long bow</description>';
     Session('shoppingcart') += '<weight>2.7</weight>';
     Session('shoppingcart') += '<unitprice>190.00</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>4</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>W04</item>';
     Session('shoppingcart') += '<description>Wizard staff</description>';
     Session('shoppingcart') += '<weight>3.1</weight>';
     Session('shoppingcart') += '<unitprice>89.25</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
    Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>5</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>C01</item>';
     Session('shoppingcart') += '<description>Gauntlets</description>';
     Session('shoppingcart') += '<weight>0.7</weight>';
     Session('shoppingcart') += '<unitprice>25.00</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>6</line>';
     Session('shoppingcart') += '<quantity>5</quantity>';
     Session('shoppingcart') += '<item>C02</item>';
     Session('shoppingcart') += '<description>Knee-high boots</description>';
     Session('shoppingcart') += '<weight>1.9</weight>';
     Session('shoppingcart') += '<unitprice>95.00</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>7</line>';
     Session('shoppingcart') += '<quantity>9</quantity>';
     Session('shoppingcart') += '<item>C04</item>';
     Session('shoppingcart') += '<description>Cloak</description>';
     Session('shoppingcart') += '<weight>1.0</weight>';
     Session('shoppingcart') += '<unitprice>125.00</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
    Session('shoppingcart') += '<line>8</line>';
     Session('shoppingcart') += '<quantity>22</quantity>';
     Session('shoppingcart') += '<item>C05</item>';
     Session('shoppingcart') += '<description>Orc repellent</description>';
     Session('shoppingcart') += '<weight>1.0</weight>';
     Session('shoppingcart') += '<unitprice>8.95</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>9</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>W05</item>';
     Session('shoppingcart') += '<description>Dwarf axe</description>';
     Session('shoppingcart') += '<weight>8.0</weight>';
     Session('shoppingcart') += '<unitprice>358.95</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>10</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>A01</item>';
     Session('shoppingcart') += '<description>Steel cap</description>';
     Session('shoppingcart') += '<weight>2.8</weight>';
     Session('shoppingcart') += '<unitprice>219.95</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>11</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>A02</item>';
     Session('shoppingcart') += '<description>Chainmail shirt</description>';
     Session('shoppingcart') += '<weight>15.3</weight>';
     Session('shoppingcart') += '<unitprice>487.22</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>12</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>A03</item>';
     Session('shoppingcart') += '<description>Mithril shirt</description>';
     Session('shoppingcart') += '<weight>0.4</weight>';
     Session('shoppingcart') += '<unitprice>87236.03</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>13</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>W07</item>';
     Session('shoppingcart') += '<description>Elvish long sword</description>';
     Session('shoppingcart') += '<weight>1.9</weight>';
     Session('shoppingcart') += '<unitprice>794.99</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>14</line>';
     Session('shoppingcart') += '<quantity>1</quantity>';
     Session('shoppingcart') += '<item>W08</item>';
     Session('shoppingcart') += '<description>Elvish short sword</description>';
     Session('shoppingcart') += '<weight>0.8</weight>';
     Session('shoppingcart') += '<unitprice>435.99</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '<row>';
     Session('shoppingcart') += '<selected></selected>';
     Session('shoppingcart') += '<line>15</line>';
     Session('shoppingcart') += '<quantity>3</quantity>';
     Session('shoppingcart') += '<item>W09</item>';
     Session('shoppingcart') += '<description>Short sword</description>';
     Session('shoppingcart') += '<weight>1.5</weight>';
     Session('shoppingcart') += '<unitprice>89.95</unitprice>';
     Session('shoppingcart') += '</row>';
     Session('shoppingcart') += '</root>';


%>

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
     <title><%=strTitle %></title>
    <style type="text/css">

TD

{
    FONT-SIZE: 9pt;
    FONT-FAMILY: Tahoma

}

XML

{
  WIDTH: 0px;
  HEIGHT: 0px;
  DISPLAY: none;

}
    </style>
    <script language="JavaScript">
      <!-- <![CDATA[

function setEvents() {
  /* Function:      setEvents
     Creation Date: April 25, 2003
     Programmer:    Edmond Woychowsky
     Purpose:       The purpose of this function is to create an instance
                        of the xmlPage object, initialize the object and
                         perform page initialization.

     Update Date:       Programmer:              Description:
  */

     objPage = new xmlPage();                         //     Create instance

     for(var i=0;i < document.getElementsByTagName('input').length;i++)
          if(document.getElementsByTagName('input').item(i).getAttribute('type') == 'button') {
               document.getElementsByTagName('input').item(i).style.height = '26px';
               document.getElementsByTagName('input').item(i).style.width = '100px';

               document.getElementsByTagName('input').item(i).onmouseover = new Function('this.style.color = '#FF0000'');
               document.getElementsByTagName('input').item(i).onmouseout = new Function('this.style.color = '#000000'');
          }

                                                            //     Establish relationships
     objPage.bound = document.getElementById('xmlWindow');
     objPage.full = document.getElementById('xmlFull');
     objPage.table = document.getElementById('boundTable');

     objPage.length(10);                                   //     Set page length
     objPage.showPage();                                   //     Show first page

                                                            //     Display page info
     try {
          document.getElementById('currentpage').removeChild(document.getElementById('currentpage').firstChild);
          document.getElementById('totalpages').removeChild(document.getElementById('totalpages').firstChild);
     }
     catch(e) { }

     document.getElementById('currentpage').appendChild(document.createTextNode(objPage.page()));
     document.getElementById('totalpages').appendChild(document.createTextNode(objPage.pagecount()));

}


function update() {
  /* Function:      update
     Creation Date: May 5, 2003
     Programmer:    Edmond Woychowsky
     Purpose:       The purpose of this function is to apply bound Data
                        Island  changes to the full Data Island.  This is
                         accomplished by matching line numbers in both Data
                         Islands.  Once this has been completed the full Data
                         Island is sent to the server via XMLHTTP.

     Update Date:       Programmer:              Description:
  */

     var objXMLHTTP;                                   //     XMLHTTP request object
     var reWork = new RegExp('internet explorer','gi');

     document.body.style.cursor = 'wait';     //     Set cursor

     for(var i=0;i < objPage.bound.getElementsByTagName('row').length;i++)
          for(var j=0;j < objPage.full.getElementsByTagName('row').length;j++)
               if(objPage.bound.getElementsByTagName('line').item(i).firstChild.nodeValue == objPage.full.getElementsByTagName('line').item(j).firstChild.nodeValue) {
                    for(var k=0;k < objPage.bound.getElementsByTagName('row').item(i).childNodes.length;k++)
                         if(objPage.bound.getElementsByTagName('row').item(i).childNodes.item(k).nodeName != '#text')
                              switch(objPage.bound.getElementsByTagName('row').item(i).childNodes.item(k).nodeName.toLowerCase()) {
                                   case('quantity'):
                                   case('selected'):
                                        try {
                                             objPage.full.getElementsByTagName('row').item(j).childNodes.item(k).firstChild.nodeValue = objPage.bound.getElementsByTagName('row').item(i).childNodes.item(k).firstChild.nodeValue;
                                        }
                                        catch(e) {
                                             try {
                                                 objPage.full.getElementsByTagName('row').item(j).childNodes.item(k).appendChild(objPage.bound.getElementsByTagName('row').item(i).childNodes.item(k).firstChild.cloneNode(true));
                                             }
                                            catch(e) { }
                                        }

                                        break;
                              }

                    break;
               }

                                                           //     Send updates
     if(reWork.test(navigator.appName))
          objXMLHTTP = new ActiveXObject('Microsoft.XMLHTTP');
     else
          objXMLHTTP = new XMLHttpRequest();

     objXMLHTTP.open('GET','xmlServer.asp',true);
     objXMLHTTP.setRequestHeader('content-type','text/xml');
               
     objXMLHTTP.onreadystatechange = function() {
          var reWork = new RegExp('internet explorer','gi');

          if(objXMLHTTP.readyState == 4) {
               if(reWork.test(navigator.appName))
                    objPage.full.XMLDocument.loadXML(unescape(objXMLHTTP.responseText));
               else
                    objPage.full.innerHTML = unescape(objXMLHTTP.responseText);

                                                            //    Handle empty page
               if(objPage.page() > objPage.pagecount())
                    objPage.showPrevious();
               else
                    objPage.showPage();

                                                            //     Display page info
               document.getElementById('currentpage').lastChild.nodeValue = objPage.page();
               document.getElementById('totalpages').lastChild.nodeValue = objPage.pagecount();

               document.body.style.cursor = 'auto';
         }
     }

                                                            //     IE work around
     try {
          objPage.full.innerHTML = objPage.full.XMLDocument.xml;
     }
     catch(e) { }

     if(reWork.test(navigator.appName))
          objXMLHTTP.setRequestHeader('request',escape(objPage.full.XMLDocument.xml));
                     else
          objXMLHTTP.setRequestHeader('request',escape(objPage.full.innerHTML));
               
     objXMLHTTP.send(null);

}


function ieBusTable(objTable) {
  /* Function:      ieBusTable
     Creation Date: April 30, 2003
     Programmer:    Edmond Woychowsky
     Purpose:       The purpose of this function is to remove the garbage
                         that Microsoft Internet Explorer displays when a table's
                         cell contains null.  This porblem only applies to div
                         and span tags.

     Update Date:       Programmer:              Description:
  */

     var reWork = new RegExp('internet explorer','gi');

     if(reWork.test(navigator.appName))
          if(objTable.readyState == 'complete') {
               for(var i=0;i < objTable.getElementsByTagName('div').length;i++)
                    if(objTable.getElementsByTagName('div').item(i).innerText.length == 0)
                         objTable.getElementsByTagName('div').item(i).innerText = ' ';

               for(var i=0;i < objTable.getElementsByTagName('span').length;i++)
                    if(objTable.getElementsByTagName('span').item(i).innerText.length == 0)
                         objTable.getElementsByTagName('span').item(i).innerText = ' ';
          }

}


function xmlPage() {
  /* Function:      xmlPage
     Creation Date: April 25, 2003
     Programmer:    Edmond Woychowsky
     Purpose:       The purpose of this class is to define the cross-browser
                         (Mozill & IE) paging object.

     Update Date:       Programmer:              Description:
  */

                                                            //     Variables
     var objCommonAncestor = null;                   //     datafld common ancestor
     var objInitialTable = null;
     var strBound = null;                              //     XML window data island
     var strXML = null;                                   //     XML full data island
    var strTable = null;                              //     Bound HTML/XHTML table
     var intAbsolutePosition = 0;                    //     Window item index
     var intPage = 1;                                   //     Logical page number
     var intLength = 15;                                   //     Logical page length
     var blnInitialize = false;                         //     Initialize binds

                                                            //     Properties
     this.bound = null;                                   //     XML window data island
     this.full = null;                                   //     XML full data island
     this.table = null;                                   //     Bound HTML/XHTML table

                                                           //     Methods
     this.length = m_length;                              //     Page length
     this.page = m_page;                                   //     Current page number
     this.pagecount = m_pageCount;                   //     Calculate page count
     this.recordcount = m_recordCount;               //     "ADO recordset" recordcount
     this.showPage = m_showPage;                         //     Show current page
     this.showFirst = m_showFirst;                   //     "ADO recordset" movefirst
     this.showLast = m_showLast;                         //     "ADO recordset" movelast
     this.showNext = m_showNext;                         //     "ADO recordset" movenext
     this.showPrevious = m_showPrevious;               //     "ADO recordset" moveprevious

     function m_showPage() {
          /* Function:          m_showPage
             Creation Date:     April 25, 2003
             Programmer:          Edmond Woychowsky
             Purpose:              The purpose of this function is to show the
                                   current page's information.  This is accomplished
                                   by cloning the applicable nodes from the "full"
                                  Data Island to the "bound" Data Island.

             Update Date:       Programmer:              Description:
             May 13, 2003            Edmond Woychowsky          Modified to invoke m_recordCount()
                                                                to compute current record count.
          */

          var objRoot = document.createElement('root');
          var objXML = null;                              //     XML DOM for IE

          if(!blnInitialize)
               initialize(this.bound,this.full,this.table);

          this.full = document.getElementById(strXML);
          this.bound = document.getElementById(strBound);

                                                            //     Remove existing nodes
          try {
               document.getElementById(strTable).innerHTML = objInitialTable.innerHTML;
          }
          catch(e) { }

          try {
               for(var i=0;i < this.bound.childNodes.length;i++)
                    this.bound.removeChild(this.bound.childNodes.item(i));
          }
          catch(e) { }

                                                            //     Add up to this.length nodes
          for(var i=intAbsolutePosition;i < (intAbsolutePosition + intLength);i++)
               if(i > (m_recordCount() - 1))
                    break;
               else {
                    try {                                   //     Unique Mozilla logic
                         objRoot.appendChild(this.full.getElementsByTagName(objCommonAncestor).item(i).cloneNode(true));
                    }
                    catch(e) {                              //     Unique IE logic
                         if(i == intAbsolutePosition) {
                              objXML = new ActiveXObject('MSXML.DOMDocument');
                              objRoot = objXML.createElement('root');
                         }

                         objRoot.appendChild(this.full.XMLDocument.getElementsByTagName(objCommonAncestor).item(i).cloneNode(true));
                   }
               }

          this.bound.appendChild(objRoot);

          MozillaDSO();                                   //     Mozilla bind logic
     }

     function m_showFirst() {
          /* Function:          m_showFirst
             Creation Date:     April 25, 2003
             Programmer:          Edmond Woychowsky
             Purpose:               The purpose of this function is to show the
                                   first logical page.

             Update Date:       Programmer:              Description:
          */

          intAbsolutePosition = 0;                    //     Set absolute position

          m_showPage();                                   //     Show page
     }

     function m_showLast() {
          /* Function:          m_showLast
             Creation Date:     April 25, 2003
             Programmer:          Edmond Woychowsky
             Purpose:               The purpose of this function is to show the
                                   last logical page.

             Update Date:       Programmer:              Description:
          */

          intAbsolutePosition = (m_pageCount() - 1) * m_length();

          m_showPage();                                   //     Show page
     }

     function m_showNext() {
          /* Function:          m_showNext
             Creation Date:     April 25, 2003
             Programmer:          Edmond Woychowsky
             Purpose:               The purpose of this function is to show the
                                  next logical page.

             Update Date:       Programmer:              Description:
          */

          if(m_page() < m_pageCount())
               intAbsolutePosition += intLength;     //     Set absolute position

          m_showPage();                                   //     Show page
     }

     function m_showPrevious() {
          /* Function:          m_showPrevious
             Creation Date:     April 25, 2003
             Programmer:          Edmond Woychowsky
            Purpose:               The purpose of this function is to show the
                                   previous logical page.

             Update Date:       Programmer:              Description:
          */

          if(m_page() > 1)
              intAbsolutePosition -= intLength;     //     Set absolute position

          m_showPage();                                   //     Show page
     }

     function m_length() {
          /* Function:          m_length
             Creation Date:     April 25, 2003
             Programmer:          Edmond Woychowsky
             Purpose:               The purpose of this function is to set or get
                                   the logical page length.

             Update Date:       Programmer:             Description:
          */

          if(arguments.length > 0)
               intLength = parseInt(arguments[0],10);
          else
               return intLength;
     }

     function m_page() {
          /* Function:          m_page
            Creation Date:     April 25, 2003
             Programmer:          Edmond Woychowsky
             Purpose:               The purpose of this function is to compute the
                                   current logical page number.

             Update Date:       Programmer:              Description:
          */

          return (parseInt((intAbsolutePosition / intLength),10) + 1);
     }

     function m_recordCount() {
          /* Function:          m_recordCount
             Creation Date:     April 25, 2003
             Programmer:          Edmond Woychowsky
             Purpose:               The purpose of this function is to compute the
                                   return the total number of "records" in the
                                  "full" XML Data Island.

             Update Date:       Programmer:              Description:
             May 13, 2003            Edmond Woychowsky          Modified to recompute due
                                                                 to possible deletes.   
          */

          if(!blnInitialize)
               initialize(this.bound,this.full,this.table);

          return document.getElementById(strXML).getElementsByTagName(objCommonAncestor).length;
     }

     function m_pageCount() {
          /* Function:          m_pageCount
                             Creation Date:     April 25, 2003
                             Programmer:          Edmond Woychowsky
                             Purpose:               The purpose of this function is to compute the
                                                  return the total number of logical pages.
                 
                             Update Date:       Programmer:              Description:
                             May 13, 2003            Edmond Woychowsky          Modified to invoke m_recordCount()
                                                                                to compute current record count.
                          */
                 
                          if(!blnInitialize)
                               initialize(this.bound,this.full,this.table);
                 
                          return parseInt((m_recordCount() + (intLength - 1)) / intLength,10);
                     }
                 
                     function initialize(objBound,objXML,objTable) {
                          /* Function:          initialize
                             Creation Date:     April 25, 2003
                             Programmer:          Edmond Woychowsky
                             Purpose:               The purpose of this function is to perform the
                                                   necessary housekeeping before paging can occur.
                 
                             Update Date:       Programmer:              Description:
                          */
                 
                          var objNodeName = new collection();
                          var arrNodeName;
                 
                          switch(true) {
                               case((objBound == null) && (objXML == null) && (objTable == null)):
                                    alert('Error: bound, xml and table not set.');
                 
                                    break;
                               case((objBound == null) && (objXML == null)):
                                    alert('Error: bound and xml not set.');
                 
                                    break;
                               case((objBound == null) && (objTable == null)):
                                    alert('Error: bound and table not set.');
                 
                                    break;
                               case((objXML == null) && (objTable == null)):
                                    alert('Error: xml and table not set.');
                 
                                    break;
                               case(objBound == null):
                                    alert('Error: bound not set.');
                 
                                   break;
                               case(objXML == null):
                                    alert('Error: xml not set.');
                 
                                    break;
                               case(objTable == null):
                                    alert('Error: table not set.');
                 
                                    break;
                              default:
                                    for(var i=0;i < objTable.getElementsByTagName('input').length;i++)
                                         if(objTable.getElementsByTagName('input').item(i).getAttribute('datafld') != null)
                                              objNodeName.item(objTable.getElementsByTagName('input').item(i).getAttribute('datafld'),null);
                 
                                    for(var i=0;i < objTable.getElementsByTagName('div').length;i++)
                                         if(objTable.getElementsByTagName('div').item(i).getAttribute('datafld') != null)
                                              objNodeName.item(objTable.getElementsByTagName('div').item(i).getAttribute('datafld'),null);
                 
                                    for(var i=0;i < objTable.getElementsByTagName('span').length;i++)
                                        if(objTable.getElementsByTagName('span').item(i).getAttribute('datafld') != null)
                                              objNodeName.item(objTable.getElementsByTagName('span').item(i).getAttribute('datafld'),null);
                 
                                    arrNodeName = objNodeName.keys();
                                    objNodeName = new collection();
                 
                                    for(var i=0;i < arrNodeName.length;i++)
                                         objNodeName.item(objXML.getElementsByTagName(arrNodeName).item(0).parentNode.nodeName,null);
                 
                                   if(objNodeName.keys().length != 1)
                                         alert('Error: unsupported XML document structure.');
                                    else {
                                         objCommonAncestor = objNodeName.keys().join('');
                 
                                         blnInitialize = true;
                                    }
                 
                                                                            //     Store node names
                                    strBound = objBound.getAttribute('id');
                                    strXML = objXML.getAttribute('id');
                                    strTable = objTable.getAttribute('id');
                 
                                                                            //     Store initial table
                                    objInitialTable = objTable.cloneNode(true);
                 
                                    break;
                          }
                     }
                }
                 
                function MozillaDSO() {
                  /* Function:      MozillaDSO
                     Creation Date: April 16, 2003
                     Programmer:    Edmond Woychowsky
                     Purpose:       The purpose of this function is to perform binding of
                                    XML Data Islands for Mozilla.  The logic herein is bypassed
                                    for Microsoft Internet Explorer.
                 
                     Update Date:       Programmer:              Description:
                  */
                 
                                                                 //  Global variables
                  objXMLDI = new collection();                   //  XML data island collection
                  objBound = new collection();                   //  Bound XHTML object collection
                 
                                                                 //  Local variables
                  var objDatafld;                                //  Table datafld collection
                  var objRow;                                    //  Table row
                  var reWork = new RegExp('internet explorer','gi');
                  var arrKeys = new Array();
                  var intKey = 0;                                //  objBound collection key
                  var intRows;                                   //  Row count
                 
                  if(!reWork.test(navigator.appName)) {
                                                                 //  Locate data islands
                    for(var i=0;i < document.getElementsByTagName('xml').length;i++)
                      objXMLDI.add('#' + document.getElementsByTagName('xml').item(i).getAttribute('id'),document.getElementsByTagName('xml').item(i));
                 
                                                                 //  Locate bound nodes
                    for(var i=0;i < document.getElementsByTagName('table').length;i++)
                      if(document.getElementsByTagName('table').item(i).getAttribute('datasrc') != null) {
                        objBound.add(intKey.toString(),new boundXML());
                 
                        objBound.item(intKey.toString()).datasrc = document.getElementsByTagName('table').item(i).getAttribute('datasrc');
                        objBound.item(intKey.toString()).node = document.getElementsByTagName('table').item(i);
                        objBound.item(intKey.toString()).nodeName = document.getElementsByTagName('table').item(i).nodeName;
                 
                        objDatafld = new collection();           //  Reset collection;
                        intRows = 0;                             //  Reset row count
                 
                                                                 //  Remove all rows
                        if(objBound.item(intKey.toString()).node.getElementsByTagName('tr').length != 0) {
                          for(var j=0;j < objBound.item(intKey.toString()).node.getElementsByTagName('tr').length;j++)
                            objRow = objBound.item(intKey.toString()).node.lastChild.removeChild(objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j));
                 
                            for(var j=0;j < objBound.item(intKey.toString()).node.getElementsByTagName('tr').length;j++)
                              objRow = objBound.item(intKey.toString()).node.lastChild.removeChild(objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j));
                        }
                 
                                                                 //  Determine bound nodes
                        for(var j=0;j < objRow.getElementsByTagName('input').length;j++)
                          if(!objDatafld.exists(objRow.getElementsByTagName('input').item(j).getAttribute('datafld')))
                            objDatafld.item(objRow.getElementsByTagName('input').item(j).getAttribute('datafld'),null);
                 
                        for(var j=0;j < objRow.getElementsByTagName('div').length;j++)
                          if(!objDatafld.exists(objRow.getElementsByTagName('div').item(j).getAttribute('datafld')))
                            objDatafld.item(objRow.getElementsByTagName('div').item(j).getAttribute('datafld'),null);
                 
                        for(var j=0;j < objRow.getElementsByTagName('span').length;j++)
                          if(!objDatafld.exists(objRow.getElementsByTagName('span').item(j).getAttribute('datafld')))
                            objDatafld.item(objRow.getElementsByTagName('span').item(j).getAttribute('datafld'),null);
                 
                        arrKeys = objDatafld.keys();
                 
                                                                 //  Determine row count
                        for(var j=0;j < arrKeys.length;j++)
                          if(intRows < objXMLDI.item(objBound.item(intKey.toString()).datasrc).getElementsByTagName(arrKeys[0]).length)
                            intRows = objXMLDI.item(objBound.item(intKey.toString()).datasrc).getElementsByTagName(arrKeys[0]).length;
                 
                        for(var j=0;j < intRows;j++)
                          objBound.item(intKey.toString()).node.lastChild.appendChild(objRow.cloneNode(true));
                 
                                                                 //  Rebuild table and bind
                        for(var j=0;j < objBound.item(intKey.toString()).node.getElementsByTagName('tr').length;j++)
                          for(var k=0;k < objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').length;k++)
                            for(var l=0;l < objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.length;l++)
                              switch(objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).nodeName.toLowerCase()) {
                                case('input'):
                                      try {
                                   if(objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('type') != 'checkbox')
                                      objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).value = objXMLDI.item(objBound.item(intKey.toString()).datasrc).getElementsByTagName(objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('datafld')).item(j).firstChild.nodeValue;
                                    else
                                      objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).checked = eval(objXMLDI.item(objBound.item(intKey.toString()).datasrc).getElementsByTagName(objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('datafld')).item(j).firstChild.nodeValue);
                                  }
                                  catch(e) { }
                 
                                  if(objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('type') != 'checkbox')
                                    objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).onchange = new Function('try { objXMLDI.item('' + objBound.item(intKey.toString()).datasrc + '').getElementsByTagName('' + objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('datafld') + '').item(' + j.toString() + ').firstChild.nodeValue = this.value } catch(e) { objXMLDI.item('' + objBound.item(intKey.toString()).datasrc + '').getElementsByTagName('' + objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('datafld') + '').item(' + j.toString() + ').appendChild(document.createTextNode(this.value)) };MozillaDSO;');
                                  else
                                    objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).onchange = new Function('try { objXMLDI.item('' + objBound.item(intKey.toString()).datasrc + '').getElementsByTagName('' + objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('datafld') + '').item(' + j.toString() + ').firstChild.nodeValue = this.checked } catch(e) { objXMLDI.item('' + objBound.item(intKey.toString()).datasrc + '').getElementsByTagName('' + objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('datafld') + '').item(' + j.toString() + ').appendChild(document.createTextNode(this.checked)) };MozillaDSO;');
                 
                                  break;
                                case('div'):
                               case('span'):
                                  try {                        //  Text node exists
                                    objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).firstChild.nodeValue = objXMLDI.item(objBound.item(intKey.toString()).datasrc).getElementsByTagName(objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('datafld')).item(j).firstChild.nodeValue;
                                  }
                                  catch(e) {                   //  Create text node
                                    try {
                                      objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).appendChild(document.createTextNode(objXMLDI.item(objBound.item(intKey.toString()).datasrc).getElementsByTagName(objBound.item(intKey.toString()).node.getElementsByTagName('tr').item(j).getElementsByTagName('td').item(k).childNodes.item(l).getAttribute('datafld')).item(j).firstChild.nodeValue));
                                    }
                                    catch(e) { }
                                  }
                 
                                  break;
                              }
                 
                              ++intKey;
                      }
                 
                                                                 //  Non-tabular datasrc/datafld
                      for(var i=0;i < document.getElementsByTagName('input').length;i++)
                        if(document.getElementsByTagName('input').item(i).getAttribute('datafld') != null) {
                          objBound.add(intKey.toString(),new boundXML());
                 
                          if(document.getElementsByTagName('input').item(i).getAttribute('datasrc') != null)
                            objBound.item(intKey.toString()).datasrc = document.getElementsByTagName('input').item(i).getAttribute('datasrc');
                 
                          objBound.item(intKey.toString()).datafld = document.getElementsByTagName('input').item(i).getAttribute('datafld');
                          objBound.item(intKey.toString()).node = document.getElementsByTagName('input').item(i);
                          objBound.item(intKey.toString()).nodeName = document.getElementsByTagName('input').item(i).nodeName;
                 
                          ++intKey;
                        }
                 
                      for(var i=0;i < document.getElementsByTagName('div').length;i++)
                        if(document.getElementsByTagName('div').item(i).getAttribute('datafld') != null) {
                          objBound.add(intKey.toString(),new boundXML());
                 
                          if(document.getElementsByTagName('div').item(i).getAttribute('datasrc') != null)
                            objBound.item(intKey.toString()).datasrc = document.getElementsByTagName('div').item(i).getAttribute('datasrc');
                 
                          objBound.item(intKey.toString()).datafld = document.getElementsByTagName('div').item(i).getAttribute('datafld');
                          objBound.item(intKey.toString()).node = document.getElementsByTagName('div').item(i);
                          objBound.item(intKey.toString()).nodeName = document.getElementsByTagName('div').item(i).nodeName;
                 
                          ++intKey;
                        }
                 
                      for(var i=0;i < document.getElementsByTagName('span').length;i++)
                        if(document.getElementsByTagName('span').item(i).getAttribute('datafld') != null) {
                          objBound.add(intKey.toString(),new boundXML());
                 
                          if(document.getElementsByTagName('span').item(i).getAttribute('datasrc') != null)
                            objBound.item(intKey.toString()).datasrc = document.getElementsByTagName('span').item(i).getAttribute('datasrc');
                 
                          objBound.item(intKey.toString()).datafld = document.getElementsByTagName('span').item(i).getAttribute('datafld');
                          objBound.item(intKey.toString()).node = document.getElementsByTagName('span').item(i);
                          objBound.item(intKey.toString()).nodeName = document.getElementsByTagName('span').item(i).nodeName;
                 
                          ++intKey;
                        }
                 
                      arrKeys = objBound.keys();
                 
                                                                //  Handle non-tabular binds
                      for(var i=0;i < arrKeys.length;i++)
                        switch(objBound.item(arrKeys).nodeName.toLowerCase()) {
                          case('table'):
                            objBound.item(arrKeys).rows = new Array();
                 
                            break;
                          case('input'):
                            try {
                              if(typeof(objBound.item(arrKeys).datasrc) == 'string') {
                                try {
                                  if(objBound.item(arrKeys).node.getAttribute('type') != 'checkbox')
                                    objBound.item(arrKeys).node.value = objXMLDI.item(objBound.item(arrKeys).datasrc).getElementsByTagName(objBound.item(arrKeys).datafld).item(0).firstChild.nodeValue;
                                  else
                                    objBound.item(arrKeys).node.checked = eval(objXMLDI.item(objBound.item(arrKeys).datasrc).getElementsByTagName(objBound.item(arrKeys).datafld).item(0).firstChild.nodeValue);
                                }
                                catch(e) { }
                 
                                    if(objBound.item(arrKeys).node.getAttribute('type') != 'checkbox')
                                  objBound.item(arrKeys).node.onchange = new Function('try { objXMLDI.item(this.getAttribute('datasrc')).getElementsByTagName(this.getAttribute('datafld')).item(0).firstChild.nodeValue = this.value } catch(e) { objXMLDI.item(this.getAttribute('datasrc')).getElementsByTagName(this.getAttribute('datafld')).item(0).appendChild(document.createTextNode(this.value)) };MozillaDSO()');
                                else
                                  objBound.item(arrKeys).node.onclick = new Function('try { objXMLDI.item(this.getAttribute('datasrc')).getElementsByTagName(this.getAttribute('datafld')).item(0).firstChild.nodeValue = this.checked } catch(e) { objXMLDI.item(this.getAttribute('datasrc')).getElementsByTagName(this.getAttribute('datafld')).item(0).appendChild(document.createTextNode(this.checked)) };MozillaDSO()');
                              }
                            }
                            catch(e) { }
                 
                            break;
                          case('div'):
                          case('span'):
                            if(typeof(objBound.item(arrKeys).datasrc) == 'string') {
                              try {                              //  Text node exists
                                objBound.item(arrKeys).node.firstChild.nodeValue = objXMLDI.item(objBound.item(arrKeys).datasrc).getElementsByTagName(objBound.item(arrKeys).datafld).item(0).firstChild.nodeValue;
                              }
                              catch(e) {                         //  Create text node
                                try {
                                  objBound.item(arrKeys).node.appendChild(document.createTextNode(objXMLDI.item(objBound.item(arrKeys).datasrc).getElementsByTagName(objBound.item(arrKeys).datafld).item(0).firstChild.nodeValue));
                                }
                                catch(e) { }
                             }
                            }
                 
                            break;
                          default:
                            alert('Error: Unsupported HTML Element - ' + objBound.item(arrKeys).nodeName.toLowerCase());
                 
                            break;
                        }
                    }
                 
                  function boundXML() {
                    var datasrc = null;                          //  Data source (string)
                    var datafld = null;                          //  Data field (string)
                    var node = null;                             //  XHTML node (object)
                    var nodeName = null;                         //  Node name (string)
                  }
                }
                 
                function collection() {
                  /* Function:      collection
                     Creation Date: August 16, 2002
                     Programmer:    Edmond Woychowsky
                     Purpose:       The purpose of this class is to define the collection
                                    object associative array.
                 
                     Update Date:       Programmer:              Description:
                  */
                 
                                                                 //  Properties
                  this.objcollection = new Object;               //  Associative array
                  this.count = 0;                               //  Total numbers of items
                 
                                                                 //  Methods
                  this.add = colAdd;                             //  Add method
                  this.exists = colExists;                       //  Exists method
                  this.item = colItem;                          //  Item method
                  this.removeAll = colRemoveAll;                 //  Remove all method
                  this.remove = colRemove;                       //  Remove method
                  this.keys = colKeys;                           //  Keys method
                 
                  function colAdd(strKey,strItem) {
                    /* Function:      colAdd
                       Creation Date: August 16, 2002
                       Programmer:    Edmond Woychowsky
                       Purpose:       The purpose of this function is to add an item to
                                      the collection object.
                 
                      Update Date:       Programmer:              Description:
                    */
                 
                    if(typeof(this.objcollection[strKey]) == 'undefined')
                      ++this.count;
                 
                      this.objcollection[strKey] = strItem;
                  }
                 
                  function colExists(strKey) {
                    /* Function:      colExists
                       Creation Date: August 16, 2002
                       Programmer:    Edmond Woychowsky
                       Purpose:       The purpose of this function is to return a boolean
                                      indicating where or not a key exists in the
                                      collection object.
                 
                       Update Date:       Programmer:              Description:
                    */
                 
                    if(typeof(this.objcollection[strKey]) == 'undefined')
                      return false;
                    else
                      return true;
                  }
                 
                  function colItem(strKey,strItem) {
                    /* Function:     colItem
                       Creation Date: August 16, 2002
                       Programmer:    Edmond Woychowsky
                       Purpose:       The purpose of this function is to either set or get
                                      an item to or from the collection object.
                 
                       Update Date:       Programmer:              Description:
                    */
                 
                    if(typeof(strItem) == 'undefined')
                      return this.objcollection[strKey];
                    else {
                      if(typeof(this.objcollection[strKey]) == 'undefined')
                        ++this.count;
                 
                      this.objcollection[strKey] = strItem;
                    }
                  }
                 
                  function colRemoveAll() {
                    /* Function:      colRemoveAll
                       Creation Date: August 16, 2002
                       Programmer:    Edmond Woychowsky
                       Purpose:       The purpose of this function is to remove all keys
                                      and items from the collection object and set the
                                      item count to zero.
                 
                       Update Date:       Programmer:              Description:
                    */
                 
                    this.objcollection = new Object;
                    this.count = 0;
                  }
                 
                  function colRemove(strKey) {
                    /* Function:      colRemove
                       Creation Date: August 16, 2002
                       Programmer:    Edmond Woychowsky
                       Purpose:       The purpose of this function is to remove a single
                                      item and it's associated key from the collection
                                      object and decrement the count by one.
                 
                       Update Date:       Programmer:              Description:
                    */
                 
                    if(typeof(strItem) != 'undefined') {
                      this.objcollection[strKey] == 'undefined';
                      --this.count;
                    }
                  }
                 
                  function colKeys() {
                    /* Function:      colKeys
                       Creation Date: August 16, 2002
                       Programmer:    Edmond Woychowsky
                       Purpose:       The purpose of this function is to return an array
                                     consisting of the collection object's keys.
                 
                       Update Date:       Programmer:              Description:
                    */
                 
                    var arrWork = new Array();
                    var strKey;
                 
                    for(strKey in this.objcollection)
                      if(this.objcollection[strKey] != 'undefined')
                        arrWork.push(strKey);
                 
                    return arrWork;
                  }
                }
                // ]]> -->
                </script>
                </head>
                  <body onload="setEvents()">
                     <table width="100%" border="0">
                          <tr>
                               <td width="100%" align="center" bgcolor="black" >
                                   <font color="white" size="8pt"><%=strTitle %></font>
                               </td>
                          </tr>
                     </table>
                     <table width="100%" height="450" border="0">
                       <tr>
                         <td align="left" valign="top">
                           <table id="boundTable" datasrc="#xmlWindow" width="100%" border="1" onreadystatechange="ieBusTable(this)">
                            <thead>
                              <td bgcolor="#FFFFEE" width="5%"><b>Delete</b></td>
                              <td bgcolor="#FFFFEE" width="5%"><b>Line</b></td>
                              <td bgcolor="#FFFFEE" width="20%"><b>Item number</b></td>
                              <td bgcolor="#FFFFEE" width="30%"><b>Description</b></td>
                              <td bgcolor="#FFFFEE" width="25%"><b>Weight</b></td>
                              <td bgcolor="#FFFFEE" width="7%"><b>Quantity</b></td>
                              <td bgcolor="#FFFFEE" width="8%"><b>Unit Price</b></td>
                            </thead>
                            <tr>
                              <td align="center" valign="top">
                                    <input type="hidden" id="line" name="line" datafld="line" />
                                    <input type="checkbox" id="selected" name="selected" datafld="selected" />
                              </td>
                              <td align="right" valign="top">
                                <div datafld="line"></div>
                              </td>
                              <td valign="top">
                                <div datafld="item"></div>
                              </td>
                              <td valign="top">
                                <div datafld="description"></div>
                              </td>
                              <td valign="top">
                                <div datafld="weight"></div>
                              </td>
                              <td align="center" valign="top">
                                    <input type="text" id="quantity" name="quantity" datafld="quantity" style="text-align: right" size="5" maxlength="3" />
                              </td>
                              <td align="right" valign="top">
                                <div datafld="unitprice"></div>
                              </td>
                            </tr>
                          </table>
                         </td>
                       </tr>
                       <tr>
                         <td align="bottom">
                           <table width="100%" border="0">
                            <tr>
                              <td align="right">
                                   Page <span id="currentpage"></span> of <span id="totalpages"></span>
                              </td>
                            </tr>
                          </table>
                         </td>
                       </tr>
                     </table>
                    <p />
                    <table width="100%" border="0">
                      <tr>
                        <td width="12%">
                          <input type="button" name="First" id="First" value="First" onclick="document.body.style.cursor = 'wait';objPage.showFirst();document.getElementById('currentpage').lastChild.nodeValue = objPage.page();document.body.style.cursor = 'auto'" />
                        </td>
                        <td width="12%">
                          <input type="button" name="Next" id="Next" value="Next" onclick="document.body.style.cursor = 'wait';objPage.showNext();document.getElementById('currentpage').lastChild.nodeValue = objPage.page();document.body.style.cursor = 'auto'" />
                        </td>
                        <td width="12%">
                          <input type="button" name="Previous" id="Previous" value="Previous" onclick="document.body.style.cursor = 'wait';objPage.showPrevious();document.getElementById('currentpage').lastChild.nodeValue = objPage.page();document.body.style.cursor = 'auto'" />
                        </td>
                        <td width="12%">
                          <input type="button" name="Last" id="Last" value="Last" onclick="document.body.style.cursor = 'wait';objPage.showLast();document.getElementById('currentpage').lastChild.nodeValue = objPage.page();document.body.style.cursor = 'auto'" />
                        </td>
                        <td width="12%"> </td>
                        <td width="12%">
                          <input type="button" name="Update" id="Update" value="Update" onclick="document.body.style.cursor = 'wait';update();document.body.style.cursor = 'auto'" />
                        </td>
                        <td> </td>
                      </tr>
                    </table>
                    <xml id="xmlWindow" async="false">
                    </xml>
                    <xml id="xmlFull" async="false"><%=Session("shoppingcart") %></xml>
                  </body>
                </html>
                </td>
        </tr>
</table>

</body>

</html>



服务器端
一旦客户端的代码编写完成,就到了把注意力集中到购物车的服务器端上了。创建购物车的机制因电子商务系统的差异而有所不同,但是XLM数据岛的基本布局就像下面列表D里面的一样。

列表D

<%@ Language=JScript %>

<%

/* ASP:               xmlServer

Creation Date: May 12, 2003

Programmer:    Edmond Woychowsky

Purpose:       The purpose of this script is to handle client-side changes

to the contents of an XML "shopping cart".


Update Date:       Programmer:              Description:

*/

var objXML = new ActiveXObject('MSXML2.FreeThreadedDOMDocument.4.0');

objXML.loadXML(unescape(Request.ServerVariables.Item('HTTP_request')));


if(objXML.parseError == 0) {                    //     Delete rows

for(var i=0;i < objXML.getElementsByTagName('row').length;i++)

if(eval(objXML.getElementsByTagName('selected').item(i).text)) {

objXML.getElementsByTagName('root').item(0).removeChild(objXML.getElementsByTagName('row').item(i));


--i;

}


//     Resequence lines

for(var i=0;i < objXML.getElementsByTagName('line').length;i++)

objXML.getElementsByTagName('line').item(i).text = (i + 1).toString();


Session('shoppingcart') = objXML.xml;     //     Update session variable

}


Response.Write(Session('shoppingcart'));     //     Respond to client


objXML = null;

//     Clean up

%>



由于这只是一个演示版的应用程序,所以客户端页面代码之后部分(见列表C)并没有显示出购物车最初是如何创建的,也没有显示任何数据库逻辑。它把重点放在了购物车的操控上(见列表D)。当第一件物品被选中的时候,利用XML文档对象模型(DOM),或者通过使用ADO的保存方法和XSLT就可以完成创建购物车了。以后的物品简单地通过使用DOM或者XSLT就可以加在后面了。

检验过程就是数据库逻辑所在的地方。我使用DOM来浏览XML购物车,使用一个Oracle存储过程来更新或者添加数据行,这真的对那些使用SQL服务器或者MySQL的购物车没有什么帮助。

第二次会更好
使用XML数据岛比较容易让HTML具有清爽的外观。这里没有一行接一行的服务器端代码,也没有嵌入在循环里的单行HTML,这里有的是一行HTML。当有人在你刚刚完成购物车应用程序就建议添加一个数据列的时候,这个方法可以帮助你避免一些开发人员需要面对的维护恶梦。
台州维博网络(www.tzweb.com)专门运用PHP+MYSQL/ASP.NET+MSSQL技术开发网站门户平台系统等。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

网站推广
关于我们
  • 台州朗动科技(Tzweb.com)拥有多年开发网站平台系统门户手机客户端等业务的成功经验。主要从事:政企网站,系统平台,微信公众号,各类小程序,手机APP客户端,浙里办微应用,浙政钉微应用、主机域名、虚拟空间、后期维护等服务,满足不同企业公司的需求,是台州地区领先的网络技术服务商!

Hi,扫描关注我

Copyright © 2005-2026 站长论坛 All rights reserved

Powered by 站长论坛 with TZWEB Update Techonolgy Support

快速回复 返回顶部 返回列表