home *** CD-ROM | disk | FTP | other *** search
/ Australian Personal Computer 1999 April / APC443.iso / features / grpware / coldfus / coldfusi.exe / data1.cab / JavaScript / scripts / wddx.js
Encoding:
JavaScript  |  1998-10-08  |  13.0 KB  |  520 lines

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. //    WddxSerializer
  4. //
  5. ///////////////////////////////////////////////////////////////////////////
  6.  
  7.  
  8. ///////////////////////////////////////////////////////////////////////////
  9. //     serializeValue() serializes any value that can be serialized
  10. //    returns true/false
  11. function wddxSerializer_serializeValue(obj)
  12. {
  13.     var bSuccess = true;
  14.  
  15.     if (typeof(obj) == "string")
  16.     {
  17.         // String value
  18.         this.serializeString(obj);
  19.     }
  20.     else if (typeof(obj) == "number")
  21.     {
  22.         // Number value
  23.         this.write("<number>" + obj + "</number>");
  24.     }
  25.     else if (typeof(obj) == "boolean")
  26.     {
  27.         // Boolean value
  28.         this.write("<boolean value='" + obj + "'/>");
  29.     }
  30.     else if (typeof(obj) == "object")
  31.     {
  32.         if (obj == null)
  33.         {
  34.             // Null values become empty strings
  35.             this.write("<string></string>");
  36.         }
  37.         else if (typeof(obj.wddxSerialize) == "function")
  38.         {
  39.             // Object knows how to serialize itself
  40.             bSuccess = obj.wddxSerialize(this);
  41.         }
  42.         else if (
  43.             typeof(obj.join) == "function" &&
  44.             typeof(obj.reverse) == "function" &&
  45.             typeof(obj.sort) == "function" &&
  46.             typeof(obj.length) == "number")
  47.         {
  48.             this.write("<array length='" + obj.length + "'>");
  49.             for (var i = 0; bSuccess && i < obj.length; ++i)
  50.             {
  51.                 bSuccess = this.serializeValue(obj[i]);
  52.             }
  53.             this.write("</array>");
  54.         }
  55.         else if (
  56.             typeof(obj.getTimezoneOffset) == "function" &&
  57.             typeof(obj.toGMTString) == "function")
  58.         {
  59.             // Possible Date
  60.             this.write(    "<dateTime>" + 
  61.                 obj.getYear() + "-" + (obj.getMonth() + 1) + "-" + obj.getDate() +
  62.                 "T" + obj.getHours() + ":" + obj.getMinutes() + ":" + obj.getSeconds());
  63.             if (this.useTimezoneInfo)
  64.             {
  65.                 this.write(this.timezoneString);
  66.             }
  67.             this.write("</dateTime>");
  68.         }
  69.         else
  70.         {
  71.             // Some generic object; treat it as a structure
  72.             this.write("<struct>");
  73.             for (var prop in obj)
  74.             {
  75.                 bSuccess = this.serializeVariable(prop, obj[prop]);
  76.                 if (! bSuccess)
  77.                 {
  78.                     break;
  79.                 }
  80.             }
  81.             this.write("</struct>");
  82.         }
  83.     }
  84.     else
  85.     {
  86.         // Error: undefined values or functions
  87.         bSuccess = false;
  88.     }
  89.  
  90.     // Successful serialization
  91.     return bSuccess;
  92. }
  93.  
  94.  
  95. ///////////////////////////////////////////////////////////////////////////
  96. //     serializeString() serializes a string using JavaScript functionality
  97. //    available in NS 3.0 and above
  98. function wddxSerializer_serializeString(s)
  99. {
  100.     this.write("<string>");
  101.     for (var i = 0; i < s.length; ++i)
  102.     {
  103.         this.write(this.et[s.charAt(i)]);
  104.     }
  105.     this.write("</string>");
  106. }
  107.  
  108.  
  109. ///////////////////////////////////////////////////////////////////////////
  110. //     serializeStringOld() serializes a string using JavaScript functionality
  111. //    available in IE 3.0
  112. function wddxSerializer_serializeStringOld(s)
  113. {
  114.     this.write("<string><![CDATA[");
  115.     
  116.     pos = s.indexOf("]]>");
  117.     if (pos != -1)
  118.     {
  119.         startPos = 0;
  120.         while (pos != -1)
  121.         {
  122.             this.write(s.substring(startPos, pos) + "]]>]]><![CDATA[");
  123.             
  124.             startPos = pos + 3;
  125.             if (startPos < s.length)
  126.             {
  127.                 pos = s.indexOf("]]>", startPos);
  128.             }
  129.             else
  130.             {
  131.                 // Work around bug in indexOf()
  132.                 // "" will be returned instead of -1 if startPos > length
  133.                 pos = -1;
  134.             }                               
  135.         }
  136.         this.write(s.substring(startPos, s.length));
  137.     }
  138.     else
  139.     {
  140.         this.write(s);
  141.     }
  142.             
  143.     this.write("]]></string>");
  144. }
  145.  
  146.  
  147. ///////////////////////////////////////////////////////////////////////////
  148. //     serializeVariable() serializes a property of a structure
  149. //    returns true/false
  150. function wddxSerializer_serializeVariable(name, obj)
  151. {
  152.     var bSuccess = true;
  153.     
  154.     if (typeof(obj) != "function")
  155.     {
  156.         this.write("<var name='" + name.toUpperCase() + "'>");
  157.         bSuccess = this.serializeValue(obj);
  158.         this.write("</var>");
  159.     }
  160.  
  161.     return bSuccess;
  162. }
  163.  
  164.  
  165. ///////////////////////////////////////////////////////////////////////////
  166. //    write() appends text to the wddxPacket buffer
  167. function wddxSerializer_write(str)
  168. {
  169.     this.wddxPacket += str;
  170. }
  171.  
  172.  
  173. ///////////////////////////////////////////////////////////////////////////
  174. //    serialize() creates a WDDX packet for a given object
  175. //    returns the packet on success or null on failure
  176. function wddxSerializer_serialize(rootObj)
  177. {
  178.     this.wddxPacket = "";
  179.  
  180.     this.write("<wddxPacket version='0.9'><header/><data>");
  181.     var bSuccess = this.serializeValue(rootObj);
  182.     this.write("</data></wddxPacket>");
  183.  
  184.     if (bSuccess)
  185.     {
  186.         return this.wddxPacket;
  187.     }
  188.     else
  189.     {    
  190.         return null;
  191.     }
  192. }
  193.  
  194.  
  195. ///////////////////////////////////////////////////////////////////////////
  196. // WddxSerializer() binds the function properties of the object
  197. function WddxSerializer()
  198. {
  199.     // Compatibility section
  200.     if (navigator.appVersion != "" && navigator.appVersion.indexOf("MSIE 3.") == -1)
  201.     {
  202.         // Character encoding table
  203.         
  204.         // Encoding table    
  205.         var et = new Array();
  206.     
  207.         // Numbers to characters table and 
  208.         // characters to numbers table
  209.         var n2c = new Array();
  210.         var c2n = new Array();
  211.     
  212.         for (var i = 0; i < 256; ++i)
  213.         {
  214.             // Build a character from octal code
  215.             var d1 = Math.floor(i/64);
  216.             var d2 = Math.floor((i%64)/8);
  217.             var d3 = i%8;
  218.             var c = eval("\"\\" + d1.toString(10) + d2.toString(10) + d3.toString(10) + "\"");
  219.     
  220.             // Modify character-code conversion tables        
  221.             n2c[i] = c;
  222.             c2n[c] = i; 
  223.             
  224.             // Modify encoding table
  225.             if (i < 32 && i != 9 && i != 10 && i != 13)
  226.             {
  227.                 // Control characters that are not tabs, newlines, and carriage returns
  228.                 
  229.                 // Create a two-character hex code representation
  230.                 var hex = i.toString(16);
  231.                 if (hex.length == 1)
  232.                 {
  233.                     hex = "0" + hex;
  234.                 }
  235.                 
  236.                 et[n2c[i]] = "<char code='" + hex + "'/>";
  237.             }
  238.             else if (i < 128)
  239.             {
  240.                 // Low characters that are not special control characters
  241.                 et[n2c[i]] = n2c[i];
  242.             }
  243.             else
  244.             {
  245.                 // High characters
  246.                 et[n2c[i]] = "&#x" + i.toString(16) + ";";
  247.             }
  248.         }    
  249.     
  250.         // Special escapes
  251.         et["<"] = "<";
  252.         et[">"] = ">";
  253.         et["&"] = "&";
  254.         
  255.         // Store tables
  256.         this.n2c = n2c;
  257.         this.c2n = c2n;
  258.         this.et = et;    
  259.         
  260.            // The browser is not MSIE 3.x
  261.         this.serializeString = wddxSerializer_serializeString;
  262.     }
  263.     else
  264.     {
  265.         // The browser is most likely MSIE 3.x, it is NS 2.0 compatible
  266.         this.serializeString = wddxSerializer_serializeStringOld;
  267.     }
  268.     
  269.     // Setup timezone information
  270.     
  271.     var tzOffset = (new Date()).getTimezoneOffset();
  272.  
  273.     // Invert timezone offset to convert local time to UTC time
  274.     if (tzOffset >= 0)
  275.     {
  276.         this.timezoneString = '-';
  277.     }
  278.     else
  279.     {
  280.         this.timezoneString = '+';
  281.     }
  282.     this.timezoneString += Math.floor(Math.abs(tzOffset) / 60) + ":" + (Math.abs(tzOffset) % 60);
  283.     
  284.     // Common properties
  285.     this.useTimezoneInfo = true;
  286.  
  287.     // Common functions
  288.     this.serialize = wddxSerializer_serialize;
  289.     this.serializeValue = wddxSerializer_serializeValue;
  290.     this.serializeVariable = wddxSerializer_serializeVariable;
  291.     this.write = wddxSerializer_write;
  292. }
  293.  
  294.  
  295. ///////////////////////////////////////////////////////////////////////////
  296. //
  297. //    WddxRecordset
  298. //
  299. ///////////////////////////////////////////////////////////////////////////
  300.  
  301.  
  302. ///////////////////////////////////////////////////////////////////////////
  303. //     getRowCount() returns the number of rows in the recordset
  304. function wddxRecordset_getRowCount()
  305. {
  306.     var nRowCount = 0;
  307.     for (var col in this)
  308.     {
  309.         if (typeof(this[col]) == "object")
  310.         {
  311.             nRowCount = this[col].length;
  312.             break;
  313.         }
  314.     }
  315.     return nRowCount;
  316. }
  317.  
  318.  
  319. ///////////////////////////////////////////////////////////////////////////
  320. //     addColumn(name) adds a column with that name and length == getRowCount()
  321. function wddxRecordset_addColumn(name)
  322. {
  323.     var nLen = this.getRowCount();
  324.     var colValue = new Array(nLen);
  325.     for (var i = 0; i < nLen; ++i)
  326.     {
  327.         colValue[i] = null;
  328.     }
  329.     this[name] = colValue;
  330. }
  331.  
  332.  
  333. ///////////////////////////////////////////////////////////////////////////
  334. //     addRows() adds n rows to all columns of the recordset
  335. function wddxRecordset_addRows(n)
  336. {
  337.     for (var col in this)
  338.     {
  339.         var nLen = this[col].length;
  340.         for (var i = nLen; i < nLen + n; ++i)
  341.         {
  342.             this[col][i] = null;
  343.         }
  344.     }
  345. }
  346.  
  347.  
  348. ///////////////////////////////////////////////////////////////////////////
  349. //     getField() returns the element in a given (row, col) position
  350. function wddxRecordset_getField(row, col)
  351. {
  352.     return this[col][row];
  353. }
  354.  
  355.  
  356. ///////////////////////////////////////////////////////////////////////////
  357. //     setField() sets the element in a given (row, col) position to value
  358. function wddxRecordset_setField(row, col, value)
  359. {
  360.     this[col][row] = value;
  361. }
  362.  
  363.  
  364. ///////////////////////////////////////////////////////////////////////////
  365. //     wddxSerialize() serializes a recordset
  366. //    returns true/false
  367. function wddxRecordset_wddxSerialize(serializer)
  368. {
  369.     // Create an array and a list of column names
  370.     var colNamesList = "";
  371.     var colNames = new Array();
  372.     var i = 0;
  373.     for (var col in this)
  374.     {
  375.         if (typeof(this[col]) == "object")
  376.         {
  377.             colNames[i++] = col;
  378.  
  379.             if (colNamesList.length > 0)
  380.             {
  381.                 colNamesList += ",";
  382.             }
  383.             colNamesList += col;            
  384.         }
  385.     }
  386.     
  387.     var nRows = this.getRowCount();
  388.     
  389.     serializer.write("<recordset rowCount='" + nRows + "' fieldNames='" + colNamesList + "'>");
  390.     
  391.     var bSuccess = true;
  392.     for (i = 0; bSuccess && i < colNames.length; i++)
  393.     {
  394.         var name = colNames[i];
  395.         serializer.write("<field name='" + name + "'>");
  396.         
  397.         for (var row = 0; bSuccess && row < nRows; row++)
  398.         {
  399.             bSuccess = serializer.serializeValue(this[name][row]);
  400.         }
  401.         
  402.         serializer.write("</field>");
  403.     }
  404.     
  405.     serializer.write("</recordset>");
  406.     
  407.     return bSuccess;
  408. }
  409.  
  410.  
  411. ///////////////////////////////////////////////////////////////////////////
  412. //     dump(escapeStrings) returns an HTML table with the recordset data
  413. //    It is a convenient routine for debugging and testing recordsets
  414. //    The boolean parameter escapeStrings determines whether the <>& 
  415. //    characters in string values are escaped as <>&
  416. function wddxRecordset_dump(escapeStrings)
  417. {
  418.     // Get row count
  419.     var nRows = this.getRowCount();
  420.     
  421.     // Determine column names
  422.     var colNames = new Array();
  423.     var i = 0;
  424.     for (var col in this)
  425.     {
  426.         if (typeof(this[col]) == "object")
  427.         {
  428.             colNames[i++] = col;
  429.         }
  430.     }
  431.  
  432.     // Build table headers    
  433.     var o = "<table border=1><tr><td><b>RowNumber</b></td>";
  434.     for (i = 0; i < colNames.length; ++i)
  435.     {
  436.         o += "<td><b>" + colNames[i] + "</b></td>";
  437.     }
  438.     o += "</tr>";
  439.     
  440.     // Build data cells
  441.     for (var row = 0; row < nRows; ++row)
  442.     {
  443.         o += "<tr><td>" + row + "</td>";
  444.         for (i = 0; i < colNames.length; ++i)
  445.         {
  446.             var elem = this.getField(row, colNames[i]);
  447.             if (escapeStrings && typeof(elem) == "string")
  448.             {
  449.                 var str = "";
  450.                 for (var j = 0; j < elem.length; ++j)
  451.                 {
  452.                     var ch = elem.charAt(j);
  453.                     if (ch == '<')
  454.                     {
  455.                         str += "<";
  456.                     }
  457.                     else if (ch == '>')
  458.                     {
  459.                         str += ">";
  460.                     }
  461.                     else if (ch == '&')
  462.                     {
  463.                         str += "&";
  464.                     }
  465.                     else
  466.                     {
  467.                         str += ch;
  468.                     }
  469.                 }            
  470.                 o += ("<td>" + str + "</td>");
  471.             }
  472.             else
  473.             {
  474.                 o += ("<td>" + elem + "</td>");
  475.             }
  476.         }
  477.         o += "</tr>";
  478.     }
  479.  
  480.     // Close table
  481.     o += "</table>";
  482.  
  483.     // Return HTML recordset dump
  484.     return o;    
  485. }
  486.  
  487.  
  488. ///////////////////////////////////////////////////////////////////////////
  489. // WddxRecordset() creates an empty recordset
  490. // WddxRecordset(columns) creates a recordset with these columns
  491. // WddxRecordset(columns, rows) creates a recordset with these columns and some number of rows
  492. function WddxRecordset()
  493. {
  494.     this.getRowCount = wddxRecordset_getRowCount;
  495.     this.addColumn = wddxRecordset_addColumn;
  496.     this.addRows = wddxRecordset_addRows;
  497.     this.getField = wddxRecordset_getField;
  498.     this.setField = wddxRecordset_setField;
  499.     this.wddxSerialize = wddxRecordset_wddxSerialize;
  500.     this.dump = wddxRecordset_dump;
  501.     
  502.     if (WddxRecordset.arguments.length > 0)
  503.     {
  504.         var cols = WddxRecordset.arguments[0];
  505.         var nLen = WddxRecordset.arguments.length > 1 ? WddxRecordset.arguments[1] : 0;
  506.         
  507.         for (var i = 0; i < cols.length; ++i)
  508.         {
  509.              var colValue = new Array(nLen);
  510.             for (var j = 0; j < nLen; ++j)
  511.             {
  512.                 colValue[j] = null;
  513.             }
  514.         
  515.             this[cols[i]] = colValue;
  516.         }        
  517.     }
  518. }
  519.  
  520.