Diffstat (limited to 'frontend/gamma/js/MochiKit/Signal.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/gamma/js/MochiKit/Signal.js | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/frontend/gamma/js/MochiKit/Signal.js b/frontend/gamma/js/MochiKit/Signal.js index 7df5619..11590c1 100644 --- a/frontend/gamma/js/MochiKit/Signal.js +++ b/frontend/gamma/js/MochiKit/Signal.js @@ -1,59 +1,59 @@ /*** MochiKit.Signal 1.5 See <http://mochikit.com/> for documentation, downloads, license, etc. (c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved. ***/ -MochiKit.Base._module('Signal', '1.5', ['Base', 'DOM', 'Style']); +MochiKit.Base.module(MochiKit, 'Signal', '1.5', ['Base', 'DOM']); MochiKit.Signal._observers = []; /** @id MochiKit.Signal.Event */ MochiKit.Signal.Event = function (src, e) { this._event = e || window.event; this._src = src; }; MochiKit.Signal.Event.__export__ = false; MochiKit.Base.update(MochiKit.Signal.Event.prototype, { __repr__: function () { var repr = MochiKit.Base.repr; var str = '{event(): ' + repr(this.event()) + ', src(): ' + repr(this.src()) + ', type(): ' + repr(this.type()) + ', target(): ' + repr(this.target()); if (this.type() && this.type().indexOf('key') === 0 || this.type().indexOf('mouse') === 0 || this.type().indexOf('click') != -1 || this.type() == 'contextmenu') { str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) + ', ctrl: ' + repr(this.modifier().ctrl) + ', meta: ' + repr(this.modifier().meta) + ', shift: ' + repr(this.modifier().shift) + ', any: ' + repr(this.modifier().any) + '}'; } if (this.type() && this.type().indexOf('key') === 0) { str += ', key(): {code: ' + repr(this.key().code) + ', string: ' + repr(this.key().string) + '}'; } if (this.type() && ( this.type().indexOf('mouse') === 0 || this.type().indexOf('click') != -1 || this.type() == 'contextmenu')) { str += ', mouse(): {page: ' + repr(this.mouse().page) + ', client: ' + repr(this.mouse().client); if (this.type() != 'mousemove' && this.type() != 'mousewheel') { str += ', button: {left: ' + repr(this.mouse().button.left) + ', middle: ' + repr(this.mouse().button.middle) + ', right: ' + repr(this.mouse().button.right) + '}'; @@ -221,168 +221,169 @@ MochiKit.Base.update(MochiKit.Signal.Event.prototype, { return k; /* look for characters here */ } else if (this.type() == 'keypress') { /* Special key behavior: IE: does not fire keypress events for special keys FF: sets charCode to 0, and sets the correct keyCode Safari: sets keyCode and charCode to something stupid */ k.code = 0; k.string = ''; if (typeof(this._event.charCode) != 'undefined' && this._event.charCode !== 0 && !MochiKit.Signal._specialMacKeys[this._event.charCode]) { k.code = this._event.charCode; k.string = String.fromCharCode(k.code); } else if (this._event.keyCode && typeof(this._event.charCode) == 'undefined') { // IE k.code = this._event.keyCode; k.string = String.fromCharCode(k.code); } this._key = k; return k; } } return undefined; }, _mouse: null, /** @id MochiKit.Signal.Event.prototype.mouse */ mouse: function () { if (this._mouse !== null) { return this._mouse; } var m = {}; var e = this._event; if (this.type() && ( this.type().indexOf('mouse') === 0 || + this.type().indexOf('drag') === 0 || this.type().indexOf('click') != -1 || this.type() == 'contextmenu')) { - m.client = new MochiKit.Style.Coordinates(0, 0); + m.client = { x: 0, y: 0 }; if (e.clientX || e.clientY) { m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX; m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY; } - m.page = new MochiKit.Style.Coordinates(0, 0); + m.page = { x: 0, y: 0 }; if (e.pageX || e.pageY) { m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX; m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY; } else { /* The IE shortcut can be off by two. We fix it. See: http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp This is similar to the method used in MochiKit.Style.getElementPosition(). */ var de = MochiKit.DOM._document.documentElement; var b = MochiKit.DOM._document.body; m.page.x = e.clientX + (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0); m.page.y = e.clientY + (de.scrollTop || b.scrollTop) - (de.clientTop || 0); } if (this.type() != 'mousemove' && this.type() != 'mousewheel') { m.button = {}; m.button.left = false; m.button.right = false; m.button.middle = false; /* we could check e.button, but which is more consistent */ if (e.which) { m.button.left = (e.which == 1); m.button.middle = (e.which == 2); m.button.right = (e.which == 3); /* Mac browsers and right click: - Safari doesn't fire any click events on a right click: http://bugs.webkit.org/show_bug.cgi?id=6595 - Firefox fires the event, and sets ctrlKey = true - Opera fires the event, and sets metaKey = true oncontextmenu is fired on right clicks between browsers and across platforms. */ } else { m.button.left = !!(e.button & 1); m.button.right = !!(e.button & 2); m.button.middle = !!(e.button & 4); } } if (this.type() == 'mousewheel') { - m.wheel = new MochiKit.Style.Coordinates(0, 0); + m.wheel = { x: 0, y: 0 }; if (e.wheelDeltaX || e.wheelDeltaY) { m.wheel.x = e.wheelDeltaX / -40 || 0; m.wheel.y = e.wheelDeltaY / -40 || 0; } else if (e.wheelDelta) { m.wheel.y = e.wheelDelta / -40; } else { m.wheel.y = e.detail || 0; } } this._mouse = m; return m; } return undefined; }, /** @id MochiKit.Signal.Event.prototype.stop */ stop: function () { this.stopPropagation(); this.preventDefault(); }, /** @id MochiKit.Signal.Event.prototype.stopPropagation */ stopPropagation: function () { if (this._event.stopPropagation) { this._event.stopPropagation(); } else { this._event.cancelBubble = true; } }, /** @id MochiKit.Signal.Event.prototype.preventDefault */ preventDefault: function () { if (this._event.preventDefault) { this._event.preventDefault(); } else if (this._confirmUnload === null) { this._event.returnValue = false; } }, _confirmUnload: null, /** @id MochiKit.Signal.Event.prototype.confirmUnload */ confirmUnload: function (msg) { if (this.type() == 'beforeunload') { this._confirmUnload = msg; this._event.returnValue = msg; } } @@ -627,262 +628,274 @@ MochiKit.Base.update(MochiKit.Signal, { var destPair = self._getDestPair(objOrFunc, funcOrStr); var obj = destPair[0]; var func = destPair[1]; if (typeof(obj) == 'undefined' || obj === null) { obj = src; } var isDOM = !!(src.addEventListener || src.attachEvent); if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave") && !self._browserAlreadyHasMouseEnterAndLeave()) { var listener = self._mouseEnterListener(src, sig.substr(2), func, obj); if (sig === "onmouseenter") { sig = "onmouseover"; } else { sig = "onmouseout"; } } else if (isDOM && sig == "onmousewheel" && self._browserLacksMouseWheelEvent()) { var listener = self._listener(src, sig, func, obj, isDOM); sig = "onDOMMouseScroll"; } else { var listener = self._listener(src, sig, func, obj, isDOM); } if (src.addEventListener) { src.addEventListener(sig.substr(2), listener, false); } else if (src.attachEvent) { src.attachEvent(sig, listener); // useCapture unsupported } var ident = new MochiKit.Signal.Ident({ source: src, signal: sig, listener: listener, isDOM: isDOM, objOrFunc: objOrFunc, funcOrStr: funcOrStr, connected: true }); self._observers.push(ident); if (!isDOM && typeof(src.__connect__) == 'function') { var args = MochiKit.Base.extend([ident], arguments, 1); src.__connect__.apply(src, args); } return ident; }, + /** @id MochiKit.Signal.connectOnce */ + connectOnce: function (src, sig, objOrFunc/* optional */, funcOrStr) { + var self = MochiKit.Signal; + var ident1 = self.connect(src, sig, objOrFunc, funcOrStr); + var ident2; + ident2 = self.connect(src, sig, function() { + self.disconnect(ident1); + self.disconnect(ident2); + }); + return ident1; + }, + _disconnect: function (ident) { // already disconnected if (!ident.connected) { return; } ident.connected = false; var src = ident.source; var sig = ident.signal; var listener = ident.listener; // check isDOM if (!ident.isDOM) { if (typeof(src.__disconnect__) == 'function') { src.__disconnect__(ident, sig, ident.objOrFunc, ident.funcOrStr); } return; } if (src.removeEventListener) { src.removeEventListener(sig.substr(2), listener, false); } else if (src.detachEvent) { src.detachEvent(sig, listener); // useCapture unsupported } else { throw new Error("'src' must be a DOM element"); } }, /** @id MochiKit.Signal.disconnect */ disconnect: function (ident) { var self = MochiKit.Signal; var observers = self._observers; var m = MochiKit.Base; if (arguments.length > 1) { // compatibility API var src = arguments[0]; if (typeof(src) == "string") { src = MochiKit.DOM.getElement(src); } var sig = arguments[1]; var obj = arguments[2]; var func = arguments[3]; for (var i = observers.length - 1; i >= 0; i--) { var o = observers[i]; if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) { self._disconnect(o); - if (!self._lock) { + if (self._lock === 0) { observers.splice(i, 1); } else { self._dirty = true; } return true; } } } else { var idx = m.findIdentical(observers, ident); if (idx >= 0) { self._disconnect(ident); - if (!self._lock) { + if (self._lock === 0) { observers.splice(idx, 1); } else { self._dirty = true; } return true; } } return false; }, /** @id MochiKit.Signal.disconnectAllTo */ disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) { var self = MochiKit.Signal; var observers = self._observers; var disconnect = self._disconnect; - var locked = self._lock; + var lock = self._lock; var dirty = self._dirty; if (typeof(funcOrStr) === 'undefined') { funcOrStr = null; } for (var i = observers.length - 1; i >= 0; i--) { var ident = observers[i]; if (ident.objOrFunc === objOrFunc && (funcOrStr === null || ident.funcOrStr === funcOrStr)) { disconnect(ident); - if (locked) { - dirty = true; - } else { + if (lock === 0) { observers.splice(i, 1); + } else { + dirty = true; } } } self._dirty = dirty; }, /** @id MochiKit.Signal.disconnectAll */ disconnectAll: function (src/* optional */, sig) { if (typeof(src) == "string") { src = MochiKit.DOM.getElement(src); } var m = MochiKit.Base; var signals = m.flattenArguments(m.extend(null, arguments, 1)); var self = MochiKit.Signal; var disconnect = self._disconnect; var observers = self._observers; var i, ident; - var locked = self._lock; + var lock = self._lock; var dirty = self._dirty; if (signals.length === 0) { // disconnect all for (i = observers.length - 1; i >= 0; i--) { ident = observers[i]; if (ident.source === src) { disconnect(ident); - if (!locked) { + if (lock === 0) { observers.splice(i, 1); } else { dirty = true; } } } } else { var sigs = {}; for (i = 0; i < signals.length; i++) { sigs[signals[i]] = true; } for (i = observers.length - 1; i >= 0; i--) { ident = observers[i]; if (ident.source === src && ident.signal in sigs) { disconnect(ident); - if (!locked) { + if (lock === 0) { observers.splice(i, 1); } else { dirty = true; } } } } self._dirty = dirty; }, /** @id MochiKit.Signal.signal */ signal: function (src, sig) { var self = MochiKit.Signal; var observers = self._observers; if (typeof(src) == "string") { src = MochiKit.DOM.getElement(src); } var args = MochiKit.Base.extend(null, arguments, 2); var errors = []; - self._lock = true; + self._lock++; for (var i = 0; i < observers.length; i++) { var ident = observers[i]; if (ident.source === src && ident.signal === sig && ident.connected) { try { if (ident.isDOM && ident.funcOrStr != null) { var obj = ident.objOrFunc; obj[ident.funcOrStr].apply(obj, args); } else if (ident.isDOM) { ident.objOrFunc.apply(src, args); } else { ident.listener.apply(src, args); } } catch (e) { errors.push(e); } } } - self._lock = false; - if (self._dirty) { + self._lock--; + if (self._lock === 0 && self._dirty) { self._dirty = false; for (var i = observers.length - 1; i >= 0; i--) { if (!observers[i].connected) { observers.splice(i, 1); } } } if (errors.length == 1) { throw errors[0]; } else if (errors.length > 1) { var e = new Error("Multiple errors thrown in handling 'sig', see errors property"); e.errors = errors; throw e; } } }); MochiKit.Signal.__new__ = function (win) { var m = MochiKit.Base; this._document = document; this._window = win; - this._lock = false; + this._lock = 0; this._dirty = false; try { this.connect(window, 'onunload', this._unloadCache); } catch (e) { // pass: might not be a browser } m.nameFunctions(this); }; MochiKit.Signal.__new__(this); // // XXX: Internet Explorer blows // if (MochiKit.__export__) { connect = MochiKit.Signal.connect; disconnect = MochiKit.Signal.disconnect; disconnectAll = MochiKit.Signal.disconnectAll; signal = MochiKit.Signal.signal; } MochiKit.Base._exportSymbols(this, MochiKit.Signal); |