]> git.wh0rd.org - 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