diff options
Diffstat (limited to 'includes/js/dojo/_base/connect.js')
-rw-r--r-- | includes/js/dojo/_base/connect.js | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/includes/js/dojo/_base/connect.js b/includes/js/dojo/_base/connect.js new file mode 100644 index 0000000..5111372 --- /dev/null +++ b/includes/js/dojo/_base/connect.js @@ -0,0 +1,285 @@ +if(!dojo._hasResource["dojo._base.connect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo._base.connect"] = true; +dojo.provide("dojo._base.connect"); +dojo.require("dojo._base.lang"); + +// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA + +// low-level delegation machinery +dojo._listener = { + // create a dispatcher function + getDispatcher: function(){ + // following comments pulled out-of-line to prevent cloning them + // in the returned function. + // - indices (i) that are really in the array of listeners (ls) will + // not be in Array.prototype. This is the 'sparse array' trick + // that keeps us safe from libs that take liberties with built-in + // objects + // - listener is invoked with current scope (this) + return function(){ + var ap=Array.prototype, c=arguments.callee, ls=c._listeners, t=c.target; + // return value comes from original target function + var r=t && t.apply(this, arguments); + // invoke listeners after target function + for(var i in ls){ + if(!(i in ap)){ + ls[i].apply(this, arguments); + } + } + // return value comes from original target function + return r; + } + }, + // add a listener to an object + add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){ + // Whenever 'method' is invoked, 'listener' will have the same scope. + // Trying to supporting a context object for the listener led to + // complexity. + // Non trivial to provide 'once' functionality here + // because listener could be the result of a dojo.hitch call, + // in which case two references to the same hitch target would not + // be equivalent. + source = source || dojo.global; + // The source method is either null, a dispatcher, or some other function + var f = source[method]; + // Ensure a dispatcher + if(!f||!f._listeners){ + var d = dojo._listener.getDispatcher(); + // original target function is special + d.target = f; + // dispatcher holds a list of listeners + d._listeners = []; + // redirect source to dispatcher + f = source[method] = d; + } + // The contract is that a handle is returned that can + // identify this listener for disconnect. + // + // The type of the handle is private. Here is it implemented as Integer. + // DOM event code has this same contract but handle is Function + // in non-IE browsers. + // + // We could have separate lists of before and after listeners. + return f._listeners.push(listener) ; /*Handle*/ + }, + // remove a listener from an object + remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){ + var f = (source||dojo.global)[method]; + // remember that handle is the index+1 (0 is not a valid handle) + if(f && f._listeners && handle--){ + delete f._listeners[handle]; + } + } +}; + +// Multiple delegation for arbitrary methods. + +// This unit knows nothing about DOM, +// but we include DOM aware +// documentation and dontFix +// argument here to help the autodocs. +// Actual DOM aware code is in event.js. + +dojo.connect = function(/*Object|null*/ obj, + /*String*/ event, + /*Object|null*/ context, + /*String|Function*/ method, + /*Boolean*/ dontFix){ + // summary: + // Create a link that calls one function when another executes. + // + // description: + // Connects method to event, so that after event fires, method + // does too. All connected functions are passed the same arguments as + // the event function was initially called with. You may connect as + // many methods to event as needed. + // + // event must be a string. If obj is null, dojo.global is used. + // + // null arguments may simply be omitted. + // + // obj[event] can resolve to a function or undefined (null). + // If obj[event] is null, it is assigned a function. + // + // The return value is a handle that is needed to + // remove this connection with dojo.disconnect. + // + // obj: + // The source object for the event function. + // Defaults to dojo.global if null. + // If obj is a DOM node, the connection is delegated + // to the DOM event manager (unless dontFix is true). + // + // event: + // String name of the event function in obj. + // I.e. identifies a property obj[event]. + // + // context: + // The object that method will receive as "this". + // + // If context is null and method is a function, then method + // inherits the context of event. + // + // If method is a string then context must be the source + // object object for method (context[method]). If context is null, + // dojo.global is used. + // + // method: + // A function reference, or name of a function in context. + // The function identified by method fires after event does. + // method receives the same arguments as the event. + // See context argument comments for information on method's scope. + // + // dontFix: + // If obj is a DOM node, set dontFix to true to prevent delegation + // of this connection to the DOM event manager. + // + // example: + // When obj.onchange(), do ui.update(): + // | dojo.connect(obj, "onchange", ui, "update"); + // | dojo.connect(obj, "onchange", ui, ui.update); // same + // + // example: + // Using return value for disconnect: + // | var link = dojo.connect(obj, "onchange", ui, "update"); + // | ... + // | dojo.disconnect(link); + // + // example: + // When onglobalevent executes, watcher.handler is invoked: + // | dojo.connect(null, "onglobalevent", watcher, "handler"); + // + // example: + // When ob.onCustomEvent executes, customEventHandler is invoked: + // | dojo.connect(ob, "onCustomEvent", null, "customEventHandler"); + // | dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same + // + // example: + // When ob.onCustomEvent executes, customEventHandler is invoked + // with the same scope (this): + // | dojo.connect(ob, "onCustomEvent", null, customEventHandler); + // | dojo.connect(ob, "onCustomEvent", customEventHandler); // same + // + // example: + // When globalEvent executes, globalHandler is invoked + // with the same scope (this): + // | dojo.connect(null, "globalEvent", null, globalHandler); + // | dojo.connect("globalEvent", globalHandler); // same + + // normalize arguments + var a=arguments, args=[], i=0; + // if a[0] is a String, obj was ommited + args.push(dojo.isString(a[0]) ? null : a[i++], a[i++]); + // if the arg-after-next is a String or Function, context was NOT omitted + var a1 = a[i+1]; + args.push(dojo.isString(a1)||dojo.isFunction(a1) ? a[i++] : null, a[i++]); + // absorb any additional arguments + for(var l=a.length; i<l; i++){ args.push(a[i]); } + // do the actual work + return dojo._connect.apply(this, args); /*Handle*/ +} + +// used by non-browser hostenvs. always overriden by event.js +dojo._connect = function(obj, event, context, method){ + var l=dojo._listener, h=l.add(obj, event, dojo.hitch(context, method)); + return [obj, event, h, l]; // Handle +} + +dojo.disconnect = function(/*Handle*/ handle){ + // summary: + // Remove a link created by dojo.connect. + // description: + // Removes the connection between event and the method referenced by handle. + // handle: + // the return value of the dojo.connect call that created the connection. + if(handle && handle[0] !== undefined){ + dojo._disconnect.apply(this, handle); + // let's not keep this reference + delete handle[0]; + } +} + +dojo._disconnect = function(obj, event, handle, listener){ + listener.remove(obj, event, handle); +} + +// topic publish/subscribe + +dojo._topics = {}; + +dojo.subscribe = function(/*String*/ topic, /*Object|null*/ context, /*String|Function*/ method){ + // summary: + // Attach a listener to a named topic. The listener function is invoked whenever the + // named topic is published (see: dojo.publish). + // Returns a handle which is needed to unsubscribe this listener. + // context: + // Scope in which method will be invoked, or null for default scope. + // method: + // The name of a function in context, or a function reference. This is the function that + // is invoked when topic is published. + // example: + // | dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); }; + // | dojo.publish("alerts", [ "read this", "hello world" ]); + + // support for 2 argument invocation (omitting context) depends on hitch + return [topic, dojo._listener.add(dojo._topics, topic, dojo.hitch(context, method))]; /*Handle*/ +} + +dojo.unsubscribe = function(/*Handle*/ handle){ + // summary: + // Remove a topic listener. + // handle: + // The handle returned from a call to subscribe. + // example: + // | var alerter = dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); }; + // | ... + // | dojo.unsubscribe(alerter); + if(handle){ + dojo._listener.remove(dojo._topics, handle[0], handle[1]); + } +} + +dojo.publish = function(/*String*/ topic, /*Array*/ args){ + // summary: + // Invoke all listener method subscribed to topic. + // topic: + // The name of the topic to publish. + // args: + // An array of arguments. The arguments will be applied + // to each topic subscriber (as first class parameters, via apply). + // example: + // | dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); }; + // | dojo.publish("alerts", [ "read this", "hello world" ]); + + // Note that args is an array, which is more efficient vs variable length + // argument list. Ideally, var args would be implemented via Array + // throughout the APIs. + var f = dojo._topics[topic]; + if(f){ + f.apply(this, args||[]); + } +} + +dojo.connectPublisher = function( /*String*/ topic, + /*Object|null*/ obj, + /*String*/ event){ + // summary: + // Ensure that everytime obj.event() is called, a message is published + // on the topic. Returns a handle which can be passed to + // dojo.disconnect() to disable subsequent automatic publication on + // the topic. + // topic: + // The name of the topic to publish. + // obj: + // The source object for the event function. Defaults to dojo.global + // if null. + // event: + // The name of the event function in obj. + // I.e. identifies a property obj[event]. + // example: + // | dojo.connectPublisher("/ajax/start", dojo, "xhrGet"}; + var pf = function(){ dojo.publish(topic, arguments); } + return (event) ? dojo.connect(obj, event, pf) : dojo.connect(obj, pf); //Handle +}; + +} |