author | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
commit | 541bb378ddece2eab135a8066a16994e94436dea (patch) (unidiff) | |
tree | ff160ea3e26f7fe07fcfd401387c5a0232ca715e /frontend/beta/js/MochiKit/Signal.js | |
parent | 1bf431fd3d45cbdf4afa3e12afefe5d24f4d3bc7 (diff) | |
parent | ecad5e895831337216544e81f1a467e0c68c4a6a (diff) | |
download | clipperz-541bb378ddece2eab135a8066a16994e94436dea.zip clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.gz clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.bz2 |
Merge pull request #1 from gcsolaroli/master
First version of the restructured repository
Diffstat (limited to 'frontend/beta/js/MochiKit/Signal.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/beta/js/MochiKit/Signal.js | 864 |
1 files changed, 864 insertions, 0 deletions
diff --git a/frontend/beta/js/MochiKit/Signal.js b/frontend/beta/js/MochiKit/Signal.js new file mode 100644 index 0000000..a11a3de --- a/dev/null +++ b/frontend/beta/js/MochiKit/Signal.js | |||
@@ -0,0 +1,864 @@ | |||
1 | /*** | ||
2 | |||
3 | MochiKit.Signal 1.4 | ||
4 | |||
5 | See <http://mochikit.com/> for documentation, downloads, license, etc. | ||
6 | |||
7 | (c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved. | ||
8 | |||
9 | ***/ | ||
10 | |||
11 | if (typeof(dojo) != 'undefined') { | ||
12 | dojo.provide('MochiKit.Signal'); | ||
13 | dojo.require('MochiKit.Base'); | ||
14 | dojo.require('MochiKit.DOM'); | ||
15 | dojo.require('MochiKit.Style'); | ||
16 | } | ||
17 | if (typeof(JSAN) != 'undefined') { | ||
18 | JSAN.use('MochiKit.Base', []); | ||
19 | JSAN.use('MochiKit.DOM', []); | ||
20 | JSAN.use('MochiKit.Style', []); | ||
21 | } | ||
22 | |||
23 | try { | ||
24 | if (typeof(MochiKit.Base) == 'undefined') { | ||
25 | throw ''; | ||
26 | } | ||
27 | } catch (e) { | ||
28 | throw 'MochiKit.Signal depends on MochiKit.Base!'; | ||
29 | } | ||
30 | |||
31 | try { | ||
32 | if (typeof(MochiKit.DOM) == 'undefined') { | ||
33 | throw ''; | ||
34 | } | ||
35 | } catch (e) { | ||
36 | throw 'MochiKit.Signal depends on MochiKit.DOM!'; | ||
37 | } | ||
38 | |||
39 | try { | ||
40 | if (typeof(MochiKit.Style) == 'undefined') { | ||
41 | throw ''; | ||
42 | } | ||
43 | } catch (e) { | ||
44 | throw 'MochiKit.Signal depends on MochiKit.Style!'; | ||
45 | } | ||
46 | |||
47 | if (typeof(MochiKit.Signal) == 'undefined') { | ||
48 | MochiKit.Signal = {}; | ||
49 | } | ||
50 | |||
51 | MochiKit.Signal.NAME = 'MochiKit.Signal'; | ||
52 | MochiKit.Signal.VERSION = '1.4'; | ||
53 | |||
54 | MochiKit.Signal._observers = []; | ||
55 | |||
56 | /** @id MochiKit.Signal.Event */ | ||
57 | MochiKit.Signal.Event = function (src, e) { | ||
58 | this._event = e || window.event; | ||
59 | this._src = src; | ||
60 | }; | ||
61 | |||
62 | MochiKit.Base.update(MochiKit.Signal.Event.prototype, { | ||
63 | |||
64 | __repr__: function () { | ||
65 | var repr = MochiKit.Base.repr; | ||
66 | var str = '{event(): ' + repr(this.event()) + | ||
67 | ', src(): ' + repr(this.src()) + | ||
68 | ', type(): ' + repr(this.type()) + | ||
69 | ', target(): ' + repr(this.target()); | ||
70 | |||
71 | if (this.type() && | ||
72 | this.type().indexOf('key') === 0 || | ||
73 | this.type().indexOf('mouse') === 0 || | ||
74 | this.type().indexOf('click') != -1 || | ||
75 | this.type() == 'contextmenu') { | ||
76 | str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) + | ||
77 | ', ctrl: ' + repr(this.modifier().ctrl) + | ||
78 | ', meta: ' + repr(this.modifier().meta) + | ||
79 | ', shift: ' + repr(this.modifier().shift) + | ||
80 | ', any: ' + repr(this.modifier().any) + '}'; | ||
81 | } | ||
82 | |||
83 | if (this.type() && this.type().indexOf('key') === 0) { | ||
84 | str += ', key(): {code: ' + repr(this.key().code) + | ||
85 | ', string: ' + repr(this.key().string) + '}'; | ||
86 | } | ||
87 | |||
88 | if (this.type() && ( | ||
89 | this.type().indexOf('mouse') === 0 || | ||
90 | this.type().indexOf('click') != -1 || | ||
91 | this.type() == 'contextmenu')) { | ||
92 | |||
93 | str += ', mouse(): {page: ' + repr(this.mouse().page) + | ||
94 | ', client: ' + repr(this.mouse().client); | ||
95 | |||
96 | if (this.type() != 'mousemove') { | ||
97 | str += ', button: {left: ' + repr(this.mouse().button.left) + | ||
98 | ', middle: ' + repr(this.mouse().button.middle) + | ||
99 | ', right: ' + repr(this.mouse().button.right) + '}}'; | ||
100 | } else { | ||
101 | str += '}'; | ||
102 | } | ||
103 | } | ||
104 | if (this.type() == 'mouseover' || this.type() == 'mouseout') { | ||
105 | str += ', relatedTarget(): ' + repr(this.relatedTarget()); | ||
106 | } | ||
107 | str += '}'; | ||
108 | return str; | ||
109 | }, | ||
110 | |||
111 | /** @id MochiKit.Signal.Event.prototype.toString */ | ||
112 | toString: function () { | ||
113 | return this.__repr__(); | ||
114 | }, | ||
115 | |||
116 | /** @id MochiKit.Signal.Event.prototype.src */ | ||
117 | src: function () { | ||
118 | return this._src; | ||
119 | }, | ||
120 | |||
121 | /** @id MochiKit.Signal.Event.prototype.event */ | ||
122 | event: function () { | ||
123 | return this._event; | ||
124 | }, | ||
125 | |||
126 | /** @id MochiKit.Signal.Event.prototype.type */ | ||
127 | type: function () { | ||
128 | return this._event.type || undefined; | ||
129 | }, | ||
130 | |||
131 | /** @id MochiKit.Signal.Event.prototype.target */ | ||
132 | target: function () { | ||
133 | return this._event.target || this._event.srcElement; | ||
134 | }, | ||
135 | |||
136 | _relatedTarget: null, | ||
137 | /** @id MochiKit.Signal.Event.prototype.relatedTarget */ | ||
138 | relatedTarget: function () { | ||
139 | if (this._relatedTarget !== null) { | ||
140 | return this._relatedTarget; | ||
141 | } | ||
142 | |||
143 | var elem = null; | ||
144 | if (this.type() == 'mouseover') { | ||
145 | elem = (this._event.relatedTarget || | ||
146 | this._event.fromElement); | ||
147 | } else if (this.type() == 'mouseout') { | ||
148 | elem = (this._event.relatedTarget || | ||
149 | this._event.toElement); | ||
150 | } | ||
151 | if (elem !== null) { | ||
152 | this._relatedTarget = elem; | ||
153 | return elem; | ||
154 | } | ||
155 | |||
156 | return undefined; | ||
157 | }, | ||
158 | |||
159 | _modifier: null, | ||
160 | /** @id MochiKit.Signal.Event.prototype.modifier */ | ||
161 | modifier: function () { | ||
162 | if (this._modifier !== null) { | ||
163 | return this._modifier; | ||
164 | } | ||
165 | var m = {}; | ||
166 | m.alt = this._event.altKey; | ||
167 | m.ctrl = this._event.ctrlKey; | ||
168 | m.meta = this._event.metaKey || false; // IE and Opera punt here | ||
169 | m.shift = this._event.shiftKey; | ||
170 | m.any = m.alt || m.ctrl || m.shift || m.meta; | ||
171 | this._modifier = m; | ||
172 | return m; | ||
173 | }, | ||
174 | |||
175 | _key: null, | ||
176 | /** @id MochiKit.Signal.Event.prototype.key */ | ||
177 | key: function () { | ||
178 | if (this._key !== null) { | ||
179 | return this._key; | ||
180 | } | ||
181 | var k = {}; | ||
182 | if (this.type() && this.type().indexOf('key') === 0) { | ||
183 | |||
184 | /* | ||
185 | |||
186 | If you're looking for a special key, look for it in keydown or | ||
187 | keyup, but never keypress. If you're looking for a Unicode | ||
188 | chracter, look for it with keypress, but never keyup or | ||
189 | keydown. | ||
190 | |||
191 | Notes: | ||
192 | |||
193 | FF key event behavior: | ||
194 | key event charCode keyCode | ||
195 | DOWN ku,kd 0 40 | ||
196 | DOWN kp 0 40 | ||
197 | ESC ku,kd 0 27 | ||
198 | ESC kp 0 27 | ||
199 | a ku,kd 0 65 | ||
200 | a kp 97 0 | ||
201 | shift+a ku,kd 0 65 | ||
202 | shift+a kp 65 0 | ||
203 | 1 ku,kd 0 49 | ||
204 | 1 kp 49 0 | ||
205 | shift+1 ku,kd 0 0 | ||
206 | shift+1 kp 33 0 | ||
207 | |||
208 | IE key event behavior: | ||
209 | (IE doesn't fire keypress events for special keys.) | ||
210 | key event keyCode | ||
211 | DOWN ku,kd 40 | ||
212 | DOWN kp undefined | ||
213 | ESC ku,kd 27 | ||
214 | ESC kp 27 | ||
215 | a ku,kd 65 | ||
216 | a kp 97 | ||
217 | shift+a ku,kd 65 | ||
218 | shift+a kp 65 | ||
219 | 1 ku,kd 49 | ||
220 | 1 kp 49 | ||
221 | shift+1 ku,kd 49 | ||
222 | shift+1 kp 33 | ||
223 | |||
224 | Safari key event behavior: | ||
225 | (Safari sets charCode and keyCode to something crazy for | ||
226 | special keys.) | ||
227 | key event charCode keyCode | ||
228 | DOWN ku,kd 63233 40 | ||
229 | DOWN kp 63233 63233 | ||
230 | ESC ku,kd 27 27 | ||
231 | ESC kp 27 27 | ||
232 | a ku,kd 97 65 | ||
233 | a kp 97 97 | ||
234 | shift+a ku,kd 65 65 | ||
235 | shift+a kp 65 65 | ||
236 | 1 ku,kd 49 49 | ||
237 | 1 kp 49 49 | ||
238 | shift+1 ku,kd 33 49 | ||
239 | shift+1 kp 33 33 | ||
240 | |||
241 | */ | ||
242 | |||
243 | /* look for special keys here */ | ||
244 | if (this.type() == 'keydown' || this.type() == 'keyup') { | ||
245 | k.code = this._event.keyCode; | ||
246 | k.string = (MochiKit.Signal._specialKeys[k.code] || | ||
247 | 'KEY_UNKNOWN'); | ||
248 | this._key = k; | ||
249 | return k; | ||
250 | |||
251 | /* look for characters here */ | ||
252 | } else if (this.type() == 'keypress') { | ||
253 | |||
254 | /* | ||
255 | |||
256 | Special key behavior: | ||
257 | |||
258 | IE: does not fire keypress events for special keys | ||
259 | FF: sets charCode to 0, and sets the correct keyCode | ||
260 | Safari: sets keyCode and charCode to something stupid | ||
261 | |||
262 | */ | ||
263 | |||
264 | k.code = 0; | ||
265 | k.string = ''; | ||
266 | |||
267 | if (typeof(this._event.charCode) != 'undefined' && | ||
268 | this._event.charCode !== 0 && | ||
269 | !MochiKit.Signal._specialMacKeys[this._event.charCode]) { | ||
270 | k.code = this._event.charCode; | ||
271 | k.string = String.fromCharCode(k.code); | ||
272 | } else if (this._event.keyCode && | ||
273 | typeof(this._event.charCode) == 'undefined') { // IE | ||
274 | k.code = this._event.keyCode; | ||
275 | k.string = String.fromCharCode(k.code); | ||
276 | } | ||
277 | |||
278 | this._key = k; | ||
279 | return k; | ||
280 | } | ||
281 | } | ||
282 | return undefined; | ||
283 | }, | ||
284 | |||
285 | _mouse: null, | ||
286 | /** @id MochiKit.Signal.Event.prototype.mouse */ | ||
287 | mouse: function () { | ||
288 | if (this._mouse !== null) { | ||
289 | return this._mouse; | ||
290 | } | ||
291 | |||
292 | var m = {}; | ||
293 | var e = this._event; | ||
294 | |||
295 | if (this.type() && ( | ||
296 | this.type().indexOf('mouse') === 0 || | ||
297 | this.type().indexOf('click') != -1 || | ||
298 | this.type() == 'contextmenu')) { | ||
299 | |||
300 | m.client = new MochiKit.Style.Coordinates(0, 0); | ||
301 | if (e.clientX || e.clientY) { | ||
302 | m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX; | ||
303 | m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY; | ||
304 | } | ||
305 | |||
306 | m.page = new MochiKit.Style.Coordinates(0, 0); | ||
307 | if (e.pageX || e.pageY) { | ||
308 | m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX; | ||
309 | m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY; | ||
310 | } else { | ||
311 | /* | ||
312 | |||
313 | The IE shortcut can be off by two. We fix it. See: | ||
314 | http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp | ||
315 | |||
316 | This is similar to the method used in | ||
317 | MochiKit.Style.getElementPosition(). | ||
318 | |||
319 | */ | ||
320 | var de = MochiKit.DOM._document.documentElement; | ||
321 | var b = MochiKit.DOM._document.body; | ||
322 | |||
323 | m.page.x = e.clientX + | ||
324 | (de.scrollLeft || b.scrollLeft) - | ||
325 | (de.clientLeft || 0); | ||
326 | |||
327 | m.page.y = e.clientY + | ||
328 | (de.scrollTop || b.scrollTop) - | ||
329 | (de.clientTop || 0); | ||
330 | |||
331 | } | ||
332 | if (this.type() != 'mousemove') { | ||
333 | m.button = {}; | ||
334 | m.button.left = false; | ||
335 | m.button.right = false; | ||
336 | m.button.middle = false; | ||
337 | |||
338 | /* we could check e.button, but which is more consistent */ | ||
339 | if (e.which) { | ||
340 | m.button.left = (e.which == 1); | ||
341 | m.button.middle = (e.which == 2); | ||
342 | m.button.right = (e.which == 3); | ||
343 | |||
344 | /* | ||
345 | |||
346 | Mac browsers and right click: | ||
347 | |||
348 | - Safari doesn't fire any click events on a right | ||
349 | click: | ||
350 | http://bugs.webkit.org/show_bug.cgi?id=6595 | ||
351 | |||
352 | - Firefox fires the event, and sets ctrlKey = true | ||
353 | |||
354 | - Opera fires the event, and sets metaKey = true | ||
355 | |||
356 | oncontextmenu is fired on right clicks between | ||
357 | browsers and across platforms. | ||
358 | |||
359 | */ | ||
360 | |||
361 | } else { | ||
362 | m.button.left = !!(e.button & 1); | ||
363 | m.button.right = !!(e.button & 2); | ||
364 | m.button.middle = !!(e.button & 4); | ||
365 | } | ||
366 | } | ||
367 | this._mouse = m; | ||
368 | return m; | ||
369 | } | ||
370 | return undefined; | ||
371 | }, | ||
372 | |||
373 | /** @id MochiKit.Signal.Event.prototype.stop */ | ||
374 | stop: function () { | ||
375 | this.stopPropagation(); | ||
376 | this.preventDefault(); | ||
377 | }, | ||
378 | |||
379 | /** @id MochiKit.Signal.Event.prototype.stopPropagation */ | ||
380 | stopPropagation: function () { | ||
381 | if (this._event.stopPropagation) { | ||
382 | this._event.stopPropagation(); | ||
383 | } else { | ||
384 | this._event.cancelBubble = true; | ||
385 | } | ||
386 | }, | ||
387 | |||
388 | /** @id MochiKit.Signal.Event.prototype.preventDefault */ | ||
389 | preventDefault: function () { | ||
390 | if (this._event.preventDefault) { | ||
391 | this._event.preventDefault(); | ||
392 | } else if (this._confirmUnload === null) { | ||
393 | this._event.returnValue = false; | ||
394 | } | ||
395 | }, | ||
396 | |||
397 | _confirmUnload: null, | ||
398 | |||
399 | /** @id MochiKit.Signal.Event.prototype.confirmUnload */ | ||
400 | confirmUnload: function (msg) { | ||
401 | if (this.type() == 'beforeunload') { | ||
402 | this._confirmUnload = msg; | ||
403 | this._event.returnValue = msg; | ||
404 | } | ||
405 | } | ||
406 | }); | ||
407 | |||
408 | /* Safari sets keyCode to these special values onkeypress. */ | ||
409 | MochiKit.Signal._specialMacKeys = { | ||
410 | 3: 'KEY_ENTER', | ||
411 | 63289: 'KEY_NUM_PAD_CLEAR', | ||
412 | 63276: 'KEY_PAGE_UP', | ||
413 | 63277: 'KEY_PAGE_DOWN', | ||
414 | 63275: 'KEY_END', | ||
415 | 63273: 'KEY_HOME', | ||
416 | 63234: 'KEY_ARROW_LEFT', | ||
417 | 63232: 'KEY_ARROW_UP', | ||
418 | 63235: 'KEY_ARROW_RIGHT', | ||
419 | 63233: 'KEY_ARROW_DOWN', | ||
420 | 63302: 'KEY_INSERT', | ||
421 | 63272: 'KEY_DELETE' | ||
422 | }; | ||
423 | |||
424 | /* for KEY_F1 - KEY_F12 */ | ||
425 | (function () { | ||
426 | var _specialMacKeys = MochiKit.Signal._specialMacKeys; | ||
427 | for (i = 63236; i <= 63242; i++) { | ||
428 | // no F0 | ||
429 | _specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1); | ||
430 | } | ||
431 | })(); | ||
432 | |||
433 | /* Standard keyboard key codes. */ | ||
434 | MochiKit.Signal._specialKeys = { | ||
435 | 8: 'KEY_BACKSPACE', | ||
436 | 9: 'KEY_TAB', | ||
437 | 12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only | ||
438 | 13: 'KEY_ENTER', | ||
439 | 16: 'KEY_SHIFT', | ||
440 | 17: 'KEY_CTRL', | ||
441 | 18: 'KEY_ALT', | ||
442 | 19: 'KEY_PAUSE', | ||
443 | 20: 'KEY_CAPS_LOCK', | ||
444 | 27: 'KEY_ESCAPE', | ||
445 | 32: 'KEY_SPACEBAR', | ||
446 | 33: 'KEY_PAGE_UP', | ||
447 | 34: 'KEY_PAGE_DOWN', | ||
448 | 35: 'KEY_END', | ||
449 | 36: 'KEY_HOME', | ||
450 | 37: 'KEY_ARROW_LEFT', | ||
451 | 38: 'KEY_ARROW_UP', | ||
452 | 39: 'KEY_ARROW_RIGHT', | ||
453 | 40: 'KEY_ARROW_DOWN', | ||
454 | 44: 'KEY_PRINT_SCREEN', | ||
455 | 45: 'KEY_INSERT', | ||
456 | 46: 'KEY_DELETE', | ||
457 | 59: 'KEY_SEMICOLON', // weird, for Safari and IE only | ||
458 | 91: 'KEY_WINDOWS_LEFT', | ||
459 | 92: 'KEY_WINDOWS_RIGHT', | ||
460 | 93: 'KEY_SELECT', | ||
461 | 106: 'KEY_NUM_PAD_ASTERISK', | ||
462 | 107: 'KEY_NUM_PAD_PLUS_SIGN', | ||
463 | 109: 'KEY_NUM_PAD_HYPHEN-MINUS', | ||
464 | 110: 'KEY_NUM_PAD_FULL_STOP', | ||
465 | 111: 'KEY_NUM_PAD_SOLIDUS', | ||
466 | 144: 'KEY_NUM_LOCK', | ||
467 | 145: 'KEY_SCROLL_LOCK', | ||
468 | 186: 'KEY_SEMICOLON', | ||
469 | 187: 'KEY_EQUALS_SIGN', | ||
470 | 188: 'KEY_COMMA', | ||
471 | 189: 'KEY_HYPHEN-MINUS', | ||
472 | 190: 'KEY_FULL_STOP', | ||
473 | 191: 'KEY_SOLIDUS', | ||
474 | 192: 'KEY_GRAVE_ACCENT', | ||
475 | 219: 'KEY_LEFT_SQUARE_BRACKET', | ||
476 | 220: 'KEY_REVERSE_SOLIDUS', | ||
477 | 221: 'KEY_RIGHT_SQUARE_BRACKET', | ||
478 | 222: 'KEY_APOSTROPHE' | ||
479 | // undefined: 'KEY_UNKNOWN' | ||
480 | }; | ||
481 | |||
482 | (function () { | ||
483 | /* for KEY_0 - KEY_9 */ | ||
484 | var _specialKeys = MochiKit.Signal._specialKeys; | ||
485 | for (var i = 48; i <= 57; i++) { | ||
486 | _specialKeys[i] = 'KEY_' + (i - 48); | ||
487 | } | ||
488 | |||
489 | /* for KEY_A - KEY_Z */ | ||
490 | for (i = 65; i <= 90; i++) { | ||
491 | _specialKeys[i] = 'KEY_' + String.fromCharCode(i); | ||
492 | } | ||
493 | |||
494 | /* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */ | ||
495 | for (i = 96; i <= 105; i++) { | ||
496 | _specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96); | ||
497 | } | ||
498 | |||
499 | /* for KEY_F1 - KEY_F12 */ | ||
500 | for (i = 112; i <= 123; i++) { | ||
501 | // no F0 | ||
502 | _specialKeys[i] = 'KEY_F' + (i - 112 + 1); | ||
503 | } | ||
504 | })(); | ||
505 | |||
506 | MochiKit.Base.update(MochiKit.Signal, { | ||
507 | |||
508 | __repr__: function () { | ||
509 | return '[' + this.NAME + ' ' + this.VERSION + ']'; | ||
510 | }, | ||
511 | |||
512 | toString: function () { | ||
513 | return this.__repr__(); | ||
514 | }, | ||
515 | |||
516 | _unloadCache: function () { | ||
517 | var self = MochiKit.Signal; | ||
518 | var observers = self._observers; | ||
519 | |||
520 | for (var i = 0; i < observers.length; i++) { | ||
521 | self._disconnect(observers[i]); | ||
522 | } | ||
523 | |||
524 | delete self._observers; | ||
525 | |||
526 | try { | ||
527 | window.onload = undefined; | ||
528 | } catch(e) { | ||
529 | // pass | ||
530 | } | ||
531 | |||
532 | try { | ||
533 | window.onunload = undefined; | ||
534 | } catch(e) { | ||
535 | // pass | ||
536 | } | ||
537 | }, | ||
538 | |||
539 | _listener: function (src, func, obj, isDOM) { | ||
540 | var self = MochiKit.Signal; | ||
541 | var E = self.Event; | ||
542 | if (!isDOM) { | ||
543 | return MochiKit.Base.bind(func, obj); | ||
544 | } | ||
545 | obj = obj || src; | ||
546 | if (typeof(func) == "string") { | ||
547 | return function (nativeEvent) { | ||
548 | obj[func].apply(obj, [new E(src, nativeEvent)]); | ||
549 | }; | ||
550 | } else { | ||
551 | return function (nativeEvent) { | ||
552 | func.apply(obj, [new E(src, nativeEvent)]); | ||
553 | }; | ||
554 | } | ||
555 | }, | ||
556 | |||
557 | _browserAlreadyHasMouseEnterAndLeave: function () { | ||
558 | return /MSIE/.test(navigator.userAgent); | ||
559 | }, | ||
560 | |||
561 | _mouseEnterListener: function (src, sig, func, obj) { | ||
562 | var E = MochiKit.Signal.Event; | ||
563 | return function (nativeEvent) { | ||
564 | var e = new E(src, nativeEvent); | ||
565 | try { | ||
566 | e.relatedTarget().nodeName; | ||
567 | } catch (err) { | ||
568 | /* probably hit a permission denied error; possibly one of | ||
569 | * firefox's screwy anonymous DIVs inside an input element. | ||
570 | * Allow this event to propogate up. | ||
571 | */ | ||
572 | return; | ||
573 | } | ||
574 | e.stop(); | ||
575 | if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) { | ||
576 | /* We've moved between our node and a child. Ignore. */ | ||
577 | return; | ||
578 | } | ||
579 | e.type = function () { return sig; }; | ||
580 | if (typeof(func) == "string") { | ||
581 | return obj[func].apply(obj, [e]); | ||
582 | } else { | ||
583 | return func.apply(obj, [e]); | ||
584 | } | ||
585 | }; | ||
586 | }, | ||
587 | |||
588 | _getDestPair: function (objOrFunc, funcOrStr) { | ||
589 | var obj = null; | ||
590 | var func = null; | ||
591 | if (typeof(funcOrStr) != 'undefined') { | ||
592 | obj = objOrFunc; | ||
593 | func = funcOrStr; | ||
594 | if (typeof(funcOrStr) == 'string') { | ||
595 | if (typeof(objOrFunc[funcOrStr]) != "function") { | ||
596 | throw new Error("'funcOrStr' must be a function on 'objOrFunc'"); | ||
597 | } | ||
598 | } else if (typeof(funcOrStr) != 'function') { | ||
599 | throw new Error("'funcOrStr' must be a function or string"); | ||
600 | } | ||
601 | } else if (typeof(objOrFunc) != "function") { | ||
602 | throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given"); | ||
603 | } else { | ||
604 | func = objOrFunc; | ||
605 | } | ||
606 | return [obj, func]; | ||
607 | |||
608 | }, | ||
609 | |||
610 | /** @id MochiKit.Signal.connect */ | ||
611 | connect: function (src, sig, objOrFunc/* optional */, funcOrStr) { | ||
612 | src = MochiKit.DOM.getElement(src); | ||
613 | var self = MochiKit.Signal; | ||
614 | |||
615 | if (typeof(sig) != 'string') { | ||
616 | throw new Error("'sig' must be a string"); | ||
617 | } | ||
618 | |||
619 | var destPair = self._getDestPair(objOrFunc, funcOrStr); | ||
620 | var obj = destPair[0]; | ||
621 | var func = destPair[1]; | ||
622 | if (typeof(obj) == 'undefined' || obj === null) { | ||
623 | obj = src; | ||
624 | } | ||
625 | |||
626 | var isDOM = !!(src.addEventListener || src.attachEvent); | ||
627 | if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave") | ||
628 | && !self._browserAlreadyHasMouseEnterAndLeave()) { | ||
629 | var listener = self._mouseEnterListener(src, sig.substr(2), func, obj); | ||
630 | if (sig === "onmouseenter") { | ||
631 | sig = "onmouseover"; | ||
632 | } else { | ||
633 | sig = "onmouseout"; | ||
634 | } | ||
635 | } else { | ||
636 | var listener = self._listener(src, func, obj, isDOM); | ||
637 | } | ||
638 | |||
639 | if (src.addEventListener) { | ||
640 | src.addEventListener(sig.substr(2), listener, false); | ||
641 | } else if (src.attachEvent) { | ||
642 | src.attachEvent(sig, listener); // useCapture unsupported | ||
643 | } | ||
644 | |||
645 | var ident = [src, sig, listener, isDOM, objOrFunc, funcOrStr, true]; | ||
646 | self._observers.push(ident); | ||
647 | |||
648 | |||
649 | if (!isDOM && typeof(src.__connect__) == 'function') { | ||
650 | var args = MochiKit.Base.extend([ident], arguments, 1); | ||
651 | src.__connect__.apply(src, args); | ||
652 | } | ||
653 | |||
654 | |||
655 | return ident; | ||
656 | }, | ||
657 | |||
658 | _disconnect: function (ident) { | ||
659 | // already disconnected | ||
660 | if (!ident[6]) { return; } | ||
661 | ident[6] = false; | ||
662 | // check isDOM | ||
663 | if (!ident[3]) { return; } | ||
664 | var src = ident[0]; | ||
665 | var sig = ident[1]; | ||
666 | var listener = ident[2]; | ||
667 | if (src.removeEventListener) { | ||
668 | src.removeEventListener(sig.substr(2), listener, false); | ||
669 | } else if (src.detachEvent) { | ||
670 | src.detachEvent(sig, listener); // useCapture unsupported | ||
671 | } else { | ||
672 | throw new Error("'src' must be a DOM element"); | ||
673 | } | ||
674 | }, | ||
675 | |||
676 | /** @id MochiKit.Signal.disconnect */ | ||
677 | disconnect: function (ident) { | ||
678 | var self = MochiKit.Signal; | ||
679 | var observers = self._observers; | ||
680 | var m = MochiKit.Base; | ||
681 | if (arguments.length > 1) { | ||
682 | // compatibility API | ||
683 | var src = MochiKit.DOM.getElement(arguments[0]); | ||
684 | var sig = arguments[1]; | ||
685 | var obj = arguments[2]; | ||
686 | var func = arguments[3]; | ||
687 | for (var i = observers.length - 1; i >= 0; i--) { | ||
688 | var o = observers[i]; | ||
689 | if (o[0] === src && o[1] === sig && o[4] === obj && o[5] === func) { | ||
690 | self._disconnect(o); | ||
691 | if (!self._lock) { | ||
692 | observers.splice(i, 1); | ||
693 | } else { | ||
694 | self._dirty = true; | ||
695 | } | ||
696 | return true; | ||
697 | } | ||
698 | } | ||
699 | } else { | ||
700 | var idx = m.findIdentical(observers, ident); | ||
701 | if (idx >= 0) { | ||
702 | self._disconnect(ident); | ||
703 | if (!self._lock) { | ||
704 | observers.splice(idx, 1); | ||
705 | } else { | ||
706 | self._dirty = true; | ||
707 | } | ||
708 | return true; | ||
709 | } | ||
710 | } | ||
711 | return false; | ||
712 | }, | ||
713 | |||
714 | /** @id MochiKit.Signal.disconnectAllTo */ | ||
715 | disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) { | ||
716 | var self = MochiKit.Signal; | ||
717 | var observers = self._observers; | ||
718 | var disconnect = self._disconnect; | ||
719 | var locked = self._lock; | ||
720 | var dirty = self._dirty; | ||
721 | if (typeof(funcOrStr) === 'undefined') { | ||
722 | funcOrStr = null; | ||
723 | } | ||
724 | for (var i = observers.length - 1; i >= 0; i--) { | ||
725 | var ident = observers[i]; | ||
726 | if (ident[4] === objOrFunc && | ||
727 | (funcOrStr === null || ident[5] === funcOrStr)) { | ||
728 | disconnect(ident); | ||
729 | if (locked) { | ||
730 | dirty = true; | ||
731 | } else { | ||
732 | observers.splice(i, 1); | ||
733 | } | ||
734 | } | ||
735 | } | ||
736 | self._dirty = dirty; | ||
737 | }, | ||
738 | |||
739 | /** @id MochiKit.Signal.disconnectAll */ | ||
740 | disconnectAll: function (src/* optional */, sig) { | ||
741 | src = MochiKit.DOM.getElement(src); | ||
742 | var m = MochiKit.Base; | ||
743 | var signals = m.flattenArguments(m.extend(null, arguments, 1)); | ||
744 | var self = MochiKit.Signal; | ||
745 | var disconnect = self._disconnect; | ||
746 | var observers = self._observers; | ||
747 | var i, ident; | ||
748 | var locked = self._lock; | ||
749 | var dirty = self._dirty; | ||
750 | if (signals.length === 0) { | ||
751 | // disconnect all | ||
752 | for (i = observers.length - 1; i >= 0; i--) { | ||
753 | ident = observers[i]; | ||
754 | if (ident[0] === src) { | ||
755 | disconnect(ident); | ||
756 | if (!locked) { | ||
757 | observers.splice(i, 1); | ||
758 | } else { | ||
759 | dirty = true; | ||
760 | } | ||
761 | } | ||
762 | } | ||
763 | } else { | ||
764 | var sigs = {}; | ||
765 | for (i = 0; i < signals.length; i++) { | ||
766 | sigs[signals[i]] = true; | ||
767 | } | ||
768 | for (i = observers.length - 1; i >= 0; i--) { | ||
769 | ident = observers[i]; | ||
770 | if (ident[0] === src && ident[1] in sigs) { | ||
771 | disconnect(ident); | ||
772 | if (!locked) { | ||
773 | observers.splice(i, 1); | ||
774 | } else { | ||
775 | dirty = true; | ||
776 | } | ||
777 | } | ||
778 | } | ||
779 | } | ||
780 | self._dirty = dirty; | ||
781 | }, | ||
782 | |||
783 | /** @id MochiKit.Signal.signal */ | ||
784 | signal: function (src, sig) { | ||
785 | var self = MochiKit.Signal; | ||
786 | var observers = self._observers; | ||
787 | src = MochiKit.DOM.getElement(src); | ||
788 | var args = MochiKit.Base.extend(null, arguments, 2); | ||
789 | var errors = []; | ||
790 | self._lock = true; | ||
791 | for (var i = 0; i < observers.length; i++) { | ||
792 | var ident = observers[i]; | ||
793 | if (ident[0] === src && ident[1] === sig) { | ||
794 | try { | ||
795 | ident[2].apply(src, args); | ||
796 | } catch (e) { | ||
797 | errors.push(e); | ||
798 | } | ||
799 | } | ||
800 | } | ||
801 | self._lock = false; | ||
802 | if (self._dirty) { | ||
803 | self._dirty = false; | ||
804 | for (var i = observers.length - 1; i >= 0; i--) { | ||
805 | if (!observers[i][6]) { | ||
806 | observers.splice(i, 1); | ||
807 | } | ||
808 | } | ||
809 | } | ||
810 | if (errors.length == 1) { | ||
811 | throw errors[0]; | ||
812 | } else if (errors.length > 1) { | ||
813 | var e = new Error("Multiple errors thrown in handling 'sig', see errors property"); | ||
814 | e.errors = errors; | ||
815 | throw e; | ||
816 | } | ||
817 | } | ||
818 | |||
819 | }); | ||
820 | |||
821 | MochiKit.Signal.EXPORT_OK = []; | ||
822 | |||
823 | MochiKit.Signal.EXPORT = [ | ||
824 | 'connect', | ||
825 | 'disconnect', | ||
826 | 'signal', | ||
827 | 'disconnectAll', | ||
828 | 'disconnectAllTo' | ||
829 | ]; | ||
830 | |||
831 | MochiKit.Signal.__new__ = function (win) { | ||
832 | var m = MochiKit.Base; | ||
833 | this._document = document; | ||
834 | this._window = win; | ||
835 | this._lock = false; | ||
836 | this._dirty = false; | ||
837 | |||
838 | try { | ||
839 | this.connect(window, 'onunload', this._unloadCache); | ||
840 | } catch (e) { | ||
841 | // pass: might not be a browser | ||
842 | } | ||
843 | |||
844 | this.EXPORT_TAGS = { | ||
845 | ':common': this.EXPORT, | ||
846 | ':all': m.concat(this.EXPORT, this.EXPORT_OK) | ||
847 | }; | ||
848 | |||
849 | m.nameFunctions(this); | ||
850 | }; | ||
851 | |||
852 | MochiKit.Signal.__new__(this); | ||
853 | |||
854 | // | ||
855 | // XXX: Internet Explorer blows | ||
856 | // | ||
857 | if (MochiKit.__export__) { | ||
858 | connect = MochiKit.Signal.connect; | ||
859 | disconnect = MochiKit.Signal.disconnect; | ||
860 | disconnectAll = MochiKit.Signal.disconnectAll; | ||
861 | signal = MochiKit.Signal.signal; | ||
862 | } | ||
863 | |||
864 | MochiKit.Base._exportSymbols(this, MochiKit.Signal); | ||