]> git.wh0rd.org Git - tt-rss.git/blob - lib/dojo/_base/connect.js.uncompressed.js
upgrade dojo to 1.8.3 (refs #570)
[tt-rss.git] / lib / dojo / _base / connect.js.uncompressed.js
1 define("dojo/_base/connect", ["./kernel", "../on", "../topic", "../aspect", "./event", "../mouse", "./sniff", "./lang", "../keys"], function(dojo, on, hub, aspect, eventModule, mouse, has, lang){
2 // module:
3 //              dojo/_base/connect
4
5 has.add("events-keypress-typed", function(){ // keypresses should only occur a printable character is hit
6         var testKeyEvent = {charCode: 0};
7         try{
8                 testKeyEvent = document.createEvent("KeyboardEvent");
9                 (testKeyEvent.initKeyboardEvent || testKeyEvent.initKeyEvent).call(testKeyEvent, "keypress", true, true, null, false, false, false, false, 9, 3);
10         }catch(e){}
11         return testKeyEvent.charCode == 0 && !has("opera");
12 });
13
14 function connect_(obj, event, context, method, dontFix){
15         method = lang.hitch(context, method);
16         if(!obj || !(obj.addEventListener || obj.attachEvent)){
17                 // it is a not a DOM node and we are using the dojo.connect style of treating a
18                 // method like an event, must go right to aspect
19                 return aspect.after(obj || dojo.global, event, method, true);
20         }
21         if(typeof event == "string" && event.substring(0, 2) == "on"){
22                 event = event.substring(2);
23         }
24         if(!obj){
25                 obj = dojo.global;
26         }
27         if(!dontFix){
28                 switch(event){
29                         // dojo.connect has special handling for these event types
30                         case "keypress":
31                                 event = keypress;
32                                 break;
33                         case "mouseenter":
34                                 event = mouse.enter;
35                                 break;
36                         case "mouseleave":
37                                 event = mouse.leave;
38                                 break;
39                 }
40         }
41         return on(obj, event, method, dontFix);
42 }
43
44 var _punctMap = {
45         106:42,
46         111:47,
47         186:59,
48         187:43,
49         188:44,
50         189:45,
51         190:46,
52         191:47,
53         192:96,
54         219:91,
55         220:92,
56         221:93,
57         222:39,
58         229:113
59 };
60 var evtCopyKey = has("mac") ? "metaKey" : "ctrlKey";
61
62
63 var _synthesizeEvent = function(evt, props){
64         var faux = lang.mixin({}, evt, props);
65         setKeyChar(faux);
66         // FIXME: would prefer to use lang.hitch: lang.hitch(evt, evt.preventDefault);
67         // but it throws an error when preventDefault is invoked on Safari
68         // does Event.preventDefault not support "apply" on Safari?
69         faux.preventDefault = function(){ evt.preventDefault(); };
70         faux.stopPropagation = function(){ evt.stopPropagation(); };
71         return faux;
72 };
73 function setKeyChar(evt){
74         evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : '';
75         evt.charOrCode = evt.keyChar || evt.keyCode;
76 }
77 var keypress;
78 if(has("events-keypress-typed")){
79         // this emulates Firefox's keypress behavior where every keydown can correspond to a keypress
80         var _trySetKeyCode = function(e, code){
81                 try{
82                         // squelch errors when keyCode is read-only
83                         // (e.g. if keyCode is ctrl or shift)
84                         return (e.keyCode = code);
85                 }catch(e){
86                         return 0;
87                 }
88         };
89         keypress = function(object, listener){
90                 var keydownSignal = on(object, "keydown", function(evt){
91                         // munge key/charCode
92                         var k=evt.keyCode;
93                         // These are Windows Virtual Key Codes
94                         // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
95                         var unprintable = (k!=13) && k!=32 && (k!=27||!has("ie")) && (k<48||k>90) && (k<96||k>111) && (k<186||k>192) && (k<219||k>222) && k!=229;
96                         // synthesize keypress for most unprintables and CTRL-keys
97                         if(unprintable||evt.ctrlKey){
98                                 var c = unprintable ? 0 : k;
99                                 if(evt.ctrlKey){
100                                         if(k==3 || k==13){
101                                                 return listener.call(evt.currentTarget, evt); // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively
102                                         }else if(c>95 && c<106){
103                                                 c -= 48; // map CTRL-[numpad 0-9] to ASCII
104                                         }else if((!evt.shiftKey)&&(c>=65&&c<=90)){
105                                                 c += 32; // map CTRL-[A-Z] to lowercase
106                                         }else{
107                                                 c = _punctMap[c] || c; // map other problematic CTRL combinations to ASCII
108                                         }
109                                 }
110                                 // simulate a keypress event
111                                 var faux = _synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
112                                 listener.call(evt.currentTarget, faux);
113                                 if(has("ie")){
114                                         _trySetKeyCode(evt, faux.keyCode);
115                                 }
116                         }
117                 });
118                 var keypressSignal = on(object, "keypress", function(evt){
119                         var c = evt.charCode;
120                         c = c>=32 ? c : 0;
121                         evt = _synthesizeEvent(evt, {charCode: c, faux: true});
122                         return listener.call(this, evt);
123                 });
124                 return {
125                         remove: function(){
126                                 keydownSignal.remove();
127                                 keypressSignal.remove();
128                         }
129                 };
130         };
131 }else{
132         if(has("opera")){
133                 keypress = function(object, listener){
134                         return on(object, "keypress", function(evt){
135                                 var c = evt.which;
136                                 if(c==3){
137                                         c=99; // Mozilla maps CTRL-BREAK to CTRL-c
138                                 }
139                                 // can't trap some keys at all, like INSERT and DELETE
140                                 // there is no differentiating info between DELETE and ".", or INSERT and "-"
141                                 c = c<32 && !evt.shiftKey ? 0 : c;
142                                 if(evt.ctrlKey && !evt.shiftKey && c>=65 && c<=90){
143                                         // lowercase CTRL-[A-Z] keys
144                                         c += 32;
145                                 }
146                                 return listener.call(this, _synthesizeEvent(evt, { charCode: c }));
147                         });
148                 };
149         }else{
150                 keypress = function(object, listener){
151                         return on(object, "keypress", function(evt){
152                                 setKeyChar(evt);
153                                 return listener.call(this, evt);
154                         });
155                 };
156         }
157 }
158
159 var connect = {
160         // summary:
161         //              This module defines the dojo.connect API.
162         //              This modules also provides keyboard event handling helpers.
163         //              This module exports an extension event for emulating Firefox's keypress handling.
164         //              However, this extension event exists primarily for backwards compatibility and
165         //              is not recommended. WebKit and IE uses an alternate keypress handling (only
166         //              firing for printable characters, to distinguish from keydown events), and most
167         //              consider the WebKit/IE behavior more desirable.
168
169         _keypress:keypress,
170
171         connect:function(obj, event, context, method, dontFix){
172                 // summary:
173                 //              `dojo.connect` is a deprecated event handling and delegation method in
174                 //              Dojo. It allows one function to "listen in" on the execution of
175                 //              any other, triggering the second whenever the first is called. Many
176                 //              listeners may be attached to a function, and source functions may
177                 //              be either regular function calls or DOM events.
178                 //
179                 // description:
180                 //              Connects listeners to actions, so that after event fires, a
181                 //              listener is called with the same arguments passed to the original
182                 //              function.
183                 //
184                 //              Since `dojo.connect` allows the source of events to be either a
185                 //              "regular" JavaScript function or a DOM event, it provides a uniform
186                 //              interface for listening to all the types of events that an
187                 //              application is likely to deal with though a single, unified
188                 //              interface. DOM programmers may want to think of it as
189                 //              "addEventListener for everything and anything".
190                 //
191                 //              When setting up a connection, the `event` parameter must be a
192                 //              string that is the name of the method/event to be listened for. If
193                 //              `obj` is null, `kernel.global` is assumed, meaning that connections
194                 //              to global methods are supported but also that you may inadvertently
195                 //              connect to a global by passing an incorrect object name or invalid
196                 //              reference.
197                 //
198                 //              `dojo.connect` generally is forgiving. If you pass the name of a
199                 //              function or method that does not yet exist on `obj`, connect will
200                 //              not fail, but will instead set up a stub method. Similarly, null
201                 //              arguments may simply be omitted such that fewer than 4 arguments
202                 //              may be required to set up a connection See the examples for details.
203                 //
204                 //              The return value is a handle that is needed to
205                 //              remove this connection with `dojo.disconnect`.
206                 //
207                 // obj: Object?
208                 //              The source object for the event function.
209                 //              Defaults to `kernel.global` if null.
210                 //              If obj is a DOM node, the connection is delegated
211                 //              to the DOM event manager (unless dontFix is true).
212                 //
213                 // event: String
214                 //              String name of the event function in obj.
215                 //              I.e. identifies a property `obj[event]`.
216                 //
217                 // context: Object|null
218                 //              The object that method will receive as "this".
219                 //
220                 //              If context is null and method is a function, then method
221                 //              inherits the context of event.
222                 //
223                 //              If method is a string then context must be the source
224                 //              object object for method (context[method]). If context is null,
225                 //              kernel.global is used.
226                 //
227                 // method: String|Function
228                 //              A function reference, or name of a function in context.
229                 //              The function identified by method fires after event does.
230                 //              method receives the same arguments as the event.
231                 //              See context argument comments for information on method's scope.
232                 //
233                 // dontFix: Boolean?
234                 //              If obj is a DOM node, set dontFix to true to prevent delegation
235                 //              of this connection to the DOM event manager.
236                 //
237                 // example:
238                 //              When obj.onchange(), do ui.update():
239                 //      |       dojo.connect(obj, "onchange", ui, "update");
240                 //      |       dojo.connect(obj, "onchange", ui, ui.update); // same
241                 //
242                 // example:
243                 //              Using return value for disconnect:
244                 //      |       var link = dojo.connect(obj, "onchange", ui, "update");
245                 //      |       ...
246                 //      |       dojo.disconnect(link);
247                 //
248                 // example:
249                 //              When onglobalevent executes, watcher.handler is invoked:
250                 //      |       dojo.connect(null, "onglobalevent", watcher, "handler");
251                 //
252                 // example:
253                 //              When ob.onCustomEvent executes, customEventHandler is invoked:
254                 //      |       dojo.connect(ob, "onCustomEvent", null, "customEventHandler");
255                 //      |       dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same
256                 //
257                 // example:
258                 //              When ob.onCustomEvent executes, customEventHandler is invoked
259                 //              with the same scope (this):
260                 //      |       dojo.connect(ob, "onCustomEvent", null, customEventHandler);
261                 //      |       dojo.connect(ob, "onCustomEvent", customEventHandler); // same
262                 //
263                 // example:
264                 //              When globalEvent executes, globalHandler is invoked
265                 //              with the same scope (this):
266                 //      |       dojo.connect(null, "globalEvent", null, globalHandler);
267                 //      |       dojo.connect("globalEvent", globalHandler); // same
268
269                 // normalize arguments
270                 var a=arguments, args=[], i=0;
271                 // if a[0] is a String, obj was omitted
272                 args.push(typeof a[0] == "string" ? null : a[i++], a[i++]);
273                 // if the arg-after-next is a String or Function, context was NOT omitted
274                 var a1 = a[i+1];
275                 args.push(typeof a1 == "string" || typeof a1 == "function" ? a[i++] : null, a[i++]);
276                 // absorb any additional arguments
277                 for(var l=a.length; i<l; i++){  args.push(a[i]); }
278                 return connect_.apply(this, args);
279         },
280
281         disconnect:function(handle){
282                 // summary:
283                 //              Remove a link created by dojo.connect.
284                 // description:
285                 //              Removes the connection between event and the method referenced by handle.
286                 // handle: Handle
287                 //              the return value of the dojo.connect call that created the connection.
288
289                 if(handle){
290                         handle.remove();
291                 }
292         },
293
294         subscribe:function(topic, context, method){
295                 // summary:
296                 //              Attach a listener to a named topic. The listener function is invoked whenever the
297                 //              named topic is published (see: dojo.publish).
298                 //              Returns a handle which is needed to unsubscribe this listener.
299                 // topic: String
300                 //              The topic to which to subscribe.
301                 // context: Object?
302                 //              Scope in which method will be invoked, or null for default scope.
303                 // method: String|Function
304                 //              The name of a function in context, or a function reference. This is the function that
305                 //              is invoked when topic is published.
306                 // example:
307                 //      |       dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); });
308                 //      |       dojo.publish("alerts", [ "read this", "hello world" ]);
309                 return hub.subscribe(topic, lang.hitch(context, method));
310         },
311
312         publish:function(topic, args){
313                 // summary:
314                 //              Invoke all listener method subscribed to topic.
315                 // topic: String
316                 //              The name of the topic to publish.
317                 // args: Array?
318                 //              An array of arguments. The arguments will be applied
319                 //              to each topic subscriber (as first class parameters, via apply).
320                 // example:
321                 //      |       dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
322                 //      |       dojo.publish("alerts", [ "read this", "hello world" ]);
323                 return hub.publish.apply(hub, [topic].concat(args));
324         },
325
326         connectPublisher:function(topic, obj, event){
327                 // summary:
328                 //              Ensure that every time obj.event() is called, a message is published
329                 //              on the topic. Returns a handle which can be passed to
330                 //              dojo.disconnect() to disable subsequent automatic publication on
331                 //              the topic.
332                 // topic: String
333                 //              The name of the topic to publish.
334                 // obj: Object?
335                 //              The source object for the event function. Defaults to kernel.global
336                 //              if null.
337                 // event: String
338                 //              The name of the event function in obj.
339                 //              I.e. identifies a property obj[event].
340                 // example:
341                 //      |       dojo.connectPublisher("/ajax/start", dojo, "xhrGet");
342                 var pf = function(){ connect.publish(topic, arguments); };
343                 return event ? connect.connect(obj, event, pf) : connect.connect(obj, pf); //Handle
344         },
345
346         isCopyKey: function(e){
347                 // summary:
348                 //              Checks an event for the copy key (meta on Mac, and ctrl anywhere else)
349                 // e: Event
350                 //              Event object to examine
351                 return e[evtCopyKey];   // Boolean
352         }
353 };
354
355 connect.unsubscribe = connect.disconnect;
356 /*=====
357  connect.unsubscribe = function(handle){
358          // summary:
359          //             Remove a topic listener.
360          // handle: Handle
361          //             The handle returned from a call to subscribe.
362          // example:
363          //     |       var alerter = dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
364          //     |       ...
365          //     |       dojo.unsubscribe(alerter);
366  };
367  =====*/
368
369  1  && lang.mixin(dojo, connect);
370 return connect;
371
372 });
373
374