Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/__package__.js
------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/__package__.js ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/__package__.js ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cometd.js URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cometd.js?view=auto&rev=509273 ============================================================================== --- ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cometd.js (added) +++ ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cometd.js Mon Feb 19 09:56:06 2007 @@ -0,0 +1,929 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.require("dojo.io.common"); // io/common.js provides setIFrameSrc and the IO module +dojo.provide("dojo.io.cometd"); +dojo.require("dojo.AdapterRegistry"); +dojo.require("dojo.json"); +dojo.require("dojo.io.BrowserIO"); // we need XHR for the handshake, etc. +// FIXME: determine if we can use XMLHTTP to make x-domain posts despite not +// being able to hear back about the result +dojo.require("dojo.io.IframeIO"); +dojo.require("dojo.io.ScriptSrcIO"); // for x-domain long polling +dojo.require("dojo.io.cookie"); // for peering +dojo.require("dojo.event.*"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.lang.func"); + +/* + * this file defines Comet protocol client. Actual message transport is + * deferred to one of several connection type implementations. The default is a + * forever-frame implementation. A single global object named "cometd" is + * used to mediate for these connection types in order to provide a stable + * interface. + */ + +// TODO: the auth handling in this file is a *mess*. It should probably live in +// the cometd object with the ability to mix in or call down to an auth-handler +// object, the prototypical variant of which is a no-op + +cometd = new function(){ + + this.initialized = false; + this.connected = false; + + this.connectionTypes = new dojo.AdapterRegistry(true); + + this.version = 0.1; + this.minimumVersion = 0.1; + this.clientId = null; + + this._isXD = false; + this.handshakeReturn = null; + this.currentTransport = null; + this.url = null; + this.lastMessage = null; + this.globalTopicChannels = {}; + this.backlog = []; + + this.tunnelInit = function(childLocation, childDomain){ + // placeholder + } + + this.tunnelCollapse = function(){ + dojo.debug("tunnel collapsed!"); + // placeholder + } + + this.init = function(props, root, bargs){ + // FIXME: if the root isn't from the same host, we should automatically + // try to select an XD-capable transport + props = props||{}; + // go ask the short bus server what we can support + props.version = this.version; + props.minimumVersion = this.minimumVersion; + props.channel = "/meta/handshake"; + // FIXME: do we just assume that the props knows + // everything we care about WRT to auth? Should we be trying to + // call back into it for subsequent auth actions? Should we fire + // local auth functions to ask for/get auth data? + + // FIXME: what about ScriptSrcIO for x-domain comet? + this.url = root||djConfig["cometdRoot"]; + if(!this.url){ + dojo.debug("no cometd root specified in djConfig and no root passed"); + return; + } + + // FIXME: we need to select a way to handle JSONP-style stuff + // generically here. We already know if the server is gonna be on + // another domain (or can know it), so we should select appropriate + // negotiation methods here as well as in final transport type + // selection. + var bindArgs = { + url: this.url, + method: "POST", + mimetype: "text/json", + load: dojo.lang.hitch(this, "finishInit"), + content: { "message": dojo.json.serialize([props]) } + }; + + // borrowed from dojo.uri.Uri in lieu of fixed host and port properties + var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"; + var r = (""+window.location).match(new RegExp(regexp)); + if(r[4]){ + var tmp = r[4].split(":"); + var thisHost = tmp[0]; + var thisPort = tmp[1]||"80"; // FIXME: match 443 + + r = this.url.match(new RegExp(regexp)); + if(r[4]){ + tmp = r[4].split(":"); + var urlHost = tmp[0]; + var urlPort = tmp[1]||"80"; + if( (urlHost != thisHost)|| + (urlPort != thisPort) ){ + dojo.debug(thisHost, urlHost); + dojo.debug(thisPort, urlPort); + + this._isXD = true; + bindArgs.transport = "ScriptSrcTransport"; + bindArgs.jsonParamName = "jsonp"; + bindArgs.method = "GET"; + } + } + } + if(bargs){ + dojo.lang.mixin(bindArgs, bargs); + } + return dojo.io.bind(bindArgs); + } + + this.finishInit = function(type, data, evt, request){ + data = data[0]; + this.handshakeReturn = data; + // pick a transport + if(data["authSuccessful"] == false){ + dojo.debug("cometd authentication failed"); + return; + } + if(data.version < this.minimumVersion){ + dojo.debug("cometd protocol version mismatch. We wanted", this.minimumVersion, "but got", data.version); + return; + } + this.currentTransport = this.connectionTypes.match( + data.supportedConnectionTypes, + data.version, + this._isXD + ); + this.currentTransport.version = data.version; + this.clientId = data.clientId; + this.tunnelInit = dojo.lang.hitch(this.currentTransport, "tunnelInit"); + this.tunnelCollapse = dojo.lang.hitch(this.currentTransport, "tunnelCollapse"); + this.initialized = true; + this.currentTransport.startup(data); + while(this.backlog.length != 0){ + var cur = this.backlog.shift(); + var fn = cur.shift(); + this[fn].apply(this, cur); + } + } + + this._getRandStr = function(){ + return Math.random().toString().substring(2, 10); + } + + // public API functions called by cometd or by the transport classes + this.deliver = function(messages){ + dojo.lang.forEach(messages, this._deliver, this); + } + + this._deliver = function(message){ + // dipatch events along the specified path + if(!message["channel"]){ + dojo.debug("cometd error: no channel for message!"); + return; + } + if(!this.currentTransport){ + this.backlog.push(["deliver", message]); + return; + } + this.lastMessage = message; + // check to see if we got a /meta channel message that we care about + if( (message.channel.length > 5)&& + (message.channel.substr(0, 5) == "/meta")){ + // check for various meta topic actions that we need to respond to + switch(message.channel){ + case "/meta/subscribe": + if(!message.successful){ + dojo.debug("cometd subscription error for channel", message.channel, ":", message.error); + return; + } + this.subscribed(message.subscription, message); + break; + case "/meta/unsubscribe": + if(!message.successful){ + dojo.debug("cometd unsubscription error for channel", message.channel, ":", message.error); + return; + } + this.unsubscribed(message.subscription, message); + break; + } + } + // send the message down for processing by the transport + this.currentTransport.deliver(message); + + // dispatch the message to any locally subscribed listeners + var tname = (this.globalTopicChannels[message.channel]) ? message.channel : "/cometd"+message.channel; + dojo.event.topic.publish(tname, message); + } + + this.disconnect = function(){ + if(!this.currentTransport){ + dojo.debug("no current transport to disconnect from"); + return; + } + this.currentTransport.disconnect(); + } + + // public API functions called by end users + this.publish = function(/*string*/channel, /*object*/data, /*object*/properties){ + // summary: + // publishes the passed message to the cometd server for delivery + // on the specified topic + // channel: + // the destination channel for the message + // data: + // a JSON object containing the message "payload" + // properties: + // Optional. Other meta-data to be mixed into the top-level of the + // message + if(!this.currentTransport){ + this.backlog.push(["publish", channel, data, properties]); + return; + } + var message = { + data: data, + channel: channel + }; + if(properties){ + dojo.lang.mixin(message, properties); + } + return this.currentTransport.sendMessage(message); + } + + this.subscribe = function( /*string*/ channel, + /*boolean, optional*/ useLocalTopics, + /*object, optional*/ objOrFunc, + /*string, optional*/ funcName){ // return: boolean + // summary: + // inform the server of this client's interest in channel + // channel: + // name of the cometd channel to subscribe to + // useLocalTopics: + // Determines if up a local event topic subscription to the passed + // function using the channel name that was passed is constructed, + // or if the topic name will be prefixed with some other + // identifier for local message distribution. Setting this to + // "true" is a good way to hook up server-sent message delivery to + // pre-existing local topics. + // objOrFunc: + // an object scope for funcName or the name or reference to a + // function to be called when messages are delivered to the + // channel + // funcName: + // the second half of the objOrFunc/funcName pair for identifying + // a callback function to notifiy upon channel message delivery + if(!this.currentTransport){ + this.backlog.push(["subscribe", channel, useLocalTopics, objOrFunc, funcName]); + return; + } + if(objOrFunc){ + var tname = (useLocalTopics) ? channel : "/cometd"+channel; + if(useLocalTopics){ + this.globalTopicChannels[channel] = true; + } + dojo.event.topic.subscribe(tname, objOrFunc, funcName); + } + // FIXME: would we handle queuing of the subscription if not connected? + // Or should the transport object? + return this.currentTransport.sendMessage({ + channel: "/meta/subscribe", + subscription: channel + }); + } + + this.subscribed = function( /*string*/ channel, + /*obj*/ message){ + dojo.debug(channel); + dojo.debugShallow(message); + } + + this.unsubscribe = function(/*string*/ channel, + /*boolean, optional*/ useLocalTopics, + /*object, optional*/ objOrFunc, + /*string, optional*/ funcName){ // return: boolean + // summary: + // inform the server of this client's disinterest in channel + // channel: + // name of the cometd channel to subscribe to + // useLocalTopics: + // Determines if up a local event topic subscription to the passed + // function using the channel name that was passed is destroyed, + // or if the topic name will be prefixed with some other + // identifier for stopping message distribution. + // objOrFunc: + // an object scope for funcName or the name or reference to a + // function to be called when messages are delivered to the + // channel + // funcName: + // the second half of the objOrFunc/funcName pair for identifying + if(!this.currentTransport){ + this.backlog.push(["unsubscribe", channel, useLocalTopics, objOrFunc, funcName]); + return; + } + // a callback function to notifiy upon channel message delivery + if(objOrFunc){ + // FIXME: should actual local topic unsubscription be delayed for + // successful unsubcribe notices from the other end? (guessing "no") + // FIXME: if useLocalTopics is false, should we go ahead and + // destroy the local topic? + var tname = (useLocalTopics) ? channel : "/cometd"+channel; + dojo.event.topic.unsubscribe(tname, objOrFunc, funcName); + } + return this.currentTransport.sendMessage({ + channel: "/meta/unsubscribe", + subscription: channel + }); + } + + this.unsubscribed = function(/*string*/ channel, + /*obj*/ message){ + dojo.debug(channel); + dojo.debugShallow(message); + } + + // FIXME: add an "addPublisher" function + +} + +/* +transport objects MUST expose the following methods: + - check + - startup + - sendMessage + - deliver + - disconnect +optional, standard but transport dependent methods are: + - tunnelCollapse + - tunnelInit + +Transports SHOULD be namespaced under the cometd object and transports MUST +register themselves with cometd.connectionTypes + +here's a stub transport defintion: + +cometd.blahTransport = new function(){ + this.connected = false; + this.connectionId = null; + this.authToken = null; + this.lastTimestamp = null; + this.lastId = null; + + this.check = function(types, version, xdomain){ + // summary: + // determines whether or not this transport is suitable given a + // list of transport types that the server supports + return dojo.lang.inArray(types, "blah"); + } + + this.startup = function(){ + if(this.connected){ return; } + // FIXME: fill in startup routine here + this.connected = true; + } + + this.sendMessage = function(message){ + // FIXME: fill in message sending logic + } + + this.deliver = function(message){ + if(message["timestamp"]){ + this.lastTimestamp = message.timestamp; + } + if(message["id"]){ + this.lastId = message.id; + } + if( (message.channel.length > 5)&& + (message.channel.substr(0, 5) == "/meta")){ + // check for various meta topic actions that we need to respond to + // switch(message.channel){ + // case "/meta/connect": + // // FIXME: fill in logic here + // break; + // // case ...: ... + // } + } + } + + this.disconnect = function(){ + if(!this.connected){ return; } + // FIXME: fill in shutdown routine here + this.connected = false; + } +} +cometd.connectionTypes.register("blah", cometd.blahTransport.check, cometd.blahTransport); +*/ + +cometd.iframeTransport = new function(){ + this.connected = false; + this.connectionId = null; + + this.rcvNode = null; + this.rcvNodeName = ""; + this.phonyForm = null; + this.authToken = null; + this.lastTimestamp = null; + this.lastId = null; + this.backlog = []; + + this.check = function(types, version, xdomain){ + return ((!xdomain)&& + (!dojo.render.html.safari)&& + (dojo.lang.inArray(types, "iframe"))); + } + + this.tunnelInit = function(){ + // we've gotten our initialization document back in the iframe, so + // now open up a connection and start passing data! + this.postToIframe({ + message: dojo.json.serialize([ + { + channel: "/meta/connect", + clientId: cometd.clientId, + connectionType: "iframe" + // FIXME: auth not passed here! + // "authToken": this.authToken + } + ]) + }); + } + + this.tunnelCollapse = function(){ + if(this.connected){ + // try to restart the tunnel + this.connected = false; + + this.postToIframe({ + message: dojo.json.serialize([ + { + channel: "/meta/reconnect", + clientId: cometd.clientId, + connectionId: this.connectionId, + timestamp: this.lastTimestamp, + id: this.lastId + // FIXME: no authToken provision! + } + ]) + }); + } + } + + this.deliver = function(message){ + // handle delivery details that this transport particularly cares + // about. Most functions of should be handled by the main cometd object + // with only transport-specific details and state being tracked here. + if(message["timestamp"]){ + this.lastTimestamp = message.timestamp; + } + if(message["id"]){ + this.lastId = message.id; + } + // check to see if we got a /meta channel message that we care about + if( (message.channel.length > 5)&& + (message.channel.substr(0, 5) == "/meta")){ + // check for various meta topic actions that we need to respond to + switch(message.channel){ + case "/meta/connect": + if(!message.successful){ + dojo.debug("cometd connection error:", message.error); + return; + } + this.connectionId = message.connectionId; + this.connected = true; + this.processBacklog(); + break; + case "/meta/reconnect": + if(!message.successful){ + dojo.debug("cometd reconnection error:", message.error); + return; + } + this.connected = true; + break; + case "/meta/subscribe": + if(!message.successful){ + dojo.debug("cometd subscription error for channel", message.channel, ":", message.error); + return; + } + // this.subscribed(message.channel); + dojo.debug(message.channel); + break; + } + } + } + + this.widenDomain = function(domainStr){ + // allow us to make reqests to the TLD + var cd = domainStr||document.domain; + if(cd.indexOf(".")==-1){ return; } // probably file:/// or localhost + var dps = cd.split("."); + if(dps.length<=2){ return; } // probably file:/// or an RFC 1918 address + dps = dps.slice(dps.length-2); + document.domain = dps.join("."); + return document.domain; + } + + this.postToIframe = function(content, url){ + if(!this.phonyForm){ + if(dojo.render.html.ie){ + this.phonyForm = document.createElement("<form enctype='application/x-www-form-urlencoded' method='POST' style='display: none;'>"); + dojo.body().appendChild(this.phonyForm); + }else{ + this.phonyForm = document.createElement("form"); + this.phonyForm.style.display = "none"; // FIXME: will this still work? + dojo.body().appendChild(this.phonyForm); + this.phonyForm.enctype = "application/x-www-form-urlencoded"; + this.phonyForm.method = "POST"; + } + } + + this.phonyForm.action = url||cometd.url; + this.phonyForm.target = this.rcvNodeName; + this.phonyForm.setAttribute("target", this.rcvNodeName); + + while(this.phonyForm.firstChild){ + this.phonyForm.removeChild(this.phonyForm.firstChild); + } + + for(var x in content){ + var tn; + if(dojo.render.html.ie){ + tn = document.createElement("<input type='hidden' name='"+x+"' value='"+content[x]+"'>"); + this.phonyForm.appendChild(tn); + }else{ + tn = document.createElement("input"); + this.phonyForm.appendChild(tn); + tn.type = "hidden"; + tn.name = x; + tn.value = content[x]; + } + } + this.phonyForm.submit(); + } + + this.processBacklog = function(){ + while(this.backlog.length > 0){ + this.sendMessage(this.backlog.shift(), true); + } + } + + this.sendMessage = function(message, bypassBacklog){ + // FIXME: what about auth fields? + if((bypassBacklog)||(this.connected)){ + message.connectionId = this.connectionId; + message.clientId = cometd.clientId; + var bindArgs = { + url: cometd.url||djConfig["cometdRoot"], + method: "POST", + mimetype: "text/json", + // FIXME: we should be able to do better than this given that we're sending an array! + content: { message: dojo.json.serialize([ message ]) } + }; + return dojo.io.bind(bindArgs); + }else{ + this.backlog.push(message); + } + } + + this.startup = function(handshakeData){ + dojo.debug("startup!"); + dojo.debug(dojo.json.serialize(handshakeData)); + + if(this.connected){ return; } + + // this.widenDomain(); + + // NOTE: we require the server to cooperate by hosting + // cometdInit.html at the designated endpoint + this.rcvNodeName = "cometdRcv_"+cometd._getRandStr(); + // the "forever frame" approach + + var initUrl = cometd.url+"/?tunnelInit=iframe"; // &domain="+document.domain; + if(false && dojo.render.html.ie){ // FIXME: DISALBED FOR NOW + // use the "htmlfile hack" to prevent the background click junk + this.rcvNode = new ActiveXObject("htmlfile"); + this.rcvNode.open(); + this.rcvNode.write("<html>"); + this.rcvNode.write("<script>document.domain = '"+document.domain+"'"); + this.rcvNode.write("</html>"); + this.rcvNode.close(); + + var ifrDiv = this.rcvNode.createElement("div"); + this.rcvNode.appendChild(ifrDiv); + this.rcvNode.parentWindow.dojo = dojo; + ifrDiv.innerHTML = "<iframe src='"+initUrl+"'></iframe>" + }else{ + this.rcvNode = dojo.io.createIFrame(this.rcvNodeName, "", initUrl); + // dojo.io.setIFrameSrc(this.rcvNode, initUrl); + // we're still waiting on the iframe to call back up to use and + // advertise that it's been initialized via tunnelInit + } + } +} + +cometd.mimeReplaceTransport = new function(){ + this.connected = false; + this.connectionId = null; + this.xhr = null; + + this.authToken = null; + this.lastTimestamp = null; + this.lastId = null; + this.backlog = []; + + this.check = function(types, version, xdomain){ + return ((!xdomain)&& + (dojo.render.html.mozilla)&& // seems only Moz really supports this right now = ( + (dojo.lang.inArray(types, "mime-message-block"))); + } + + this.tunnelInit = function(){ + if(this.connected){ return; } + // FIXME: open up the connection here + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/connect", + clientId: cometd.clientId, + connectionType: "mime-message-block" + // FIXME: auth not passed here! + // "authToken": this.authToken + } + ]) + }); + this.connected = true; + } + + this.tunnelCollapse = function(){ + if(this.connected){ + // try to restart the tunnel + this.connected = false; + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/reconnect", + clientId: cometd.clientId, + connectionId: this.connectionId, + timestamp: this.lastTimestamp, + id: this.lastId + // FIXME: no authToken provision! + } + ]) + }); + } + } + + this.deliver = cometd.iframeTransport.deliver; + // the logic appears to be the same + + this.handleOnLoad = function(resp){ + cometd.deliver(dojo.json.evalJson(this.xhr.responseText)); + } + + this.openTunnelWith = function(content, url){ + // set up the XHR object and register the multipart callbacks + this.xhr = dojo.hostenv.getXmlhttpObject(); + this.xhr.multipart = true; // FIXME: do Opera and Safari support this flag? + if(dojo.render.html.mozilla){ + this.xhr.addEventListener("load", dojo.lang.hitch(this, "handleOnLoad"), false); + }else if(dojo.render.html.safari){ + // Blah. WebKit doesn't actually populate responseText and/or responseXML. Useless. + dojo.debug("Webkit is broken with multipart responses over XHR = ("); + this.xhr.onreadystatechange = dojo.lang.hitch(this, "handleOnLoad"); + }else{ + this.xhr.onload = dojo.lang.hitch(this, "handleOnLoad"); + } + this.xhr.open("POST", (url||cometd.url), true); // async post + this.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + dojo.debug(dojo.json.serialize(content)); + this.xhr.send(dojo.io.argsFromMap(content, "utf8")); + } + + this.processBacklog = function(){ + while(this.backlog.length > 0){ + this.sendMessage(this.backlog.shift(), true); + } + } + + this.sendMessage = function(message, bypassBacklog){ + // FIXME: what about auth fields? + if((bypassBacklog)||(this.connected)){ + message.connectionId = this.connectionId; + message.clientId = cometd.clientId; + var bindArgs = { + url: cometd.url||djConfig["cometdRoot"], + method: "POST", + mimetype: "text/json", + content: { message: dojo.json.serialize([ message ]) } + }; + return dojo.io.bind(bindArgs); + }else{ + this.backlog.push(message); + } + } + + this.startup = function(handshakeData){ + dojo.debugShallow(handshakeData); + if(this.connected){ return; } + this.tunnelInit(); + } +} + +cometd.longPollTransport = new function(){ + this.connected = false; + this.connectionId = null; + + this.authToken = null; + this.lastTimestamp = null; + this.lastId = null; + this.backlog = []; + + this.check = function(types, version, xdomain){ + return ((!xdomain)&&(dojo.lang.inArray(types, "long-polling"))); + } + + this.tunnelInit = function(){ + if(this.connected){ return; } + // FIXME: open up the connection here + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/connect", + clientId: cometd.clientId, + connectionType: "long-polling" + // FIXME: auth not passed here! + // "authToken": this.authToken + } + ]) + }); + this.connected = true; + } + + this.tunnelCollapse = function(){ + if(!this.connected){ + // try to restart the tunnel + this.connected = false; + dojo.debug("clientId:", cometd.clientId); + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/reconnect", + connectionType: "long-polling", + clientId: cometd.clientId, + connectionId: this.connectionId, + timestamp: this.lastTimestamp, + id: this.lastId + // FIXME: no authToken provision! + } + ]) + }); + } + } + + this.deliver = cometd.iframeTransport.deliver; + // the logic appears to be the same + + this.openTunnelWith = function(content, url){ + dojo.io.bind({ + url: (url||cometd.url), + method: "post", + content: content, + mimetype: "text/json", + load: dojo.lang.hitch(this, function(type, data, evt, args){ + // dojo.debug(evt.responseText); + cometd.deliver(data); + this.connected = false; + this.tunnelCollapse(); + }), + error: function(){ dojo.debug("tunnel opening failed"); } + }); + this.connected = true; + } + + this.processBacklog = function(){ + while(this.backlog.length > 0){ + this.sendMessage(this.backlog.shift(), true); + } + } + + this.sendMessage = function(message, bypassBacklog){ + // FIXME: what about auth fields? + if((bypassBacklog)||(this.connected)){ + message.connectionId = this.connectionId; + message.clientId = cometd.clientId; + var bindArgs = { + url: cometd.url||djConfig["cometdRoot"], + method: "post", + mimetype: "text/json", + content: { message: dojo.json.serialize([ message ]) } + }; + return dojo.io.bind(bindArgs); + }else{ + this.backlog.push(message); + } + } + + this.startup = function(handshakeData){ + if(this.connected){ return; } + this.tunnelInit(); + } +} + +cometd.callbackPollTransport = new function(){ + this.connected = false; + this.connectionId = null; + + this.authToken = null; + this.lastTimestamp = null; + this.lastId = null; + this.backlog = []; + + this.check = function(types, version, xdomain){ + // we handle x-domain! + return dojo.lang.inArray(types, "callback-polling"); + } + + this.tunnelInit = function(){ + if(this.connected){ return; } + // FIXME: open up the connection here + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/connect", + clientId: cometd.clientId, + connectionType: "callback-polling" + // FIXME: auth not passed here! + // "authToken": this.authToken + } + ]) + }); + this.connected = true; + } + + this.tunnelCollapse = function(){ + if(!this.connected){ + // try to restart the tunnel + this.connected = false; + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/reconnect", + connectionType: "long-polling", + clientId: cometd.clientId, + connectionId: this.connectionId, + timestamp: this.lastTimestamp, + id: this.lastId + // FIXME: no authToken provision! + } + ]) + }); + } + } + + this.deliver = cometd.iframeTransport.deliver; + // the logic appears to be the same + + this.openTunnelWith = function(content, url){ + // create a <script> element to generate the request + var req = dojo.io.bind({ + url: (url||cometd.url), + content: content, + mimetype: "text/json", + transport: "ScriptSrcTransport", + jsonParamName: "jsonp", + load: dojo.lang.hitch(this, function(type, data, evt, args){ + dojo.debug(dojo.json.serialize(data)); + cometd.deliver(data); + this.connected = false; + this.tunnelCollapse(); + }), + error: function(){ dojo.debug("tunnel opening failed"); } + }); + this.connected = true; + } + + this.processBacklog = function(){ + while(this.backlog.length > 0){ + this.sendMessage(this.backlog.shift(), true); + } + } + + this.sendMessage = function(message, bypassBacklog){ + // FIXME: what about auth fields? + if((bypassBacklog)||(this.connected)){ + message.connectionId = this.connectionId; + message.clientId = cometd.clientId; + var bindArgs = { + url: cometd.url||djConfig["cometdRoot"], + mimetype: "text/json", + transport: "ScriptSrcTransport", + jsonParamName: "jsonp", + content: { message: dojo.json.serialize([ message ]) } + }; + return dojo.io.bind(bindArgs); + }else{ + this.backlog.push(message); + } + } + + this.startup = function(handshakeData){ + if(this.connected){ return; } + this.tunnelInit(); + } +} + +cometd.connectionTypes.register("mime-message-block", cometd.mimeReplaceTransport.check, cometd.mimeReplaceTransport); +cometd.connectionTypes.register("long-polling", cometd.longPollTransport.check, cometd.longPollTransport); +cometd.connectionTypes.register("callback-polling", cometd.callbackPollTransport.check, cometd.callbackPollTransport); +cometd.connectionTypes.register("iframe", cometd.iframeTransport.check, cometd.iframeTransport); + +// FIXME: need to implement fallback-polling, IE XML block + +dojo.io.cometd = cometd; Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cometd.js ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cometd.js ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cometd.js ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/common.js URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/images/webapp/images/dojo/src/io/common.js?view=auto&rev=509273 ============================================================================== --- ofbiz/trunk/framework/images/webapp/images/dojo/src/io/common.js (added) +++ ofbiz/trunk/framework/images/webapp/images/dojo/src/io/common.js Mon Feb 19 09:56:06 2007 @@ -0,0 +1,517 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.io.common"); +dojo.require("dojo.string"); +dojo.require("dojo.lang.extras"); + +/****************************************************************************** + * Notes about dojo.io design: + * + * The dojo.io.* package has the unenviable task of making a lot of different + * types of I/O feel natural, despite a universal lack of good (or even + * reasonable!) I/O capability in the host environment. So lets pin this down + * a little bit further. + * + * Rhino: + * perhaps the best situation anywhere. Access to Java classes allows you + * to do anything one might want in terms of I/O, both synchronously and + * async. Can open TCP sockets and perform low-latency client/server + * interactions. HTTP transport is available through Java HTTP client and + * server classes. Wish it were always this easy. + * + * xpcshell: + * XPCOM for I/O. + * + * spidermonkey: + * S.O.L. + * + * Browsers: + * Browsers generally do not provide any useable filesystem access. We are + * therefore limited to HTTP for moving information to and from Dojo + * instances living in a browser. + * + * XMLHTTP: + * Sync or async, allows reading of arbitrary text files (including + * JS, which can then be eval()'d), writing requires server + * cooperation and is limited to HTTP mechanisms (POST and GET). + * + * <iframe> hacks: + * iframe document hacks allow browsers to communicate asynchronously + * with a server via HTTP POST and GET operations. With significant + * effort and server cooperation, low-latency data transit between + * client and server can be acheived via iframe mechanisms (repubsub). + * + * SVG: + * Adobe's SVG viewer implements helpful primitives for XML-based + * requests, but receipt of arbitrary text data seems unlikely w/o + * <![CDATA[]]> sections. + * + * + * A discussion between Dylan, Mark, Tom, and Alex helped to lay down a lot + * the IO API interface. A transcript of it can be found at: + * http://dojotoolkit.org/viewcvs/viewcvs.py/documents/irc/irc_io_api_log.txt?rev=307&view=auto + * + * Also referenced in the design of the API was the DOM 3 L&S spec: + * http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/load-save.html + ******************************************************************************/ + +// a map of the available transport options. Transports should add themselves +// by calling add(name) +dojo.io.transports = []; +dojo.io.hdlrFuncNames = [ "load", "error", "timeout" ]; // we're omitting a progress() event for now + +dojo.io.Request = function(/*String*/ url, /*String*/ mimetype, /*String*/ transport, /*String or Boolean*/ changeUrl){ +// summary: +// Constructs a Request object that is used by dojo.io.bind(). +// description: +// dojo.io.bind() will create one of these for you if +// you call dojo.io.bind() with an plain object containing the bind parameters. +// This method can either take the arguments specified, or an Object containing all of the parameters that you +// want to use to create the dojo.io.Request (similar to how dojo.io.bind() is called. +// The named parameters to this constructor represent the minimum set of parameters need + if((arguments.length == 1)&&(arguments[0].constructor == Object)){ + this.fromKwArgs(arguments[0]); + }else{ + this.url = url; + if(mimetype){ this.mimetype = mimetype; } + if(transport){ this.transport = transport; } + if(arguments.length >= 4){ this.changeUrl = changeUrl; } + } +} + +dojo.lang.extend(dojo.io.Request, { + + /** The URL to hit */ + url: "", + + /** The mime type used to interrpret the response body */ + mimetype: "text/plain", + + /** The HTTP method to use */ + method: "GET", + + /** An Object containing key-value pairs to be included with the request */ + content: undefined, // Object + + /** The transport medium to use */ + transport: undefined, // String + + /** If defined the URL of the page is physically changed */ + changeUrl: undefined, // String + + /** A form node to use in the request */ + formNode: undefined, // HTMLFormElement + + /** Whether the request should be made synchronously */ + sync: false, + + bindSuccess: false, + + /** Cache/look for the request in the cache before attempting to request? + * NOTE: this isn't a browser cache, this is internal and would only cache in-page + */ + useCache: false, + + /** Prevent the browser from caching this by adding a query string argument to the URL */ + preventCache: false, + + // events stuff + load: function(/*String*/type, /*Object*/data, /*Object*/transportImplementation, /*Object*/kwArgs){ + // summary: + // Called on successful completion of a bind. + // type: String + // A string with value "load" + // data: Object + // The object representing the result of the bind. The actual structure + // of the data object will depend on the mimetype that was given to bind + // in the bind arguments. + // transportImplementation: Object + // The object that implements a particular transport. Structure is depedent + // on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the + // XMLHttpRequest object from the browser. + // kwArgs: Object + // Object that contains the request parameters that were given to the + // bind call. Useful for storing and retrieving state from when bind + // was called. + }, + error: function(/*String*/type, /*Object*/error, /*Object*/transportImplementation, /*Object*/kwArgs){ + // summary: + // Called when there is an error with a bind. + // type: String + // A string with value "error" + // error: Object + // The error object. Should be a dojo.io.Error object, but not guaranteed. + // transportImplementation: Object + // The object that implements a particular transport. Structure is depedent + // on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the + // XMLHttpRequest object from the browser. + // kwArgs: Object + // Object that contains the request parameters that were given to the + // bind call. Useful for storing and retrieving state from when bind + // was called. + }, + timeout: function(/*String*/type, /*Object*/empty, /*Object*/transportImplementation, /*Object*/kwArgs){ + // summary: + // Called when there is an error with a bind. Only implemented in certain transports at this time. + // type: String + // A string with value "timeout" + // empty: Object + // Should be null. Just a spacer argument so that load, error, timeout and handle have the + // same signatures. + // transportImplementation: Object + // The object that implements a particular transport. Structure is depedent + // on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the + // XMLHttpRequest object from the browser. May be null for the timeout case for + // some transports. + // kwArgs: Object + // Object that contains the request parameters that were given to the + // bind call. Useful for storing and retrieving state from when bind + // was called. + }, + handle: function(/*String*/type, /*Object*/data, /*Object*/transportImplementation, /*Object*/kwArgs){ + // summary: + // The handle method can be defined instead of defining separate load, error and timeout + // callbacks. + // type: String + // A string with the type of callback: "load", "error", or "timeout". + // data: Object + // See the above callbacks for what this parameter could be. + // transportImplementation: Object + // The object that implements a particular transport. Structure is depedent + // on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the + // XMLHttpRequest object from the browser. + // kwArgs: Object + // Object that contains the request parameters that were given to the + // bind call. Useful for storing and retrieving state from when bind + // was called. + }, + + //FIXME: change IframeIO.js to use timeouts? + // The number of seconds to wait until firing a timeout callback. + // If it is zero, that means, don't do a timeout check. + timeoutSeconds: 0, + + // the abort method needs to be filled in by the transport that accepts the + // bind() request + abort: function(){ }, + + // backButton: function(){ }, + // forwardButton: function(){ }, + + fromKwArgs: function(/*Object*/ kwArgs){ + // summary: + // Creates a dojo.io.Request from a simple object (kwArgs object). + + // normalize args + if(kwArgs["url"]){ kwArgs.url = kwArgs.url.toString(); } + if(kwArgs["formNode"]) { kwArgs.formNode = dojo.byId(kwArgs.formNode); } + if(!kwArgs["method"] && kwArgs["formNode"] && kwArgs["formNode"].method) { + kwArgs.method = kwArgs["formNode"].method; + } + + // backwards compatibility + if(!kwArgs["handle"] && kwArgs["handler"]){ kwArgs.handle = kwArgs.handler; } + if(!kwArgs["load"] && kwArgs["loaded"]){ kwArgs.load = kwArgs.loaded; } + if(!kwArgs["changeUrl"] && kwArgs["changeURL"]) { kwArgs.changeUrl = kwArgs.changeURL; } + + // encoding fun! + kwArgs.encoding = dojo.lang.firstValued(kwArgs["encoding"], djConfig["bindEncoding"], ""); + + kwArgs.sendTransport = dojo.lang.firstValued(kwArgs["sendTransport"], djConfig["ioSendTransport"], false); + + var isFunction = dojo.lang.isFunction; + for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){ + var fn = dojo.io.hdlrFuncNames[x]; + if(kwArgs[fn] && isFunction(kwArgs[fn])){ continue; } + if(kwArgs["handle"] && isFunction(kwArgs["handle"])){ + kwArgs[fn] = kwArgs.handle; + } + // handler is aliased above, shouldn't need this check + /* else if(dojo.lang.isObject(kwArgs.handler)){ + if(isFunction(kwArgs.handler[fn])){ + kwArgs[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"]||function(){}; + } + }*/ + } + dojo.lang.mixin(this, kwArgs); + } + +}); + +dojo.io.Error = function(/*String*/ msg, /*String*/ type, /*Number*/num){ + // summary: + // Constructs an object representing a bind error. + this.message = msg; + this.type = type || "unknown"; // must be one of "io", "parse", "unknown" + this.number = num || 0; // per-substrate error number, not normalized +} + +dojo.io.transports.addTransport = function(/*String*/name){ + // summary: + // Used to register transports that can support bind calls. + this.push(name); + // FIXME: do we need to handle things that aren't direct children of the + // dojo.io module? (say, dojo.io.foo.fooTransport?) + this[name] = dojo.io[name]; +} + +// binding interface, the various implementations register their capabilities +// and the bind() method dispatches +dojo.io.bind = function(/*dojo.io.Request or Object*/request){ + // summary: + // Binding interface for IO. Loading different IO transports, like + // dojo.io.BrowserIO or dojo.io.IframeIO, will register with bind + // to handle particular types of bind calls. + // request: Object + // Object containing bind arguments. This object is converted to + // a dojo.io.Request object, and that request object is the return + // value for this method. + if(!(request instanceof dojo.io.Request)){ + try{ + request = new dojo.io.Request(request); + }catch(e){ dojo.debug(e); } + } + + // if the request asks for a particular implementation, use it + var tsName = ""; + if(request["transport"]){ + tsName = request["transport"]; + if(!this[tsName]){ + dojo.io.sendBindError(request, "No dojo.io.bind() transport with name '" + + request["transport"] + "'."); + return request; //dojo.io.Request + } + if(!this[tsName].canHandle(request)){ + dojo.io.sendBindError(request, "dojo.io.bind() transport with name '" + + request["transport"] + "' cannot handle this type of request."); + return request; //dojo.io.Request + } + }else{ + // otherwise we do our best to auto-detect what available transports + // will handle + for(var x=0; x<dojo.io.transports.length; x++){ + var tmp = dojo.io.transports[x]; + if((this[tmp])&&(this[tmp].canHandle(request))){ + tsName = tmp; + break; + } + } + if(tsName == ""){ + dojo.io.sendBindError(request, "None of the loaded transports for dojo.io.bind()" + + " can handle the request."); + return request; //dojo.io.Request + } + } + this[tsName].bind(request); + request.bindSuccess = true; + return request; //dojo.io.Request +} + +dojo.io.sendBindError = function(/* Object */request, /* String */message){ + // summary: + // Used internally by dojo.io.bind() to return/raise a bind error. + + //Need to be careful since not all hostenvs support setTimeout. + if((typeof request.error == "function" || typeof request.handle == "function") + && (typeof setTimeout == "function" || typeof setTimeout == "object")){ + var errorObject = new dojo.io.Error(message); + setTimeout(function(){ + request[(typeof request.error == "function") ? "error" : "handle"]("error", errorObject, null, request); + }, 50); + }else{ + dojo.raise(message); + } +} + +dojo.io.queueBind = function(/*dojo.io.Request or Object*/request){ + // summary: + // queueBind will use dojo.io.bind() but guarantee that only one bind + // call is handled at a time. + // description: + // If queueBind is called while a bind call + // is in process, it will queue up the other calls to bind and call them + // in order as bind calls complete. + // request: Object + // Same sort of request object as used for dojo.io.bind(). + if(!(request instanceof dojo.io.Request)){ + try{ + request = new dojo.io.Request(request); + }catch(e){ dojo.debug(e); } + } + + // make sure we get called if/when we get a response + var oldLoad = request.load; + request.load = function(){ + dojo.io._queueBindInFlight = false; + var ret = oldLoad.apply(this, arguments); + dojo.io._dispatchNextQueueBind(); + return ret; + } + + var oldErr = request.error; + request.error = function(){ + dojo.io._queueBindInFlight = false; + var ret = oldErr.apply(this, arguments); + dojo.io._dispatchNextQueueBind(); + return ret; + } + + dojo.io._bindQueue.push(request); + dojo.io._dispatchNextQueueBind(); + return request; //dojo.io.Request +} + +dojo.io._dispatchNextQueueBind = function(){ + // summary: + // Private method used by dojo.io.queueBind(). + if(!dojo.io._queueBindInFlight){ + dojo.io._queueBindInFlight = true; + if(dojo.io._bindQueue.length > 0){ + dojo.io.bind(dojo.io._bindQueue.shift()); + }else{ + dojo.io._queueBindInFlight = false; + } + } +} +dojo.io._bindQueue = []; +dojo.io._queueBindInFlight = false; + +dojo.io.argsFromMap = function(/*Object*/map, /*String?*/encoding, /*String?*/last){ + // summary: + // Converts name/values pairs in the map object to an URL-encoded string + // with format of name1=value1&name2=value2... + // map: Object + // Object that has the contains the names and values. + // encoding: String? + // String to specify how to encode the name and value. If the encoding string + // contains "utf" (case-insensitive), then encodeURIComponent is used. Otherwise + // dojo.string.encodeAscii is used. + // last: String? + // The last parameter in the list. Helps with final string formatting? + var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii; + var mapped = []; + var control = new Object(); + for(var name in map){ + var domap = function(elt){ + var val = enc(name)+"="+enc(elt); + mapped[(last == name) ? "push" : "unshift"](val); + } + if(!control[name]){ + var value = map[name]; + // FIXME: should be isArrayLike? + if (dojo.lang.isArray(value)){ + dojo.lang.forEach(value, domap); + }else{ + domap(value); + } + } + } + return mapped.join("&"); //String +} + +dojo.io.setIFrameSrc = function(/*DOMNode*/ iframe, /*String*/ src, /*Boolean*/ replace){ + //summary: + // Sets the URL that is loaded in an IFrame. The replace parameter indicates whether + // location.replace() should be used when changing the location of the iframe. + try{ + var r = dojo.render.html; + // dojo.debug(iframe); + if(!replace){ + if(r.safari){ + iframe.location = src; + }else{ + frames[iframe.name].location = src; + } + }else{ + // Fun with DOM 0 incompatibilities! + var idoc; + if(r.ie){ + idoc = iframe.contentWindow.document; + }else if(r.safari){ + idoc = iframe.document; + }else{ // if(r.moz){ + idoc = iframe.contentWindow; + } + + //For Safari (at least 2.0.3) and Opera, if the iframe + //has just been created but it doesn't have content + //yet, then iframe.document may be null. In that case, + //use iframe.location and return. + if(!idoc){ + iframe.location = src; + return; + }else{ + idoc.location.replace(src); + } + } + }catch(e){ + dojo.debug(e); + dojo.debug("setIFrameSrc: "+e); + } +} + +/* +dojo.io.sampleTranport = new function(){ + this.canHandle = function(kwArgs){ + // canHandle just tells dojo.io.bind() if this is a good transport to + // use for the particular type of request. + if( + ( + (kwArgs["mimetype"] == "text/plain") || + (kwArgs["mimetype"] == "text/html") || + (kwArgs["mimetype"] == "text/javascript") + )&&( + (kwArgs["method"] == "get") || + ( (kwArgs["method"] == "post") && (!kwArgs["formNode"]) ) + ) + ){ + return true; + } + + return false; + } + + this.bind = function(kwArgs){ + var hdlrObj = {}; + + // set up a handler object + for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){ + var fn = dojo.io.hdlrFuncNames[x]; + if(typeof kwArgs.handler == "object"){ + if(typeof kwArgs.handler[fn] == "function"){ + hdlrObj[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"]; + } + }else if(typeof kwArgs[fn] == "function"){ + hdlrObj[fn] = kwArgs[fn]; + }else{ + hdlrObj[fn] = kwArgs["handle"]||function(){}; + } + } + + // build a handler function that calls back to the handler obj + var hdlrFunc = function(evt){ + if(evt.type == "onload"){ + hdlrObj.load("load", evt.data, evt); + }else if(evt.type == "onerr"){ + var errObj = new dojo.io.Error("sampleTransport Error: "+evt.msg); + hdlrObj.error("error", errObj); + } + } + + // the sample transport would attach the hdlrFunc() when sending the + // request down the pipe at this point + var tgtURL = kwArgs.url+"?"+dojo.io.argsFromMap(kwArgs.content); + // sampleTransport.sendRequest(tgtURL, hdlrFunc); + } + + dojo.io.transports.addTransport("sampleTranport"); +} +*/ Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/common.js ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/common.js ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/common.js ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cookie.js URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cookie.js?view=auto&rev=509273 ============================================================================== --- ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cookie.js (added) +++ ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cookie.js Mon Feb 19 09:56:06 2007 @@ -0,0 +1,130 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.io.cookie"); + +dojo.io.cookie.setCookie = function(/*String*/name, /*String*/value, + /*Number?*/days, /*String?*/path, + /*String?*/domain, /*boolean?*/secure){ + //summary: sets a cookie. + var expires = -1; + if((typeof days == "number")&&(days >= 0)){ + var d = new Date(); + d.setTime(d.getTime()+(days*24*60*60*1000)); + expires = d.toGMTString(); + } + value = escape(value); + document.cookie = name + "=" + value + ";" + + (expires != -1 ? " expires=" + expires + ";" : "") + + (path ? "path=" + path : "") + + (domain ? "; domain=" + domain : "") + + (secure ? "; secure" : ""); +} + +dojo.io.cookie.set = dojo.io.cookie.setCookie; + +dojo.io.cookie.getCookie = function(/*String*/name){ + //summary: Gets a cookie with the given name. + + // FIXME: Which cookie should we return? + // If there are cookies set for different sub domains in the current + // scope there could be more than one cookie with the same name. + // I think taking the last one in the list takes the one from the + // deepest subdomain, which is what we're doing here. + var idx = document.cookie.lastIndexOf(name+'='); + if(idx == -1) { return null; } + var value = document.cookie.substring(idx+name.length+1); + var end = value.indexOf(';'); + if(end == -1) { end = value.length; } + value = value.substring(0, end); + value = unescape(value); + return value; //String +} + +dojo.io.cookie.get = dojo.io.cookie.getCookie; + +dojo.io.cookie.deleteCookie = function(/*String*/name){ + //summary: Deletes a cookie with the given name. + dojo.io.cookie.setCookie(name, "-", 0); +} + +dojo.io.cookie.setObjectCookie = function( /*String*/name, /*Object*/obj, + /*Number?*/days, /*String?*/path, + /*String?*/domain, /*boolean?*/secure, + /*boolean?*/clearCurrent){ + //summary: Takes an object, serializes it to a cookie value, and either + //sets a cookie with the serialized value. + //description: If clearCurrent is true, then any current cookie value + //for this object will be replaced with the the new serialized object value. + //If clearCurrent is false, then the existing cookie value will be modified + //with any changes from the new object value. + //Objects must be simple name/value pairs where the value is either a string + //or a number. Any other value will be ignored. + if(arguments.length == 5){ // for backwards compat + clearCurrent = domain; + domain = null; + secure = null; + } + var pairs = [], cookie, value = ""; + if(!clearCurrent){ + cookie = dojo.io.cookie.getObjectCookie(name); + } + if(days >= 0){ + if(!cookie){ cookie = {}; } + for(var prop in obj){ + if(obj[prop] == null){ + delete cookie[prop]; + }else if((typeof obj[prop] == "string")||(typeof obj[prop] == "number")){ + cookie[prop] = obj[prop]; + } + } + prop = null; + for(var prop in cookie){ + pairs.push(escape(prop) + "=" + escape(cookie[prop])); + } + value = pairs.join("&"); + } + dojo.io.cookie.setCookie(name, value, days, path, domain, secure); +} + +dojo.io.cookie.getObjectCookie = function(/*String*/name){ + //summary: Gets an object value for the given cookie name. The complement of + //dojo.io.cookie.setObjectCookie(). + var values = null, cookie = dojo.io.cookie.getCookie(name); + if(cookie){ + values = {}; + var pairs = cookie.split("&"); + for(var i = 0; i < pairs.length; i++){ + var pair = pairs[i].split("="); + var value = pair[1]; + if( isNaN(value) ){ value = unescape(pair[1]); } + values[ unescape(pair[0]) ] = value; + } + } + return values; +} + +dojo.io.cookie.isSupported = function(){ + //summary: Tests the browser to see if cookies are enabled. + if(typeof navigator.cookieEnabled != "boolean"){ + dojo.io.cookie.setCookie("__TestingYourBrowserForCookieSupport__", + "CookiesAllowed", 90, null); + var cookieVal = dojo.io.cookie.getCookie("__TestingYourBrowserForCookieSupport__"); + navigator.cookieEnabled = (cookieVal == "CookiesAllowed"); + if(navigator.cookieEnabled){ + // FIXME: should we leave this around? + this.deleteCookie("__TestingYourBrowserForCookieSupport__"); + } + } + return navigator.cookieEnabled; //boolean +} + +// need to leave this in for backwards-compat from 0.1 for when it gets pulled in by dojo.io.* +if(!dojo.io.cookies){ dojo.io.cookies = dojo.io.cookie; } Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cookie.js ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cookie.js ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/cookie.js ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/framework/images/webapp/images/dojo/src/io/xip_client.html URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/images/webapp/images/dojo/src/io/xip_client.html?view=auto&rev=509273 ============================================================================== --- ofbiz/trunk/framework/images/webapp/images/dojo/src/io/xip_client.html (added) +++ ofbiz/trunk/framework/images/webapp/images/dojo/src/io/xip_client.html Mon Feb 19 09:56:06 2007 @@ -0,0 +1,254 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> + <title></title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta> + <script type="text/javascript"> + // <!-- + /* + This file is really focused on just sending one message to the server, and + receiving one response. The code does not expect to be re-used for multiple messages. + This might be reworked later if performance indicates a need for it. + + xip fragment identifier/hash values have the form: + #id:cmd:realEncodedMessage + + id: some ID that should be unique among messages. No inherent meaning, + just something to make sure the hash value is unique so the message + receiver knows a new message is available. + + cmd: command to the receiver. Valid values are: + - init: message used to init the frame. Sent as the first URL when loading + the page. Contains some config parameters. + - loaded: the remote frame is loaded. Only sent from server to client. + - ok: the message that this page sent was received OK. The next message may + now be sent. + - start: the start message of a block of messages (a complete message may + need to be segmented into many messages to get around the limitiations + of the size of an URL that a browser accepts. + - part: indicates this is a part of a message. + - end: the end message of a block of messages. The message can now be acted upon. + If the message is small enough that it doesn't need to be segmented, then + just one hash value message can be sent with "end" as the command. + + To reassemble a segmented message, the realEncodedMessage parts just have to be concatenated + together. + */ + + //MSIE has the lowest limit for URLs with fragment identifiers, + //at around 4K. Choosing a slightly smaller number for good measure. + xipUrlLimit = 4000; + xipIdCounter = 1; + + function xipInit(){ + xipStateId = ""; + xipIsSending = false; + xipServerUrl = null; + xipStateId = null; + xipRequestData = null; + xipCurrentHash = ""; + xipResponseMessage = ""; + xipRequestParts = []; + xipPartIndex = 0; + xipServerWindow = null; + xipUseFrameRecursion = false; + } + xipInit(); + + function send(encodedData){ + if(xipUseFrameRecursion == "true"){ + var clientEndPoint = window.open(xipStateId + "_clientEndPoint"); + clientEndPoint.send(encodedData); + }else{ + if(!xipIsSending){ + xipIsSending = true; + + xipRequestData = encodedData || ""; + + //Get a handle to the server iframe. + xipServerWindow = frames[xipStateId + "_frame"]; + if (!xipServerWindow){ + xipServerWindow = document.getElementById(xipStateId + "_frame").contentWindow; + } + + sendRequestStart(); + } + } + } + + //Modify the server URL if it is a local path and + //This is done for local/same domain testing. + function fixServerUrl(ifpServerUrl){ + if(ifpServerUrl.indexOf("..") == 0){ + var parts = ifpServerUrl.split("/"); + ifpServerUrl = parts[parts.length - 1]; + } + return ifpServerUrl; + } + + + function pollHash(){ + //Can't use location.hash because at least Firefox does a decodeURIComponent on it. + var urlParts = window.location.href.split("#"); + if(urlParts.length == 2){ + var newHash = urlParts[1]; + if(newHash != xipCurrentHash){ + try{ + messageReceived(newHash); + }catch(e){ + //Make sure to not keep processing the error hash value. + xipCurrentHash = newHash; + throw e; + } + xipCurrentHash = newHash; + } + } + } + + function messageReceived(encodedData){ + var msg = unpackMessage(encodedData); + + switch(msg.command){ + case "loaded": + xipMasterFrame.dojo.io.XhrIframeProxy.clientFrameLoaded(xipStateId); + break; + case "ok": + sendRequestPart(); + break; + case "start": + xipResponseMessage = ""; + xipResponseMessage += msg.message; + setServerUrl("ok"); + break; + case "part": + xipResponseMessage += msg.message; + setServerUrl("ok"); + break; + case "end": + setServerUrl("ok"); + xipResponseMessage += msg.message; + xipMasterFrame.dojo.io.XhrIframeProxy.receive(xipStateId, xipResponseMessage); + break; + } + } + + function sendRequestStart(){ + //Break the message into parts, if necessary. + xipRequestParts = []; + var reqData = xipRequestData; + var urlLength = xipServerUrl.length; + var partLength = xipUrlLimit - urlLength; + var reqIndex = 0; + + while((reqData.length - reqIndex) + urlLength > xipUrlLimit){ + xipRequestParts.push(reqData.substring(reqIndex, reqIndex + partLength)); + reqIndex += partLength; + } + xipRequestParts.push(reqData.substring(reqIndex, reqData.length)); + + xipPartIndex = 0; + sendRequestPart(); + + } + + function sendRequestPart(){ + if(xipPartIndex < xipRequestParts.length){ + //Get the message part. + var partData = xipRequestParts[xipPartIndex]; + + //Get the command. + var cmd = "part"; + if(xipPartIndex + 1 == xipRequestParts.length){ + cmd = "end"; + }else if (xipPartIndex == 0){ + cmd = "start"; + } + + setServerUrl(cmd, partData); + xipPartIndex++; + } + } + + function setServerUrl(cmd, message){ + var serverUrl = makeServerUrl(cmd, message); + + //Safari won't let us replace across domains. + if(navigator.userAgent.indexOf("Safari") == -1){ + xipServerWindow.location.replace(serverUrl); + }else{ + xipServerWindow.location = serverUrl; + } + } + + function makeServerUrl(c |
Free forum by Nabble | Edit this page |