| 50 | | MochiKit.Signal.Event.prototype.event = function () { |
|---|
| 51 | | return this._event; |
|---|
| 52 | | }; |
|---|
| 53 | | |
|---|
| 54 | | MochiKit.Signal.Event.prototype.type = function () { |
|---|
| 55 | | return this._event.type || undefined; |
|---|
| 56 | | }; |
|---|
| 57 | | |
|---|
| 58 | | MochiKit.Signal.Event.prototype.target = function () { |
|---|
| 59 | | return this._event.target || this._event.srcElement; |
|---|
| 60 | | }; |
|---|
| 61 | | |
|---|
| 62 | | MochiKit.Signal.Event.prototype.relatedTarget = function () { |
|---|
| 63 | | if (this.type() == 'mouseover') { |
|---|
| 64 | | return (this._event.relatedTarget || |
|---|
| 65 | | this._event.fromElement); |
|---|
| 66 | | } else if (this.type() == 'mouseout') { |
|---|
| 67 | | return (this._event.relatedTarget || |
|---|
| 68 | | this._event.toElement); |
|---|
| | 50 | MochiKit.Base.update(MochiKit.Signal.Event.prototype, { |
|---|
| | 51 | |
|---|
| | 52 | _fixPoint: function (point) { |
|---|
| | 53 | /* |
|---|
| | 54 | |
|---|
| | 55 | FIXME: inline this to avoid funciton call overhead? Does JS have |
|---|
| | 56 | function call overhead? This code needs test coverage. |
|---|
| | 57 | |
|---|
| | 58 | */ |
|---|
| | 59 | if (typeof(point) == 'undefined' || point < 0) { |
|---|
| | 60 | return 0; |
|---|
| | 61 | } |
|---|
| | 62 | return point; |
|---|
| | 63 | }, |
|---|
| | 64 | |
|---|
| | 65 | event: function () { |
|---|
| | 66 | return this._event; |
|---|
| | 67 | }, |
|---|
| | 68 | |
|---|
| | 69 | type: function () { |
|---|
| | 70 | return this._event.type || undefined; |
|---|
| | 71 | }, |
|---|
| | 72 | |
|---|
| | 73 | target: function () { |
|---|
| | 74 | return this._event.target || this._event.srcElement; |
|---|
| | 75 | }, |
|---|
| | 76 | |
|---|
| | 77 | relatedTarget: function () { |
|---|
| | 78 | if (this.type() == 'mouseover') { |
|---|
| | 79 | return (this._event.relatedTarget || |
|---|
| | 80 | this._event.fromElement); |
|---|
| | 81 | } else if (this.type() == 'mouseout') { |
|---|
| | 82 | return (this._event.relatedTarget || |
|---|
| | 83 | this._event.toElement); |
|---|
| | 84 | } |
|---|
| | 85 | throw new Error('No related target'); |
|---|
| | 86 | }, |
|---|
| | 87 | |
|---|
| | 88 | modifier: function () { |
|---|
| | 89 | var m = {}; |
|---|
| | 90 | m.alt = this._event.altKey; |
|---|
| | 91 | m.ctrl = this._event.ctrlKey; |
|---|
| | 92 | m.meta = this._event.metaKey || false; // ie and opera punt here |
|---|
| | 93 | m.shift = this._event.shiftKey; |
|---|
| | 94 | return m; |
|---|
| | 95 | }, |
|---|
| | 96 | |
|---|
| | 97 | key: function () { |
|---|
| | 98 | var k = {}; |
|---|
| | 99 | if (this.type() && this.type().indexOf('key') === 0) { |
|---|
| | 100 | |
|---|
| | 101 | /* |
|---|
| | 102 | |
|---|
| | 103 | If you're looking for a special key, look for it in keydown or |
|---|
| | 104 | keyup, but never keypress. If you're looking for a Unicode |
|---|
| | 105 | chracter, look for it with keypress, but never keyup or |
|---|
| | 106 | keydown. |
|---|
| | 107 | |
|---|
| | 108 | Notes: |
|---|
| | 109 | |
|---|
| | 110 | FF key event behavior: |
|---|
| | 111 | key event charCode keyCode |
|---|
| | 112 | DOWN ku,kd 0 40 |
|---|
| | 113 | DOWN kp 0 40 |
|---|
| | 114 | ESC ku,kd 0 27 |
|---|
| | 115 | ESC kp 0 27 |
|---|
| | 116 | a ku,kd 0 65 |
|---|
| | 117 | a kp 97 0 |
|---|
| | 118 | shift+a ku,kd 0 65 |
|---|
| | 119 | shift+a kp 65 0 |
|---|
| | 120 | 1 ku,kd 0 49 |
|---|
| | 121 | 1 kp 49 0 |
|---|
| | 122 | shift+1 ku,kd 0 0 |
|---|
| | 123 | shift+1 kp 33 0 |
|---|
| | 124 | |
|---|
| | 125 | IE key event behavior: |
|---|
| | 126 | (IE doesn't fire keypress events for special keys.) |
|---|
| | 127 | key event keyCode |
|---|
| | 128 | DOWN ku,kd 40 |
|---|
| | 129 | DOWN kp undefined |
|---|
| | 130 | ESC ku,kd 27 |
|---|
| | 131 | ESC kp 27 |
|---|
| | 132 | a ku,kd 65 |
|---|
| | 133 | a kp 97 |
|---|
| | 134 | shift+a ku,kd 65 |
|---|
| | 135 | shift+a kp 65 |
|---|
| | 136 | 1 ku,kd 49 |
|---|
| | 137 | 1 kp 49 |
|---|
| | 138 | shift+1 ku,kd 49 |
|---|
| | 139 | shift+1 kp 33 |
|---|
| | 140 | |
|---|
| | 141 | Safari key event behavior: |
|---|
| | 142 | (Safari sets charCode and keyCode to something crazy for |
|---|
| | 143 | special keys.) |
|---|
| | 144 | key event charCode keyCode |
|---|
| | 145 | DOWN ku,kd 63233 40 |
|---|
| | 146 | DOWN kp 63233 63233 |
|---|
| | 147 | ESC ku,kd 27 27 |
|---|
| | 148 | ESC kp 27 27 |
|---|
| | 149 | a ku,kd 97 65 |
|---|
| | 150 | a kp 97 97 |
|---|
| | 151 | shift+a ku,kd 65 65 |
|---|
| | 152 | shift+a kp 65 65 |
|---|
| | 153 | 1 ku,kd 49 49 |
|---|
| | 154 | 1 kp 49 49 |
|---|
| | 155 | shift+1 ku,kd 33 49 |
|---|
| | 156 | shift+1 kp 33 33 |
|---|
| | 157 | |
|---|
| | 158 | */ |
|---|
| | 159 | |
|---|
| | 160 | /* look for special keys here */ |
|---|
| | 161 | if (this.type() == 'keydown' || this.type() == 'keyup') { |
|---|
| | 162 | k.code = this._event.keyCode; |
|---|
| | 163 | k.string = (MochiKit.Signal._specialKeys[k.code] || |
|---|
| | 164 | 'KEY_UNKNOWN'); |
|---|
| | 165 | return k; |
|---|
| | 166 | |
|---|
| | 167 | /* look for characters here */ |
|---|
| | 168 | } else if (this.type() == 'keypress') { |
|---|
| | 169 | |
|---|
| | 170 | /* |
|---|
| | 171 | |
|---|
| | 172 | Special key behavior: |
|---|
| | 173 | |
|---|
| | 174 | IE: does not fire keypress events for special keys |
|---|
| | 175 | FF: sets charCode to 0, and sets the correct keyCode |
|---|
| | 176 | Safari: sets keyCode and charCode to something stupid |
|---|
| | 177 | |
|---|
| | 178 | */ |
|---|
| | 179 | |
|---|
| | 180 | k.code = 0; |
|---|
| | 181 | k.string = ''; |
|---|
| | 182 | |
|---|
| | 183 | if (typeof(this._event.charCode) != 'undefined' && |
|---|
| | 184 | this._event.charCode !== 0 && |
|---|
| | 185 | !MochiKit.Signal._specialMacKeys[this._event.charCode]) { |
|---|
| | 186 | k.code = this._event.charCode; |
|---|
| | 187 | k.string = String.fromCharCode(k.code); |
|---|
| | 188 | } else if (this._event.keyCode && |
|---|
| | 189 | typeof(this._event.charCode) == 'undefined') { // IE |
|---|
| | 190 | k.code = this._event.keyCode; |
|---|
| | 191 | k.string = String.fromCharCode(k.code); |
|---|
| | 192 | } |
|---|
| | 193 | |
|---|
| | 194 | return k; |
|---|
| | 195 | } |
|---|
| | 196 | } |
|---|
| | 197 | throw new Error('Signal cannot handle this type of key event'); |
|---|
| | 198 | }, |
|---|
| | 199 | |
|---|
| | 200 | mouse: function () { |
|---|
| | 201 | var m = {}; |
|---|
| | 202 | if (this.type() && ( |
|---|
| | 203 | this.type().indexOf('mouse') === 0 || |
|---|
| | 204 | this.type().indexOf('click') != -1 || |
|---|
| | 205 | this.type() == 'contextmenu')) { |
|---|
| | 206 | |
|---|
| | 207 | m.client = new MochiKit.DOM.Coordinates(0, 0); |
|---|
| | 208 | if (this._event.clientX || this._event.clientY) { |
|---|
| | 209 | m.client.x = this._fixPoint(this._event.clientX); |
|---|
| | 210 | m.client.y = this._fixPoint(this._event.clientY); |
|---|
| | 211 | } |
|---|
| | 212 | |
|---|
| | 213 | m.page = new MochiKit.DOM.Coordinates(0, 0); |
|---|
| | 214 | if (this._event.pageX || this._event.pageY) { |
|---|
| | 215 | m.page.x = this._fixPoint(this._event.pageX); |
|---|
| | 216 | m.page.y = this._fixPoint(this._event.pageY); |
|---|
| | 217 | } else { |
|---|
| | 218 | /* |
|---|
| | 219 | |
|---|
| | 220 | IE keeps the document offset in: |
|---|
| | 221 | document.documentElement.clientTop || |
|---|
| | 222 | document.body.clientTop |
|---|
| | 223 | |
|---|
| | 224 | and: |
|---|
| | 225 | document.documentElement.clientLeft || |
|---|
| | 226 | document.body.clientLeft |
|---|
| | 227 | |
|---|
| | 228 | see: |
|---|
| | 229 | http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp |
|---|
| | 230 | |
|---|
| | 231 | The offset is (2,2) in standards mode and (0,0) in quirks |
|---|
| | 232 | mode. |
|---|
| | 233 | |
|---|
| | 234 | */ |
|---|
| | 235 | |
|---|
| | 236 | var de = MochiKit.DOM._document.documentElement; |
|---|
| | 237 | var b = MochiKit.DOM._document.body; |
|---|
| | 238 | |
|---|
| | 239 | m.page.x = this._event.clientX + |
|---|
| | 240 | (de.scrollLeft || b.scrollLeft) - |
|---|
| | 241 | (de.clientLeft || b.clientLeft); |
|---|
| | 242 | |
|---|
| | 243 | m.page.y = this._event.clientY + |
|---|
| | 244 | (de.scrollTop || b.scrollTop) - |
|---|
| | 245 | (de.clientTop || b.clientTop); |
|---|
| | 246 | |
|---|
| | 247 | } |
|---|
| | 248 | if (this.type() != 'mousemove') { |
|---|
| | 249 | m.button = {}; |
|---|
| | 250 | m.button.left = false; |
|---|
| | 251 | m.button.right = false; |
|---|
| | 252 | m.button.middle = false; |
|---|
| | 253 | |
|---|
| | 254 | /* we could check this._event.button, but which is more consistent */ |
|---|
| | 255 | if (this._event.which) { |
|---|
| | 256 | m.button.left = (this._event.which == 1); |
|---|
| | 257 | m.button.middle = (this._event.which == 2); |
|---|
| | 258 | m.button.right = (this._event.which == 3); |
|---|
| | 259 | |
|---|
| | 260 | /* |
|---|
| | 261 | |
|---|
| | 262 | Mac browsers and right click: |
|---|
| | 263 | |
|---|
| | 264 | - Safari doesn't fire any click events on a right |
|---|
| | 265 | click: |
|---|
| | 266 | http://bugzilla.opendarwin.org/show_bug.cgi?id=6595 |
|---|
| | 267 | |
|---|
| | 268 | - Firefox fires the event, and sets ctrlKey = true |
|---|
| | 269 | |
|---|
| | 270 | - Opera fires the event, and sets metaKey = true |
|---|
| | 271 | |
|---|
| | 272 | oncontextmenu is fired on right clicks between browsers |
|---|
| | 273 | and across platforms. |
|---|
| | 274 | |
|---|
| | 275 | */ |
|---|
| | 276 | |
|---|
| | 277 | } else { |
|---|
| | 278 | m.button.left = !!(this._event.button & 1); |
|---|
| | 279 | m.button.right = !!(this._event.button & 2); |
|---|
| | 280 | m.button.middle = !!(this._event.button & 4); |
|---|
| | 281 | } |
|---|
| | 282 | } |
|---|
| | 283 | return m; |
|---|
| | 284 | } |
|---|
| | 285 | throw new Error('This is not a mouse event'); |
|---|
| | 286 | }, |
|---|
| | 287 | |
|---|
| | 288 | stop: function () { |
|---|
| | 289 | this.stopPropagation(); |
|---|
| | 290 | this.preventDefault(); |
|---|
| | 291 | }, |
|---|
| | 292 | |
|---|
| | 293 | stopPropagation: function () { |
|---|
| | 294 | if (this._event.stopPropagation) { |
|---|
| | 295 | this._event.stopPropagation(); |
|---|
| | 296 | } else { |
|---|
| | 297 | this._event.cancelBubble = true; |
|---|
| | 298 | } |
|---|
| | 299 | }, |
|---|
| | 300 | |
|---|
| | 301 | preventDefault: function () { |
|---|
| | 302 | if (this._event.preventDefault) { |
|---|
| | 303 | this._event.preventDefault(); |
|---|
| | 304 | } else { |
|---|
| | 305 | this._event.returnValue = false; |
|---|
| | 306 | } |
|---|
| | 307 | }, |
|---|
| | 308 | |
|---|
| | 309 | toString: function() { |
|---|
| | 310 | return this.__repr__(); |
|---|
| 70 | | throw new Error('No related target'); |
|---|
| 71 | | }; |
|---|
| 72 | | |
|---|
| 73 | | MochiKit.Signal.Event.prototype.modifier = function () { |
|---|
| 74 | | var m = {}; |
|---|
| 75 | | m.alt = this._event.altKey; |
|---|
| 76 | | m.ctrl = this._event.ctrlKey; |
|---|
| 77 | | m.meta = this._event.metaKey || false; // ie and opera punt here |
|---|
| 78 | | m.shift = this._event.shiftKey; |
|---|
| 79 | | return m; |
|---|
| 80 | | }; |
|---|
| 81 | | |
|---|
| 82 | | MochiKit.Signal.Event.prototype.key = function () { |
|---|
| 83 | | var k = {}; |
|---|
| 84 | | if (this.type() && this.type().indexOf('key') === 0) { |
|---|
| 85 | | |
|---|
| 86 | | /* |
|---|
| 87 | | |
|---|
| 88 | | If you're looking for a special key, look for it in keydown or |
|---|
| 89 | | keyup, but never keypress. If you're looking for a Unicode |
|---|
| 90 | | chracter, look for it with keypress, but never keyup or keydown. |
|---|
| 91 | | |
|---|
| 92 | | Notes: |
|---|
| 93 | | |
|---|
| 94 | | FF key event behavior: |
|---|
| 95 | | key event charCode keyCode |
|---|
| 96 | | DOWN ku,kd 0 40 |
|---|
| 97 | | DOWN kp 0 40 |
|---|
| 98 | | ESC ku,kd 0 27 |
|---|
| 99 | | ESC kp 0 27 |
|---|
| 100 | | a ku,kd 0 65 |
|---|
| 101 | | a kp 97 0 |
|---|
| 102 | | shift+a ku,kd 0 65 |
|---|
| 103 | | shift+a kp 65 0 |
|---|
| 104 | | 1 ku,kd 0 49 |
|---|
| 105 | | 1 kp 49 0 |
|---|
| 106 | | shift+1 ku,kd 0 0 |
|---|
| 107 | | shift+1 kp 33 0 |
|---|
| 108 | | |
|---|
| 109 | | IE key event behavior: |
|---|
| 110 | | (IE doesn't fire keypress events for special keys.) |
|---|
| 111 | | key event keyCode |
|---|
| 112 | | DOWN ku,kd 40 |
|---|
| 113 | | DOWN kp undefined |
|---|
| 114 | | ESC ku,kd 27 |
|---|
| 115 | | ESC kp 27 |
|---|
| 116 | | a ku,kd 65 |
|---|
| 117 | | a kp 97 |
|---|
| 118 | | shift+a ku,kd 65 |
|---|
| 119 | | shift+a kp 65 |
|---|
| 120 | | 1 ku,kd 49 |
|---|
| 121 | | 1 kp 49 |
|---|
| 122 | | shift+1 ku,kd 49 |
|---|
| 123 | | shift+1 kp 33 |
|---|
| 124 | | |
|---|
| 125 | | Safari key event behavior: |
|---|
| 126 | | (Safari sets charCode and keyCode to something crazy for |
|---|
| 127 | | special keys.) |
|---|
| 128 | | key event charCode keyCode |
|---|
| 129 | | DOWN ku,kd 63233 40 |
|---|
| 130 | | DOWN kp 63233 63233 |
|---|
| 131 | | ESC ku,kd 27 27 |
|---|
| 132 | | ESC kp 27 27 |
|---|
| 133 | | a ku,kd 97 65 |
|---|
| 134 | | a kp 97 97 |
|---|
| 135 | | shift+a ku,kd 65 65 |
|---|
| 136 | | shift+a kp 65 65 |
|---|
| 137 | | 1 ku,kd 49 49 |
|---|
| 138 | | 1 kp 49 49 |
|---|
| 139 | | shift+1 ku,kd 33 49 |
|---|
| 140 | | shift+1 kp 33 33 |
|---|
| 141 | | |
|---|
| 142 | | */ |
|---|
| 143 | | |
|---|
| 144 | | /* look for special keys here */ |
|---|
| 145 | | if (this.type() == 'keydown' || this.type() == 'keyup') { |
|---|
| 146 | | k.code = this._event.keyCode; |
|---|
| 147 | | k.string = (MochiKit.Signal._specialKeys[k.code] || |
|---|
| 148 | | 'KEY_UNKNOWN'); |
|---|
| 149 | | return k; |
|---|
| 150 | | |
|---|
| 151 | | /* look for characters here */ |
|---|
| 152 | | } else if (this.type() == 'keypress') { |
|---|
| 153 | | |
|---|
| 154 | | /* |
|---|
| 155 | | |
|---|
| 156 | | Special key behavior: |
|---|
| 157 | | |
|---|
| 158 | | IE: does not fire keypress events for special keys |
|---|
| 159 | | FF: sets charCode to 0, and sets the correct keyCode |
|---|
| 160 | | Safari sets keyCode and charCode to something stupid |
|---|
| 161 | | |
|---|
| 162 | | */ |
|---|
| 163 | | |
|---|
| 164 | | k.code = 0; |
|---|
| 165 | | k.string = ''; |
|---|
| 166 | | |
|---|
| 167 | | if (typeof(this._event.charCode) != 'undefined' && |
|---|
| 168 | | this._event.charCode !== 0 && |
|---|
| 169 | | !MochiKit.Signal._specialMacKeys[this._event.charCode]) { |
|---|
| 170 | | k.code = this._event.charCode; |
|---|
| 171 | | k.string = String.fromCharCode(k.code); |
|---|
| 172 | | } else if (this._event.keyCode && |
|---|
| 173 | | typeof(this._event.charCode) == 'undefined') { // IE |
|---|
| 174 | | k.code = this._event.keyCode; |
|---|
| 175 | | k.string = String.fromCharCode(k.code); |
|---|
| 176 | | } |
|---|
| 177 | | |
|---|
| 178 | | return k; |
|---|
| 179 | | } |
|---|
| 180 | | } |
|---|
| 181 | | throw new Error('Signal cannot handle this type of key event'); |
|---|
| 182 | | }; |
|---|
| 183 | | |
|---|
| 184 | | MochiKit.Signal.Event.prototype._fixPoint = function (point) { |
|---|
| 185 | | /* |
|---|
| 186 | | |
|---|
| 187 | | FIXME: inline this to avoid funciton call overhead? Does JS have |
|---|
| 188 | | function call overhead? |
|---|
| 189 | | |
|---|
| 190 | | */ |
|---|
| 191 | | if (typeof(point) == 'undefined' || point < 0) { |
|---|
| 192 | | return 0; |
|---|
| 193 | | } |
|---|
| 194 | | return point; |
|---|
| 195 | | }; |
|---|
| 196 | | |
|---|
| 197 | | MochiKit.Signal.Event.prototype.mouse = function () { |
|---|
| 198 | | var m = {}; |
|---|
| 199 | | if (this.type() && ( |
|---|
| 200 | | this.type().indexOf('mouse') === 0 || |
|---|
| 201 | | this.type().indexOf('click') != -1 || |
|---|
| 202 | | this.type() == 'contextmenu')) { |
|---|
| 203 | | |
|---|
| 204 | | m.client = new MochiKit.DOM.Coordinates(0, 0); |
|---|
| 205 | | if (this._event.clientX || this._event.clientY) { |
|---|
| 206 | | m.client.x = this._fixPoint(this._event.clientX); |
|---|
| 207 | | m.client.y = this._fixPoint(this._event.clientY); |
|---|
| 208 | | } |
|---|
| 209 | | |
|---|
| 210 | | m.page = new MochiKit.DOM.Coordinates(0, 0); |
|---|
| 211 | | if (this._event.pageX || this._event.pageY) { |
|---|
| 212 | | m.page.x = this._fixPoint(this._event.pageX); |
|---|
| 213 | | m.page.y = this._fixPoint(this._event.pageY); |
|---|
| 214 | | } else { |
|---|
| 215 | | /* |
|---|
| 216 | | |
|---|
| 217 | | IE keeps the document offset in: |
|---|
| 218 | | document.documentElement.clientTop || |
|---|
| 219 | | document.body.clientTop |
|---|
| 220 | | |
|---|
| 221 | | and: |
|---|
| 222 | | document.documentElement.clientLeft || |
|---|
| 223 | | document.body.clientLeft |
|---|
| 224 | | |
|---|
| 225 | | see: |
|---|
| 226 | | http://msdn.microsoft.com/workshop/author/dhtml/reference/ |
|---|
| 227 | | methods/getboundingclientrect.asp |
|---|
| 228 | | |
|---|
| 229 | | The offset is (2,2) in standards mode and (0,0) in quirks |
|---|
| 230 | | mode. |
|---|
| 231 | | |
|---|
| 232 | | */ |
|---|
| 233 | | |
|---|
| 234 | | var de = MochiKit.DOM._document.documentElement; |
|---|
| 235 | | var b = MochiKit.DOM._document.body; |
|---|
| 236 | | |
|---|
| 237 | | m.page.x = this._event.clientX + |
|---|
| 238 | | (de.scrollLeft || b.scrollLeft) - |
|---|
| 239 | | (de.clientLeft || b.clientLeft); |
|---|
| 240 | | |
|---|
| 241 | | m.page.y = this._event.clientY + |
|---|
| 242 | | (de.scrollTop || b.scrollTop) - |
|---|
| 243 | | (de.clientTop || b.clientTop); |
|---|
| 244 | | |
|---|
| 245 | | } |
|---|
| 246 | | if (this.type() != 'mousemove') { |
|---|
| 247 | | m.button = {}; |
|---|
| 248 | | m.button.left = false; |
|---|
| 249 | | m.button.right = false; |
|---|
| 250 | | m.button.middle = false; |
|---|
| 251 | | |
|---|
| 252 | | // we could check this._event.button, but which is more consistent |
|---|
| 253 | | if (this._event.which) { |
|---|
| 254 | | m.button.left = (this._event.which == 1); |
|---|
| 255 | | m.button.middle = (this._event.which == 2); |
|---|
| 256 | | m.button.right = (this._event.which == 3); |
|---|
| 257 | | |
|---|
| 258 | | /* |
|---|
| 259 | | |
|---|
| 260 | | Mac browsers and right click: |
|---|
| 261 | | |
|---|
| 262 | | - Safari doesn't fire any click events on a right |
|---|
| 263 | | click: |
|---|
| 264 | | http://bugzilla.opendarwin.org/show_bug.cgi?id=6595 |
|---|
| 265 | | |
|---|
| 266 | | - Firefox fires the event, and sets ctrlKey = true |
|---|
| 267 | | |
|---|
| 268 | | - Opera fires the event, and sets metaKey = true |
|---|
| 269 | | |
|---|
| 270 | | oncontextmenu is fired on right clicks between browsers |
|---|
| 271 | | and across platforms. |
|---|
| 272 | | |
|---|
| 273 | | */ |
|---|
| 274 | | |
|---|
| 275 | | } else { |
|---|
| 276 | | m.button.left = !!(this._event.button & 1); |
|---|
| 277 | | m.button.right = !!(this._event.button & 2); |
|---|
| 278 | | m.button.middle = !!(this._event.button & 4); |
|---|
| 279 | | } |
|---|
| 280 | | } |
|---|
| 281 | | return m; |
|---|
| 282 | | } |
|---|
| 283 | | throw new Error('This is not a mouse event'); |
|---|
| 284 | | }; |
|---|
| 285 | | |
|---|
| 286 | | MochiKit.Signal.Event.prototype.stop = function () { |
|---|
| 287 | | this.stopPropagation(); |
|---|
| 288 | | this.preventDefault(); |
|---|
| 289 | | }; |
|---|
| 290 | | |
|---|
| 291 | | MochiKit.Signal.Event.prototype.stopPropagation = function () { |
|---|
| 292 | | if (this._event.stopPropagation) { |
|---|
| 293 | | this._event.stopPropagation(); |
|---|
| 294 | | } else { |
|---|
| 295 | | this._event.cancelBubble = true; |
|---|
| 296 | | } |
|---|
| 297 | | }; |
|---|
| 298 | | |
|---|
| 299 | | MochiKit.Signal.Event.prototype.preventDefault = function () { |
|---|
| 300 | | if (this._event.preventDefault) { |
|---|
| 301 | | this._event.preventDefault(); |
|---|
| 302 | | } else { |
|---|
| 303 | | this._event.returnValue = false; |
|---|
| 304 | | } |
|---|
| 305 | | }; |
|---|
| 306 | | |
|---|
| 307 | | MochiKit.Signal.Event.prototype.__repr__ = function () { |
|---|
| 308 | | var repr = MochiKit.Base.repr; |
|---|
| 309 | | var str = '{event(): ' + repr(this.event()) + |
|---|
| 310 | | ', type(): ' + repr(this.type()) + |
|---|
| 311 | | ', target(): ' + repr(this.target()) + |
|---|
| 312 | | ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) + |
|---|
| 313 | | ', ctrl: ' + repr(this.modifier().ctrl) + |
|---|
| 314 | | ', meta: ' + repr(this.modifier().meta) + |
|---|
| 315 | | ', shift: ' + repr(this.modifier().shift) + '}'; |
|---|
| 316 | | |
|---|
| 317 | | if (this.type() && this.type().indexOf('key') === 0) { |
|---|
| 318 | | str += ', key(): {code: ' + repr(this.key().code) + |
|---|
| 319 | | ', string: ' + repr(this.key().string) + '}'; |
|---|
| 320 | | } |
|---|
| 321 | | |
|---|
| 322 | | if (this.type() && ( |
|---|
| 323 | | this.type().indexOf('mouse') === 0 || |
|---|
| 324 | | this.type().indexOf('click') != -1 || |
|---|
| 325 | | this.type() == 'contextmenu')) { |
|---|
| 326 | | |
|---|
| 327 | | str += ', mouse(): {page: ' + repr(this.mouse().page) + |
|---|
| 328 | | ', client: ' + repr(this.mouse().client); |
|---|
| 329 | | |
|---|
| 330 | | if (this.type() != 'mousemove') { |
|---|
| 331 | | str += ', button: {left: ' + repr(this.mouse().button.left) + |
|---|
| 332 | | ', middle: ' + repr(this.mouse().button.middle) + |
|---|
| 333 | | ', right: ' + repr(this.mouse().button.right) + '}}'; |
|---|
| 334 | | } else { |
|---|
| 335 | | str += '}'; |
|---|
| 336 | | } |
|---|
| 337 | | } |
|---|
| 338 | | if (this.type() == 'mouseover' || this.type() == 'mouseout') { |
|---|
| 339 | | str += ', relatedTarget(): ' + repr(this.relatedTarget()); |
|---|
| 340 | | } |
|---|
| 341 | | str += '}'; |
|---|
| 342 | | return str; |
|---|
| 343 | | }; |
|---|
| 344 | | |
|---|
| 345 | | MochiKit.Signal.Event.prototype.toString = function() { |
|---|
| 346 | | return this.__repr__(); |
|---|
| 347 | | }; |
|---|
| | 312 | }); |
|---|
| 504 | | /*** |
|---|
| 505 | | |
|---|
| 506 | | Connects a signal to a slot. |
|---|
| 507 | | |
|---|
| 508 | | 'src' is the object that has the signal. You may pass in a string, |
|---|
| 509 | | in which case, it is interpreted as an id for an HTML Element. |
|---|
| 510 | | |
|---|
| 511 | | 'signal' is a string that represents a signal name. If 'src' is an |
|---|
| 512 | | HTML Element, Window, or the Document, then it can be one of the |
|---|
| 513 | | 'on-XYZ' events. Note that you must include the 'on' prefix, and |
|---|
| 514 | | it must be all lower-case. If 'src' is another kind of object, the |
|---|
| 515 | | signal must be previously registered with 'registerSignals()'. |
|---|
| 516 | | |
|---|
| 517 | | 'dest' and 'func' describe the slot, or the action to take when |
|---|
| 518 | | the signal is triggered. |
|---|
| 519 | | |
|---|
| 520 | | - If 'dest' is an object and 'func' is a string, then |
|---|
| 521 | | 'dest[func](...)' will be called when the signal is signalled. |
|---|
| 522 | | |
|---|
| 523 | | - If 'dest' is an object and 'func' is a function, then |
|---|
| 524 | | 'func.apply(dest, ...)' will be called when the signal is |
|---|
| 525 | | signalled. |
|---|
| 526 | | |
|---|
| 527 | | - If 'func' is undefined and 'dest' is a function, then |
|---|
| 528 | | 'func.apply(src, ...)' will be called when the signal is |
|---|
| 529 | | signalled. |
|---|
| 530 | | |
|---|
| 531 | | No other combinations are allowed and should raise and exception. |
|---|
| 532 | | |
|---|
| 533 | | You may call 'connect()' multiple times with the same connection |
|---|
| 534 | | paramters. However, only a single connection will be made. |
|---|
| 535 | | |
|---|
| 536 | | ***/ |
|---|
| 549 | | if (src.addEventListener || src.attachEvent || src[sig]) { |
|---|
| 550 | | /* |
|---|
| 551 | | |
|---|
| 552 | | Create the _listeners object. This will help us remember which |
|---|
| 553 | | events we are watching. |
|---|
| 554 | | |
|---|
| 555 | | */ |
|---|
| 556 | | if (!src._listeners) { |
|---|
| 557 | | src._listeners = {}; |
|---|
| 558 | | } |
|---|
| 559 | | |
|---|
| 560 | | /* Add the signal connector if it hasn't been done already. */ |
|---|
| 561 | | if (!src._listeners[sig]) { |
|---|
| 562 | | var listener = function (nativeEvent) { |
|---|
| 563 | | var eventObject = new MochiKit.Signal.Event(nativeEvent); |
|---|
| 564 | | MochiKit.Signal.signal(src, sig, eventObject); |
|---|
| 565 | | return true; |
|---|
| 566 | | }; |
|---|
| 567 | | MochiKit.Signal._observers.push([src, sig, listener]); |
|---|
| 568 | | |
|---|
| 569 | | if (src.addEventListener) { |
|---|
| 570 | | src.addEventListener(sig.substr(2), listener, false); |
|---|
| 571 | | } else if (src.attachEvent) { |
|---|
| 572 | | src.attachEvent(sig, listener); // useCapture unsupported |
|---|
| 573 | | } else { |
|---|
| 574 | | src[sig] = listener; |
|---|
| 575 | | } |
|---|
| 576 | | |
|---|
| 577 | | src._listeners[sig] = listener; |
|---|
| 578 | | } |
|---|
| 579 | | |
|---|
| 580 | | if (!src._signals) { |
|---|
| 581 | | src._signals = {}; |
|---|
| 582 | | } |
|---|
| 583 | | if (!src._signals[sig]) { |
|---|
| 584 | | src._signals[sig] = []; |
|---|
| 585 | | } |
|---|
| 586 | | } else { |
|---|
| 587 | | if (!src._signals || !src._signals[sig]) { |
|---|
| 588 | | throw new Error("No such signal '" + sig + "' registered."); |
|---|
| 589 | | } |
|---|
| | 475 | /* |
|---|
| | 476 | |
|---|
| | 477 | Create the _listeners object. This will help us remember which |
|---|
| | 478 | events we are watching. |
|---|
| | 479 | |
|---|
| | 480 | */ |
|---|
| | 481 | if (!src._listeners) { |
|---|
| | 482 | src._listeners = {}; |
|---|
| | 483 | } |
|---|
| | 484 | |
|---|
| | 485 | /* Add the signal connector if it hasn't been done already. */ |
|---|
| | 486 | if (!src._listeners[sig]) { |
|---|
| | 487 | var listener = function (nativeEvent) { |
|---|
| | 488 | var eventObject = new MochiKit.Signal.Event(nativeEvent); |
|---|
| | 489 | MochiKit.Signal.signal(src, sig, eventObject); |
|---|
| | 490 | return true; |
|---|
| | 491 | }; |
|---|
| | 492 | MochiKit.Signal._observers.push([src, sig, listener]); |
|---|
| | 493 | |
|---|
| | 494 | if (src.addEventListener) { |
|---|
| | 495 | src.addEventListener(sig.substr(2), listener, false); |
|---|
| | 496 | } else if (src.attachEvent) { |
|---|
| | 497 | src.attachEvent(sig, listener); // useCapture unsupported |
|---|
| | 498 | } else { |
|---|
| | 499 | src[sig] = listener; |
|---|
| | 500 | } |
|---|
| | 501 | |
|---|
| | 502 | src._listeners[sig] = listener; |
|---|
| | 503 | } |
|---|
| | 504 | |
|---|
| | 505 | if (!src._signals) { |
|---|
| | 506 | src._signals = {}; |
|---|
| | 507 | } |
|---|
| | 508 | if (!src._signals[sig]) { |
|---|
| | 509 | src._signals[sig] = []; |
|---|