| dojo.provide("tapestry.core"); |
| dojo.provide("tapestry.html"); |
| dojo.provide("tapestry.event"); |
| dojo.provide("tapestry.lang"); |
| |
| dojo.provide("dojo.AdapterRegistry"); |
| dojo.provide("dojo.json"); |
| |
| dojo.require("dojo.lang.common"); |
| dojo.require("dojo.io.BrowserIO"); |
| dojo.require("dojo.event.browser"); |
| dojo.require("dojo.html.style"); |
| dojo.require("dojo.lang.func"); |
| dojo.require("dojo.string.extras"); |
| |
| |
| // redirect logging calls to standard debug if logging not enabled |
| if (dj_undef("logging", dojo)) { |
| dojo.log = { |
| debug:function(){ |
| dojo.debug.apply(this, arguments); |
| }, |
| info:function(){ |
| dojo.debug.apply(this, arguments); |
| }, |
| warn:function(){ |
| dojo.debug.apply(this, arguments); |
| }, |
| err:function(){ |
| dojo.debug.apply(this, arguments); |
| }, |
| exception:function(){ |
| dojo.debug.apply(this, arguments); |
| } |
| } |
| } |
| |
| /** |
| * package: tapestry |
| * Provides the core functionality for the Tapestry javascript package libraries. |
| * |
| * Most of the functions in here are related to initiating and parsing IO |
| * requests. |
| */ |
| var tapestry={ |
| |
| // property: version |
| // The current client side library version, usually matching the current java library version. (ie 4.1, etc..) |
| version:"4.1.2", |
| scriptInFlight:false, // whether or not javascript is currently being eval'd, default false |
| ScriptFragment:new RegExp('(?:<script.*?>)((\n|.|\r)*?)(?:<\/script>)', 'im'), // regexp for script elements |
| GlobalScriptFragment:new RegExp('(?:<script.*?>)((\n|.|\r)*?)(?:<\/script>)', 'img'), // regexp for global script fragments |
| requestsInFlight:0, // how many ajax requests are currently in progress |
| isIE:dojo.render.html.ie, |
| // property: requestEncoding |
| // Defines the encoding that will be used in all Tapestry initiated XHR requests to encode |
| // URL or form data. Gets set by AjaxShellDelegate class on server on most requests by default. |
| requestEncoding:"UTF-8", |
| |
| /** |
| * Function: bind |
| * |
| * Core XHR bind function for tapestry internals. The |
| * <error>/<load> functions defined in this package are used to handle |
| * load/error of dojo.io.bind. |
| * |
| * Parameters: |
| * |
| * url - The url to bind the request to. |
| * content - A properties map of optional extra content to send. |
| * json - Boolean, optional parameter specifying whether or not to create a |
| * json request. If not specified the default is to use XHR. |
| */ |
| bind:function(url, content, json){ |
| var parms = { |
| url:url, |
| content:content, |
| useCache:true, |
| preventCache:true, |
| encoding: tapestry.requestEncoding, |
| error: (function(){tapestry.error.apply(this, arguments);}) |
| }; |
| |
| // setup content type |
| if (typeof json != "undefined" && json) { |
| parms.mimetype = "text/json"; |
| parms.headers={"json":true}; |
| parms.load=(function(){tapestry.loadJson.apply(this, arguments);}); |
| } else { |
| parms.headers={"dojo-ajax-request":true}; |
| parms.mimetype="text/xml"; |
| parms.load=(function(){tapestry.load.apply(this, arguments);}); |
| } |
| |
| tapestry.requestsInFlight++; |
| dojo.io.queueBind(parms); |
| }, |
| |
| /** |
| * Function: error |
| * |
| * Global error handling function for dojo.io.bind requests. This function is mapped |
| * as the "error:functionName" part of a request in the dojo.io.bind arguments |
| * in <tapestry.bind> calls. |
| * |
| * See Also: |
| * <tapestry.bind>, <tapestry.load> |
| */ |
| error:function(type, exception, http, kwArgs){ |
| tapestry.requestsInFlight--; |
| dojo.log.exception("Error received in IO response.", exception); |
| }, |
| |
| /** |
| * Function: load |
| * |
| * Global load handling function for dojo.io.bind requests. This isn't typically |
| * called directly by anything, but passed in as the "load" argument to |
| * dojo.io.bind when making IO requests as the function that will handle the |
| * return response. |
| * |
| * Parameters: |
| * type - Type of request. |
| * data - The data returned, depending on the request type might be an xml document / |
| * plaintext / json / etc. |
| * http - The http object used in request, like XmlHttpRequest. |
| * kwArgs - The original set of arguments passed into dojo.io.bind({arg:val,arg1:val2}). |
| * |
| */ |
| load:function(type, data, http, kwArgs){ |
| dojo.log.debug("tapestry.load() Response received.", data); |
| tapestry.requestsInFlight--; |
| if (!data) { |
| dojo.log.warn("No data received in response."); |
| return; |
| } |
| |
| var resp=data.getElementsByTagName("ajax-response"); |
| if (!resp || resp.length < 1 || !resp[0].childNodes) { |
| dojo.log.warn("No ajax-response elements received."); |
| return; |
| } |
| |
| var elms=resp[0].childNodes; |
| var bodyScripts=[]; |
| var initScripts=[]; |
| var rawData=[]; |
| for (var i=0; i<elms.length; i++) { |
| var elmType=elms[i].getAttribute("type"); |
| var id=elms[i].getAttribute("id"); |
| |
| if (elmType == "exception") { |
| dojo.log.err("Remote server exception received."); |
| tapestry.presentException(elms[i], kwArgs); |
| return; |
| } else if (elmType == "page") { |
| window.location=elms[i].getAttribute("url"); |
| return; |
| } else if (elmType == "status") { |
| dojo.event.topic.publish(id, {message: tapestry.html.getContentAsString(elms[i])}); |
| continue; |
| } |
| |
| // handle javascript evaluations |
| if (elmType == "script") { |
| |
| if (id == "initializationscript") { |
| initScripts.push(elms[i]); |
| continue; |
| } else if (id == "bodyscript") { |
| bodyScripts.push(elms[i]); |
| continue; |
| } else if (id == "includescript") { |
| // includes get processed immediately (synchronously) |
| var includes=elms[i].getElementsByTagName("include"); |
| if (!includes){continue;} |
| for (var e=0; e<includes.length;e++) { |
| tapestry.loadScriptFromUrl(includes[e].getAttribute("url")); |
| } |
| continue; |
| } |
| } else { |
| rawData.push(elms[i]); |
| } |
| |
| if (!id){ |
| dojo.log.warn("No element id found in ajax-response node."); |
| continue; |
| } |
| |
| var node=dojo.byId(id); |
| if (!node) { |
| dojo.log.warn("No node could be found to update content in with id " + id); |
| continue; |
| } |
| |
| tapestry.loadContent(id, node, elms[i]); |
| } |
| |
| // load body scripts before initialization |
| for (var i=0; i<bodyScripts.length; i++) { |
| tapestry.loadScriptContent(bodyScripts[i], true); |
| } |
| |
| for (var i=0; i<rawData.length; i++) { |
| tapestry.loadScriptContent(rawData[i], true); |
| } |
| |
| for (var i=0; i<initScripts.length; i++) { |
| tapestry.loadScriptContent(initScripts[i], true); |
| } |
| }, |
| |
| /** |
| * Function: loadJson |
| * |
| * Executed by default during JSON requests - default implementation does nothing but decrement |
| * the <tapestry.requestsInFlight> global variable. |
| * |
| * Parameters: |
| * type - Type of request. |
| * data - The data returned, depending on the request type might be an xml document / |
| * plaintext / json / etc. |
| * http - The http object used in request, like XmlHttpRequest. |
| * kwArgs - The original set of arguments passed into dojo.io.bind({arg:val,arg1:val2}). |
| */ |
| loadJson:function(type, data, http, kwArgs) { |
| dojo.log.debug("tapestry.loadJson() Response received.", data); |
| tapestry.requestsInFlight--; |
| }, |
| |
| /** |
| * Function: loadContent |
| * |
| * Used by <tapestry.load> when handling xml responses to iterate over the tapestry |
| * specific xml response and appropriately load all content types / perform animations / |
| * execute scripts in the proper order / etc.. |
| * |
| * Parameters: |
| * id - The element id that this content should be applied to in the existing document. |
| * node - The node that this new content will be applied to. |
| * element - The incoming xml node containing rules/content to apply to this node. |
| * |
| */ |
| loadContent:function(id, node, element){ |
| if (typeof element.childNodes != "undefined" && element.childNodes.length > 0) { |
| for (var i = 0; i < element.childNodes.length; i++) { |
| if (element.childNodes[i].nodeType != 1) { continue; } |
| |
| var nodeId = element.childNodes[i].getAttribute("id"); |
| if (nodeId) { |
| element=element.childNodes[i]; |
| break; |
| } |
| } |
| } |
| |
| dojo.event.browser.clean(node); // prevent mem leaks in ie |
| |
| var content=tapestry.html.getContentAsString(element); |
| if (djConfig["isDebug"]) { |
| dojo.log.debug("Received element content for id <" + id + "> of: " + content); |
| } |
| |
| // fix for IE - setting innerHTML does not work for SELECTs |
| if (tapestry.isIE && node.outerHTML && node.nodeName == "SELECT") { |
| node.outerHTML = node.outerHTML.replace(/(<SELECT[^<]*>).*(<\/SELECT>)/, '$1' + content + '$2'); |
| node=dojo.byId(id); |
| } else { |
| if (content && content.length > 0) { |
| node.innerHTML=content; |
| } |
| } |
| |
| // copy attributes |
| var atts=element.attributes; |
| var attnode, i=0; |
| while((attnode=atts[i++])){ |
| if(tapestry.isIE){ |
| if(!attnode){ continue; } |
| if((typeof attnode == "object")&& |
| (typeof attnode.nodeValue == 'undefined')|| |
| (attnode.nodeValue == null)|| |
| (attnode.nodeValue == '')){ |
| continue; |
| } |
| } |
| |
| var nn = attnode.nodeName; |
| var nv = attnode.nodeValue; |
| if (nn == "id" || nn == "type" || nn == "name"){continue;} |
| |
| if (nn == "style") { |
| dojo.html.setStyleText(node, nv); |
| } else if (nn == "class") { |
| dojo.html.setClass(node, nv); |
| } else { |
| node.setAttribute(nn, nv); |
| } |
| } |
| |
| // apply disabled/not disabled |
| var disabled = element.getAttribute("disabled"); |
| if (!disabled && node["disabled"]) { |
| node.disabled = false; |
| } else if (disabled) { |
| node.disabled = true; |
| } |
| }, |
| |
| /** |
| * Function: loadScriptContent |
| * |
| * Manages loading javascript content for a specific incoming xml element. |
| * |
| * Parameters: |
| * element - The element to parse javascript statements from and execute. |
| * async - Whether or not to process the script content asynchronously, meaning |
| * whether or not to execute the script in a block done in a setTimeout call |
| * so as to avoid IE specific issues. |
| */ |
| loadScriptContent:function(element, async){ |
| if (typeof async == "undefined") { async = true; } |
| async = this.isIE; |
| |
| if (tapestry.scriptInFlight) { |
| dojo.log.debug("loadScriptContent(): scriptInFlight is true, sleeping"); |
| setTimeout(function() { tapestry.loadScriptContent(element, async);}, 5); |
| return; |
| } |
| |
| var text=tapestry.html.getContentAsString(element); |
| text.replace(this.GlobalScriptFragment, ''); |
| var scripts = text.match(this.GlobalScriptFragment); |
| |
| if (!scripts) { return; } |
| |
| if (async) { |
| setTimeout(function() { |
| tapestry.evaluateScripts(scripts); |
| }, 60); |
| } else { |
| tapestry.evaluateScripts(scripts); |
| } |
| }, |
| |
| evaluateScripts:function(scripts){ |
| tapestry.scriptInFlight = true; |
| |
| for (var i=0; i<scripts.length; i++) { |
| var scr = scripts[i].match(this.ScriptFragment)[1]; |
| if(!scr || scr.length <= 0){continue;} |
| try { |
| dojo.log.debug("evaluating script:", scr); |
| eval(scr); |
| } catch (e) { |
| tapestry.scriptInFlight = false; |
| dojo.log.exception("Error evaluating script: " + scr, e, false); |
| } |
| } |
| |
| tapestry.scriptInFlight = false; |
| }, |
| |
| /** |
| * Function: loadScriptFromUrl |
| * |
| * Takes a url string and loads the javascript it points to as a normal |
| * document head script include section. ie: |
| * |
| * : <script type="text/javascript" src="http://localhost/js/foo.js"></script> |
| * |
| * Parameters: |
| * url - The url to the script to load into this documents head. |
| */ |
| loadScriptFromUrl:function(url){ |
| var scripts = window.document.getElementsByTagName("script"); |
| if (scripts){ |
| for (var i = 0; i < scripts.length; i++) { |
| var src = scripts[i].src; |
| if (src && src.length > 0 && src.indexOf(url)>=0 ) { |
| return; |
| } |
| } |
| } |
| |
| if (djConfig.isDebug) { |
| dojo.log.debug("loadScriptFromUrl: " + url + " success?: " + dojo.hostenv.loadUri(url)); |
| } else { |
| dojo.hostenv.loadUri(url); |
| } |
| }, |
| |
| /** |
| * Function: presentException |
| * |
| * When remote exceptions are caught on the server special xml blocks are returned to |
| * the client when the requests are initiated via async IO. This function takes the incoming |
| * Tapestry exception page content and dumps it into a modal dialog that is presented to the user. |
| * |
| * Parameters: |
| * node - The incoming xml exception node. |
| * kwArgs - The kwArgs used to initiate the original IO request. |
| */ |
| presentException:function(node, kwArgs) { |
| dojo.require("dojo.widget.*"); |
| dojo.require("dojo.widget.Dialog"); |
| |
| var excnode=document.createElement("div"); |
| excnode.setAttribute("id", "exceptiondialog"); |
| document.body.appendChild(excnode); |
| |
| var contentnode=document.createElement("div"); |
| contentnode.innerHTML=tapestry.html.getContentAsString(node); |
| dojo.html.setClass(contentnode, "exceptionDialog"); |
| |
| var navnode=document.createElement("div"); |
| navnode.setAttribute("id", "exceptionDialogHandle"); |
| dojo.html.setClass(navnode, "exceptionCloseLink"); |
| navnode.appendChild(document.createTextNode("Close")); |
| |
| excnode.appendChild(navnode); |
| excnode.appendChild(contentnode); |
| |
| var dialog=dojo.widget.createWidget("Dialog", {widgetId:"exception"}, excnode); |
| dojo.event.connect(navnode, "onclick", dialog, "hide"); |
| dojo.event.connect(dialog, "hide", dialog, "destroy"); |
| |
| setTimeout(function(){ |
| dialog.show(); |
| }, 100); |
| }, |
| |
| /** |
| * Function: cleanConnect |
| * |
| * Utility used to disconnect a previously connected event/function. |
| * |
| * This assumes that the incoming function name is being attached to |
| * the global namespace "tapestry". |
| */ |
| cleanConnect:function(target, event, funcName){ |
| if (!dj_undef(funcName, tapestry)){ |
| dojo.event.disconnect(target, event, tapestry, funcName); |
| } |
| }, |
| |
| linkOnClick:function(url, id, isJson){ |
| var content={beventname:"onClick"}; |
| content["beventtarget.id"]=id; |
| |
| tapestry.bind(url, content, isJson); |
| return false; |
| }, |
| |
| /** |
| * Function: isServingRequests |
| * |
| * Utility used to find out if there are any ajax requests in progress. |
| */ |
| isServingRequests:function(){ |
| return (tapestry.requestsInFlight > 0); |
| } |
| } |
| |
| /** |
| * package: tapestry.html |
| * Provides functionality related to parsing and rendering dom nodes. |
| */ |
| tapestry.html={ |
| |
| CompactElementRegexp:/<([a-zA-Z](?!nput)[a-zA-Z]*)([^>]*?)\/>/g, // regexp for compact html elements |
| CompactElementReplacer:'<$1$2></$1>', // replace pattern for compact html elements |
| |
| /** |
| * Function: getContentAsString |
| * |
| * Takes a dom node and returns its contents rendered in a string. |
| * |
| * The resulting string does NOT contain any markup (or attributes) of |
| * the given node - only child nodes are rendered and returned.Content |
| * |
| * Implementation Note: This function tries to make use of browser |
| * specific features (the xml attribute of nodes in IE and the XMLSerializer |
| * object in Mozilla derivatives) - if those fails, a generic implementation |
| * is used that is guaranteed to work in all platforms. |
| * |
| * Parameters: |
| * |
| * node - The dom node. |
| * Returns: |
| * |
| * The string representation of the given node's contents. |
| */ |
| getContentAsString:function(node){ |
| if (typeof node.xml != "undefined") { |
| return this._getContentAsStringIE(node); |
| } else if (typeof XMLSerializer != "undefined" ) { |
| return this._getContentAsStringMozilla(node); |
| } else { |
| return this._getContentAsStringGeneric(node); |
| } |
| }, |
| |
| /** |
| * Function: getElementAsString |
| * |
| * Takes a dom node and returns itself and its contents rendered in a string. |
| * |
| * Implementation Note: This function uses a generic implementation in order |
| * to generate the returned string. |
| * |
| * Parameters: |
| * |
| * node - The dom node. |
| * Returns: |
| * |
| * The string representation of the given node. |
| */ |
| getElementAsString:function(node){ |
| if (!node) { return ""; } |
| |
| var s='<' + node.nodeName; |
| // add attributes |
| if (node.attributes && node.attributes.length > 0) { |
| for (var i=0; i < node.attributes.length; i++) { |
| s += " " + node.attributes[i].name + "=\"" + node.attributes[i].value + "\""; |
| } |
| } |
| // close start tag |
| s += '>'; |
| // content of tag |
| s += this._getContentAsStringGeneric(node); |
| // end tag |
| s += '</' + node.nodeName + '>'; |
| return s; |
| }, |
| |
| _getContentAsStringIE:function(node){ |
| var s=" "; //blank works around an IE-bug |
| for (var i = 0; i < node.childNodes.length; i++){ |
| s += node.childNodes[i].xml; |
| } |
| return s; |
| }, |
| |
| _getContentAsStringMozilla:function(node){ |
| if (!this.xmlSerializer){ this.xmlSerializer = new XMLSerializer();} |
| |
| var s = ""; |
| for (var i = 0; i < node.childNodes.length; i++) { |
| s += this.xmlSerializer.serializeToString(node.childNodes[i]); |
| if (s == "undefined") |
| return this._getContentAsStringGeneric(node); |
| } |
| |
| return this._processCompactElements(s); |
| }, |
| |
| _getContentAsStringGeneric:function(node){ |
| var s=""; |
| if (node == null) { return s; } |
| for (var i = 0; i < node.childNodes.length; i++) { |
| switch (node.childNodes[i].nodeType) { |
| case 1: // ELEMENT_NODE |
| case 5: // ENTITY_REFERENCE_NODE |
| s += this.getElementAsString(node.childNodes[i]); |
| break; |
| case 3: // TEXT_NODE |
| case 2: // ATTRIBUTE_NODE |
| case 4: // CDATA_SECTION_NODE |
| s += node.childNodes[i].nodeValue; |
| break; |
| default: |
| break; |
| } |
| } |
| return s; |
| }, |
| |
| _processCompactElements:function(htmlData) |
| { |
| return htmlData.replace(this.CompactElementRegexp, this.CompactElementReplacer); |
| } |
| } |
| |
| /** |
| * package: tapestry.event |
| * |
| * Utility functions that handle converting javascript event objects into |
| * a name/value pair format that can be sent to the remote server. |
| */ |
| tapestry.event={ |
| |
| /** |
| * Function: buildEventProperties |
| * |
| * Takes an incoming browser generated event (like key/mouse events) and |
| * creates a js object holding the basic values of the event in order for |
| * it to be submitted to the server. |
| * |
| * Parameters: |
| * |
| * event - The javascript event method is based on, if it isn't a valid |
| * browser event it will be ignored. |
| * props - The existing property object to set the values on, if it doesn't |
| * exist one will be created. |
| * args - The arguments from an method-call interception |
| * Returns: |
| * |
| * The desired event properties bound to an object. Ie obj.target,obj.charCode, etc.. |
| */ |
| buildEventProperties:function(event, props, args){ |
| if (!props) props={}; |
| |
| if (dojo.event.browser.isEvent(event)) { |
| if(event["type"]) props.beventtype=event.type; |
| if(event["keys"]) props.beventkeys=event.keys; |
| if(event["charCode"]) props.beventcharCode=event.charCode; |
| if(event["pageX"]) props.beventpageX=event.pageX; |
| if(event["pageY"]) props.beventpageY=event.pageY; |
| if(event["layerX"]) props.beventlayerX=event.layerX; |
| if(event["layerY"]) props.beventlayerY=event.layerY; |
| |
| if (event["target"]) this.buildTargetProperties(props, event.target); |
| } |
| |
| props.methodArguments = dojo.json.serialize( args ); |
| |
| return props; |
| }, |
| |
| |
| |
| /** |
| * Function: buildTargetProperties |
| * |
| * Generic function to build a properties object populated with |
| * relevent target data. |
| * |
| * Parameters: |
| * |
| * props - The object that event properties are being set on to return to |
| * the server. |
| * target - The javscript Event.target object that the original event was targeted for. |
| * |
| * Returns: |
| * The original props object passed in, populated with any data found. |
| */ |
| buildTargetProperties:function(props, target){ |
| if(!target) { return; } |
| |
| if (dojo.dom.isNode(target)) { |
| return this.buildNodeProperties(props, target); |
| } else { |
| dojo.raise("buildTargetProperties() Unknown target type:" + target); |
| } |
| }, |
| |
| /** |
| * Function: buildNodeProperties |
| * |
| * Builds needed target node properties, like the node's id. |
| * |
| * Parameters: |
| * props - The object that event properties are being set on to return to |
| * the server. |
| * node - The dom node specified as the Event.target in a javascript event. |
| */ |
| buildNodeProperties:function(props, node) { |
| if (node.getAttribute("id")) { |
| props["beventtarget.id"]=node.getAttribute("id"); |
| } |
| } |
| } |
| |
| tapestry.lang = { |
| |
| /** |
| * Searches the specified list for an object with a matching propertyName/value pair. |
| * @param list The array of objects to search. |
| * @param properyName The object property key to match on. (ie object[propertyName]) |
| * Can also be a template object to match in the form of {key:{key:value}} nested |
| * as deeply as you like. |
| * @param value The value to be matched against |
| * @return The matching array object found, or null. |
| */ |
| find:function(list, property, value){ |
| if (!list || !property || list.length < 1) return null; |
| |
| // if not propMatch then template object was passed in |
| var propMatch=dojo.lang.isString(property); |
| if (propMatch && !value) return null; //if doing string/other non template match and no value |
| |
| for (var i=0; i < list.length; i++) { |
| if (!list[i]) continue; |
| if (propMatch) { |
| if (list[i] && list[i][property] && list[i][property] == value) return list[i]; |
| } else { |
| if (this.matchProperty(property, list[i])) return list[i]; |
| } |
| } |
| return null; |
| }, |
| |
| // called recursively to match object properties |
| // partially stolen logic from dojo.widget.html.SortableTable.sort |
| matchProperty:function(template, object){ |
| if(!dojo.lang.isObject(template) || !dojo.lang.isObject(object)) |
| return template.valueOf() == object.valueOf(); |
| |
| for(var p in template){ |
| if(!(p in object)) return false; // boolean |
| if (!this.matchProperty(template[p], object[p])) return false; |
| } |
| return true; |
| } |
| } |
| |
| dojo.AdapterRegistry = function (returnWrappers) { |
| this.pairs = []; |
| this.returnWrappers = returnWrappers || false; |
| }; |
| dojo.lang.extend(dojo.AdapterRegistry, {register:function (name, check, wrap, directReturn, override) { |
| var type = (override) ? "unshift" : "push"; |
| this.pairs[type]([name, check, wrap, directReturn]); |
| }, match:function () { |
| for (var i = 0; i < this.pairs.length; i++) { |
| var pair = this.pairs[i]; |
| if (pair[1].apply(this, arguments)) { |
| if ((pair[3]) || (this.returnWrappers)) { |
| return pair[2]; |
| } else { |
| return pair[2].apply(this, arguments); |
| } |
| } |
| } |
| throw new Error("No match found"); |
| }, unregister:function (name) { |
| for (var i = 0; i < this.pairs.length; i++) { |
| var pair = this.pairs[i]; |
| if (pair[0] == name) { |
| this.pairs.splice(i, 1); |
| return true; |
| } |
| } |
| return false; |
| }}); |
| |
| |
| dojo.json = { |
| jsonRegistry:new dojo.AdapterRegistry(), |
| register:function (name, check, wrap, override) { |
| dojo.json.jsonRegistry.register(name, check, wrap, override); |
| }, |
| |
| evalJson:function (json) { |
| try { |
| return eval("(" + json + ")"); |
| } |
| catch (e) { |
| dojo.debug(e); |
| return json; |
| } |
| }, |
| |
| serialize:function (o) { |
| var objtype = typeof (o); |
| if (objtype == "undefined") { |
| return "undefined"; |
| } else { |
| if ((objtype == "number") || (objtype == "boolean")) { |
| return o + ""; |
| } else { |
| if (o === null) { |
| return "null"; |
| } |
| } |
| } |
| if (objtype == "string") { |
| return dojo.string.escapeString(o); |
| } |
| var me = arguments.callee; |
| var newObj; |
| if (typeof (o.__json__) == "function") { |
| newObj = o.__json__(); |
| if (o !== newObj) { |
| return me(newObj); |
| } |
| } |
| |
| if (typeof (o.json) == "function") { |
| newObj = o.json(); |
| if (o !== newObj) { |
| return me(newObj); |
| } |
| } |
| |
| if (objtype != "function" && typeof (o.length) == "number") { |
| var res = []; |
| for (var i = 0; i < o.length; i++) { |
| if (dojo.event.browser.isEvent(o[i]) || o[i]["stopPropagation"]){continue;} |
| var val = me(o[i]); |
| if (typeof (val) != "string") { |
| val = "undefined"; |
| } |
| res.push(val); |
| } |
| return "[" + res.join(",") + "]"; |
| } |
| try { |
| window.o = o; |
| newObj = dojo.json.jsonRegistry.match(o); |
| return me(newObj); |
| } |
| catch (e) { |
| } |
| if (objtype == "function") { |
| return null; |
| } |
| |
| res = []; |
| for (var k in o) { |
| var useKey; |
| if (typeof (k) == "number") { |
| useKey = "\"" + k + "\""; |
| } else { |
| if (typeof (k) == "string") { |
| useKey = dojo.string.escapeString(k); |
| } else { |
| continue; |
| } |
| } |
| val = me(o[k]); |
| if (typeof (val) != "string") { |
| continue; |
| } |
| res.push(useKey + ":" + val); |
| } |
| return "{" + res.join(",") + "}"; |
| }}; |