diff --git a/examples/Animated/Flock.html b/examples/Animated/Flock.html
index ee167a1e..63c1cc17 100644
--- a/examples/Animated/Flock.html
+++ b/examples/Animated/Flock.html
@@ -287,7 +287,7 @@
var layer = document.activeLayer;
function onKeyDown(event) {
- if (event.character == 'space')
+ if (event.keyCode == 'space')
layer.selected = !layer.selected;
}
diff --git a/src/browser/DomEvent.js b/src/browser/DomEvent.js
index 1c411688..b5ef6557 100644
--- a/src/browser/DomEvent.js
+++ b/src/browser/DomEvent.js
@@ -62,6 +62,23 @@ var DomEvent = {
// Remove target offsets from page coordinates
return DomEvent.getPoint(event).subtract(
DomElement.getOffset(DomEvent.getElement(event), true));
+ },
+
+ preventDefault: function(event) {
+ if (event.preventDefault) {
+ event.preventDefault();
+ } else {
+ // IE
+ event.returnValue = false;
+ }
+ },
+
+ stopPropagation: function(event) {
+ if (event.stopPropagation) {
+ event.stopPropagation();
+ } else {
+ event.cancelBubble = true;
+ }
}
};
diff --git a/src/load.js b/src/load.js
index bcc2ad15..23c1793d 100644
--- a/src/load.js
+++ b/src/load.js
@@ -62,19 +62,21 @@ var sources = [
'src/color/Gradient.js',
'src/color/GradientStop.js',
+ 'src/browser/DomElement.js',
+ 'src/browser/DomEvent.js',
+
+ 'src/ui/Event.js',
+ 'src/ui/KeyEvent.js',
+ 'src/ui/Key.js',
+
'src/tool/ToolEvent.js',
'src/tool/ToolHandler.js',
'src/tool/Tool.js',
- 'src/browser/DomElement.js',
- 'src/browser/DomEvent.js',
-
'src/util/CanvasProvider.js',
'src/util/Numerical.js',
'src/util/PaperScript.js',
- 'src/util/BlendMode.js',
-
- 'src/ui/Key.js'
+ 'src/util/BlendMode.js'
];
// Load unit tests after library if asked to do so
diff --git a/src/ui/Event.js b/src/ui/Event.js
new file mode 100644
index 00000000..8a7d0919
--- /dev/null
+++ b/src/ui/Event.js
@@ -0,0 +1,39 @@
+/*
+ * Paper.js
+ *
+ * This file is part of Paper.js, a JavaScript Vector Graphics Library,
+ * based on Scriptographer.org and designed to be largely API compatible.
+ * http://paperjs.org/
+ * http://scriptographer.org/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
+ * http://lehni.org/ & http://jonathanpuckey.com/
+ *
+ * All rights reserved.
+ */
+
+var Event = this.Event = Base.extend({
+ initialize: function(event) {
+ this.event = event;
+ },
+
+ // PORT: Add to Sg
+ preventDefault: function() {
+ DomEvent.preventDefault(this.event);
+ },
+
+ stopPropagation: function() {
+ DomEvent.stopPropagation(this.event);
+ },
+
+ stop: function() {
+ this.stopPropagation();
+ this.preventDefault();
+ },
+
+ getModifiers: function() {
+ return Key.modifiers;
+ }
+});
diff --git a/src/ui/Key.js b/src/ui/Key.js
index 30980c15..1342a8d7 100644
--- a/src/ui/Key.js
+++ b/src/ui/Key.js
@@ -1,23 +1,41 @@
-var Key = new function() {
+/*
+ * Paper.js
+ *
+ * This file is part of Paper.js, a JavaScript Vector Graphics Library,
+ * based on Scriptographer.org and designed to be largely API compatible.
+ * http://paperjs.org/
+ * http://scriptographer.org/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
+ * http://lehni.org/ & http://jonathanpuckey.com/
+ *
+ * All rights reserved.
+ */
+
+var Key = this.Key = new function() {
// TODO: make sure the keys are called the same as in Scriptographer
// Missing: tab, cancel, clear, pause, page-down, page-up, end, home, comma,
// minus, period, slash, etc etc etc.
+
var keys = {
- '8': 'backspace',
- '13': 'enter',
- '16': 'shift',
- '17': 'control',
- '19': 'option', // was alt
- '20': 'capsLock',
- '27': 'escape',
- '32': 'space',
- '37': 'left',
- '38': 'up',
- '39': 'right',
- '40': 'down',
- '46': 'delete',
- '91': 'command'
+ 8: 'backspace',
+ 13: 'enter',
+ 16: 'shift',
+ 17: 'control',
+ 19: 'option', // was alt
+ 20: 'capsLock',
+ 27: 'escape',
+ 32: 'space',
+ 37: 'left',
+ 38: 'up',
+ 39: 'right',
+ 40: 'down',
+ 46: 'delete',
+ 91: 'command'
},
+
modifiers = {
shift: false,
control: false,
@@ -25,53 +43,61 @@ var Key = new function() {
command: false,
capsLock: false
},
- activeKeys = {};
-
- Event.add(document, Base.each(['keyDown', 'keyUp'], function(type) {
- var toolHandler = 'on' + Base.capitalize(type),
- keyDown = type === 'keyDown';
- this[type.toLowerCase()] = function(event) {
- var code = event.which || event.keyCode,
- key = keys[code] || String.fromCharCode(code).toLowerCase();
- activeKeys[key] = keyDown;
-
- // If the key is a modifier, update the modifiers:
- if (modifiers[key] !== undefined)
- modifiers[key] = keyDown;
-
- // Call the onKeyDown or onKeyUp handler if present:
- // TODO: don't call the key handler if the key is a modifier?
- if (paper.tool && paper.tool[toolHandler]) {
- // TODO: Introduce a class for this?
- var keyEvent = {
- type: keyDown ? 'key-down' : 'key-up',
- keyCode: code,
- character: key,
- modifiers: modifiers,
- // 'preventDefault: event.preventDefault' throws
- // an error in Safari when called, so we have to wrap
- // it into a function.
- // PORT: Add to Sg
- preventDefault: function() {
- if (event.preventDefault) {
- event.preventDefault();
- } else {
- event.returnValue = false;
- }
- }
- };
- var res = paper.tool[toolHandler](keyEvent);
- // PORT: Add to Sg
- // When the handler function returns false, prevent the
- // default behaviour of the key event:
- if (res === false)
- keyEvent.preventDefault();
+
+ keyCodes = {},
+ downCode,
+ downTimer;
+
+ function handleKey(down, code, event) {
+ var character = String.fromCharCode(code),
+ keyCode = keys[code] || character.toLowerCase(),
+ handler = down ? 'onKeyDown' : 'onKeyUp';
+ console.log(handler, keyCode, character);
+ if (modifiers[keyCode] !== undefined) {
+ modifiers[keyCode] = down;
+ } else if (paper.tool && paper.tool[handler]) {
+ // Call the onKeyDown or onKeyUp handler if present
+ // When the handler function returns false, prevent the
+ // default behaviour of the key event:
+ // PORT: Add to Sg
+ var keyEvent = new KeyEvent(down, keyCode, character, event);
+ if (paper.tool[handler](keyEvent) === false) {
+ keyEvent.preventDefault();
}
- };
- }, {}));
-
+ }
+ }
+
+ // Since only keypress gest proper keyCodes that are actually representing
+ // characters, we need to add a little timeout to keydown events to see if
+ // they are follow immediately by a keypress, and if so, map the keyCode
+ // from the keydown to the one from keypress, so keyup still knows what
+ // code has now been released.
+ DomEvent.add(document, {
+ keydown: function(event) {
+ var code = downCode = event.which || event.keyCode;
+ downTimer = setTimeout(function() {
+ keyCodes[code] = code;
+ handleKey(true, code, event);
+ }, 1);
+ },
+
+ keypress: function(event) {
+ clearTimeout(downTimer);
+ var code = event.which || event.keyCode;
+ keyCodes[downCode] = code;
+ handleKey(true, code, event);
+ },
+
+ keyup: function(event) {
+ var code = event.which || event.keyCode;
+ handleKey(false, keyCodes[code], event);
+ delete keyCodes[code];
+ }
+ });
+
return {
modifiers: modifiers,
+
isDown: function(key) {
return !!activeKeys[key];
}
diff --git a/src/ui/KeyEvent.js b/src/ui/KeyEvent.js
new file mode 100644
index 00000000..012388cb
--- /dev/null
+++ b/src/ui/KeyEvent.js
@@ -0,0 +1,43 @@
+/*
+ * Paper.js
+ *
+ * This file is part of Paper.js, a JavaScript Vector Graphics Library,
+ * based on Scriptographer.org and designed to be largely API compatible.
+ * http://paperjs.org/
+ * http://scriptographer.org/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
+ * http://lehni.org/ & http://jonathanpuckey.com/
+ *
+ * All rights reserved.
+ */
+
+var KeyEvent = this.KeyEvent = Event.extend(new function() {
+ var keys = {
+ 8: 'backspace',
+ 13: 'enter',
+ 16: 'shift',
+ 17: 'control',
+ 19: 'option', // was alt
+ 20: 'capsLock',
+ 27: 'escape',
+ 32: 'space',
+ 37: 'left',
+ 38: 'up',
+ 39: 'right',
+ 40: 'down',
+ 46: 'delete',
+ 91: 'command'
+ };
+
+ return {
+ initialize: function(down, keyCode, character, event) {
+ this.base(event);
+ this.type = down ? 'key-down' : 'key-up';
+ this.keyCode = keyCode;
+ this.character = character;
+ }
+ };
+});