Improve key event handling, work in progress.

This commit is contained in:
Jürg Lehni 2011-05-08 13:43:52 +01:00
parent 2f4f003873
commit b26caee702
6 changed files with 193 additions and 66 deletions

View file

@ -287,7 +287,7 @@
var layer = document.activeLayer; var layer = document.activeLayer;
function onKeyDown(event) { function onKeyDown(event) {
if (event.character == 'space') if (event.keyCode == 'space')
layer.selected = !layer.selected; layer.selected = !layer.selected;
} }
</script> </script>

View file

@ -62,6 +62,23 @@ var DomEvent = {
// Remove target offsets from page coordinates // Remove target offsets from page coordinates
return DomEvent.getPoint(event).subtract( return DomEvent.getPoint(event).subtract(
DomElement.getOffset(DomEvent.getElement(event), true)); 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;
}
} }
}; };

View file

@ -62,19 +62,21 @@ var sources = [
'src/color/Gradient.js', 'src/color/Gradient.js',
'src/color/GradientStop.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/ToolEvent.js',
'src/tool/ToolHandler.js', 'src/tool/ToolHandler.js',
'src/tool/Tool.js', 'src/tool/Tool.js',
'src/browser/DomElement.js',
'src/browser/DomEvent.js',
'src/util/CanvasProvider.js', 'src/util/CanvasProvider.js',
'src/util/Numerical.js', 'src/util/Numerical.js',
'src/util/PaperScript.js', 'src/util/PaperScript.js',
'src/util/BlendMode.js', 'src/util/BlendMode.js'
'src/ui/Key.js'
]; ];
// Load unit tests after library if asked to do so // Load unit tests after library if asked to do so

39
src/ui/Event.js Normal file
View file

@ -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;
}
});

View file

@ -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 // TODO: make sure the keys are called the same as in Scriptographer
// Missing: tab, cancel, clear, pause, page-down, page-up, end, home, comma, // Missing: tab, cancel, clear, pause, page-down, page-up, end, home, comma,
// minus, period, slash, etc etc etc. // minus, period, slash, etc etc etc.
var keys = { var keys = {
'8': 'backspace', 8: 'backspace',
'13': 'enter', 13: 'enter',
'16': 'shift', 16: 'shift',
'17': 'control', 17: 'control',
'19': 'option', // was alt 19: 'option', // was alt
'20': 'capsLock', 20: 'capsLock',
'27': 'escape', 27: 'escape',
'32': 'space', 32: 'space',
'37': 'left', 37: 'left',
'38': 'up', 38: 'up',
'39': 'right', 39: 'right',
'40': 'down', 40: 'down',
'46': 'delete', 46: 'delete',
'91': 'command' 91: 'command'
}, },
modifiers = { modifiers = {
shift: false, shift: false,
control: false, control: false,
@ -25,53 +43,61 @@ var Key = new function() {
command: false, command: false,
capsLock: false capsLock: false
}, },
activeKeys = {};
keyCodes = {},
Event.add(document, Base.each(['keyDown', 'keyUp'], function(type) { downCode,
var toolHandler = 'on' + Base.capitalize(type), downTimer;
keyDown = type === 'keyDown';
this[type.toLowerCase()] = function(event) { function handleKey(down, code, event) {
var code = event.which || event.keyCode, var character = String.fromCharCode(code),
key = keys[code] || String.fromCharCode(code).toLowerCase(); keyCode = keys[code] || character.toLowerCase(),
activeKeys[key] = keyDown; handler = down ? 'onKeyDown' : 'onKeyUp';
console.log(handler, keyCode, character);
// If the key is a modifier, update the modifiers: if (modifiers[keyCode] !== undefined) {
if (modifiers[key] !== undefined) modifiers[keyCode] = down;
modifiers[key] = keyDown; } else if (paper.tool && paper.tool[handler]) {
// Call the onKeyDown or onKeyUp handler if present
// Call the onKeyDown or onKeyUp handler if present: // When the handler function returns false, prevent the
// TODO: don't call the key handler if the key is a modifier? // default behaviour of the key event:
if (paper.tool && paper.tool[toolHandler]) { // PORT: Add to Sg
// TODO: Introduce a class for this? var keyEvent = new KeyEvent(down, keyCode, character, event);
var keyEvent = { if (paper.tool[handler](keyEvent) === false) {
type: keyDown ? 'key-down' : 'key-up', keyEvent.preventDefault();
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();
} }
}; }
}, {})); }
// 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 { return {
modifiers: modifiers, modifiers: modifiers,
isDown: function(key) { isDown: function(key) {
return !!activeKeys[key]; return !!activeKeys[key];
} }

43
src/ui/KeyEvent.js Normal file
View file

@ -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;
}
};
});