/* WDDX Serializer/Deserializer for Flash MX v1.0 -------------------------------------------------- Created by Branden Hall (bhall@figleaf.com) Dave Gallerizzo (dgallerizzo@figleaf.com) Based on code by Simeon Simeonov (simeons@allaire.com) Nate Weiss (nweiss@icesinc.com) Version History: 8/10/2000 - First created 9/5/2000 - Minor bug fix to the deserializer 9/15/2000 - Commented out wddxserializetype creation in the deserializer as they are not needed in most cases. 9/21/2000 - Simplified the use of the deserializer. No longer need to create the XML object yourself and the load and onLoad methods are part of the WDDX class. 9/30/2000 - Cleaned up code and removed load and onLoad methods. Updated sample code. 12/28/2000 - Added new duplicate method to WddxRecordset object 1/10/2001 - Fixed problem where serialization caused text to always drop to lower case. Thanks to Bill Tremblay for spotting this one! 1/17/2001 - Minor update to the serializer code so that it properly adds text nodes. Thanks for the catch from Carlos Mathews! Also, the deserialization of primitive types now results in primitives rather than instances of the object wrapper 1/20/2001 - Quick fix to the deserializer for recordsets so that for..in loops can get the elements of the recordset in the proper order. 2/5/2001 - Fix to the string deserialization so that it handles special characters properly, thanks to Spike Washburn for this one! 11/9/2001 - Finished small optimizations, fixed encoding issues and fixed case preservation issue. 11/16/01 - (bkruse@macromedia.com)- put all WDDX classes in Object.WDDX namespace to fix scoping issues. 4/19/2002 - Fixed various small bugs with date and number serialization/deserialization 4/19/2002 - Removed WDDX classes from WDDX namespace and put into _global namespace Authors notes: Serialization: - Create an instance of the wddx class - Call the serialize method, passing it the object your wish to serialize, it will return an XML object filled with the serialized object. Example: myXML = new XML(); foo = new WDDX(); myXML = foo.serialize(bar); Deserializtion: - Get the XML you want to deserialize - Create an instance of the WDDX class - Call the serialize method of your WDDX object and pass it your XML. It will return the deserialized object. Example: myXML = new XML(); // // XML is loaded here // foo = new WDDX(); myObj = foo.deserialize(myXML); - Branden 9/30/00 */ //------------------------------------------------------------------------------------------------- // WddxRecordset object //------------------------------------------------------------------------------------------------- // WddxRecordset([flagPreserveFieldCase]) creates an empty recordset. // WddxRecordset(columns [, flagPreserveFieldCase]) creates a recordset // with a given set of columns provided as an array of strings. // WddxRecordset(columns, rows [, flagPreserveFieldCase]) creates a // recordset with these columns and some number of rows. // In all cases, flagPreserveFieldCase determines whether the exact case // of field names is preserved. If omitted, the default value is false // which means that all field names will be lowercased. _global.WddxRecordset = function () { // Add default properties this.preserveFieldCase = true; // Add extensions if (typeof (wddxRecordsetExtensions) == "object") { for (prop in wddxRecordsetExtensions) { // Hook-up method to WddxRecordset object this[prop] = wddxRecordsetExtensions[prop]; } } // Perfom any needed initialization if (arguments.length>0) { if (typeof (val=arguments[0].valueOf()) == "boolean") { // Case preservation flag is provided as 1st argument this.preserveFieldCase = arguments[0]; } else { // First argument is the array of column names var cols = arguments[0]; // Second argument could be the length or the preserve case flag var nLen = 0; if (arguments.length>1) { if (typeof (val=arguments[1].valueOf()) == "boolean") { // Case preservation flag is provided as 2nd argument this.preserveFieldCase = arguments[1]; } else { // Explicitly specified recordset length nLen = arguments[1]; if (arguments.length>2) { // Case preservation flag is provided as 3rd argument this.preserveFieldCase = arguments[2]; } } } for (var i = 0; i0) { colNamesList+=","; } colNamesList+=col; } } var nRows = this.getRowCount(); node.appendChild((new XML()).createElement("recordset")); node.lastChild.attributes["rowCount"] = nRows; node.lastChild.attributes["fieldNames"] = colNamesList; var bSuccess = true; for (i=0; bSuccess && i"; at[i] = ""; } else if (i<128) { et[i] = chr(i); at[i] = chr(i); } else { et[i] = "&#x"+i.toString(16)+";"; etRev["&#x"+i.toString(16)+";"] = chr(i); at[i] = "&#x"+i.toString(16)+";"; atRev["&#x"+i.toString(16)+";"] = chr(i); } } et[ord("<")] = "<"; et[ord(">")] = ">"; et[ord("&")] = "&"; etRev["<"] = "<"; etRev[">"] = ">"; etRev["&"] = "&"; at[ord("<")] = "<"; at[ord(">")] = ">"; at[ord("&")] = "&"; at[ord("'")] = "'"; at[ord("\"")] = """; atRev["<"] = "<"; atRev[">"] = ">"; atRev["&"] = "&"; atRev["'"] = "'"; atRev["""] = "\""; this.et = et; this.at = at; this.atRev = atRev; this.etRev = etRev; // Deal with timezone offsets var tzOffset = (new Date()).getTimezoneOffset(); if (tzOffset>=0) { this.timezoneString = "-"; } else { this.timezoneString = "+"; } this.timezoneString+=Math.floor(Math.abs(tzOffset)/60)+":"+(Math.abs(tzOffset)%60); this.preserveVarCase = true; this.useTimezoneInfo = true; } // Serialize a Flash object Wddx.prototype.serialize = function(rootObj) { delete(this.wddxPacket); var temp = new XML(); this.packet = new XML(); this.packet.appendChild(temp.createElement("wddxPacket")); this.wddxPacket = this.packet.firstChild; this.wddxPacket.attributes["version"] = "1.0"; this.wddxPacket.appendChild(temp.createElement("header")); this.wddxPacket.appendChild(temp.createElement("data")); if (this.serializeValue(rootObj, this.wddxPacket.childNodes[1])) { return this.packet; } else { return null; } } // Determine the type of a Flash object and serialize it Wddx.prototype.serializeValue = function(obj, node) { var bSuccess = true; var val = obj.valueOf(); var tzString = null; var temp = new XML(); // null object if (obj == null) { node.appendChild(temp.createElement("null")); // string object } else if (typeof (val) == "string") { this.serializeString(val, node); // numeric objects (number or date) } else if (typeof (val) == "number") { // date object if (typeof (obj.getTimezoneOffset) == "function") { // deal with timezone offset if asked to if (this.useTimeZoneInfo) { tzString = this.timezoneString; } node.appendChild(temp.createElement("dateTime")); node.lastChild.appendChild(temp.createTextNode(obj.getFullYear()+"-"+(obj.getMonth()+1)+"-"+obj.getDate()+"T"+obj.getHours()+":"+obj.getMinutes()+":"+obj.getSeconds()+tzString)); // number object } else { node.appendChild((new XML()).createElement("number")); node.lastChild.appendChild((new XML()).createTextNode(val)); } // boolean object } else if (typeof (val) == "boolean") { node.appendChild(temp.createElement("boolean")); node.lastChild.attributes["value"] = val; // actual objects } else if (typeof (obj) == "object") { // if it has a built in serializer, use it if (typeof (obj.wddxSerialize) == "function") { bSuccess = obj.wddxSerialize(this, node); // array object } else if (typeof (obj.join) == "function" && typeof (obj.reverse) == "function") { node.appendChild(temp.createElement("array")); node.lastChild.attributes["length"] = obj.length; for (var i = 0; bSuccess && i 1) { dataObj = "" var i = 0; for(i=0; i=0; i--) { if (node.childNodes[i].nodeName.toLowerCase() == "field") { var attr = this.deserializeAttr(node.childNodes[i].attributes["name"]) dataObj[attr].wddxSerializationType = "field"; for (var j = (node.childNodes[i].childNodes.length-1); j>=0; j--) { dataObj[attr][j] = new Object(); tempObj = this.deserializeNode(node.childNodes[i].childNodes[j]); dataObj.setField(j, attr, tempObj); } } } // dataObj.wddxSerializationType = "recordset"; return dataObj; } } Wddx.prototype.deserializeAttr = function(attr){ var max = attr.length; var i=0; var char; var output = ""; while (i