|
1 | | -var Key = new function() { |
| 1 | +/* |
| 2 | + * Paper.js |
| 3 | + * |
| 4 | + * This file is part of Paper.js, a JavaScript Vector Graphics Library, |
| 5 | + * based on Scriptographer.org and designed to be largely API compatible. |
| 6 | + * http://paperjs.org/ |
| 7 | + * http://scriptographer.org/ |
| 8 | + * |
| 9 | + * Distributed under the MIT license. See LICENSE file for details. |
| 10 | + * |
| 11 | + * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey |
| 12 | + * http://lehni.org/ & http://jonathanpuckey.com/ |
| 13 | + * |
| 14 | + * All rights reserved. |
| 15 | + */ |
| 16 | + |
| 17 | +var Key = this.Key = new function() { |
2 | 18 | // TODO: make sure the keys are called the same as in Scriptographer |
3 | 19 | // Missing: tab, cancel, clear, pause, page-down, page-up, end, home, comma, |
4 | 20 | // minus, period, slash, etc etc etc. |
| 21 | + |
5 | 22 | var keys = { |
6 | | - '8': 'backspace', |
7 | | - '13': 'enter', |
8 | | - '16': 'shift', |
9 | | - '17': 'control', |
10 | | - '19': 'option', // was alt |
11 | | - '20': 'capsLock', |
12 | | - '27': 'escape', |
13 | | - '32': 'space', |
14 | | - '37': 'left', |
15 | | - '38': 'up', |
16 | | - '39': 'right', |
17 | | - '40': 'down', |
18 | | - '46': 'delete', |
19 | | - '91': 'command' |
| 23 | + 8: 'backspace', |
| 24 | + 13: 'enter', |
| 25 | + 16: 'shift', |
| 26 | + 17: 'control', |
| 27 | + 19: 'option', // was alt |
| 28 | + 20: 'capsLock', |
| 29 | + 27: 'escape', |
| 30 | + 32: 'space', |
| 31 | + 37: 'left', |
| 32 | + 38: 'up', |
| 33 | + 39: 'right', |
| 34 | + 40: 'down', |
| 35 | + 46: 'delete', |
| 36 | + 91: 'command' |
20 | 37 | }, |
| 38 | + |
21 | 39 | modifiers = { |
22 | 40 | shift: false, |
23 | 41 | control: false, |
24 | 42 | option: false, |
25 | 43 | command: false, |
26 | 44 | capsLock: false |
27 | 45 | }, |
28 | | - activeKeys = {}; |
29 | | - |
30 | | - Event.add(document, Base.each(['keyDown', 'keyUp'], function(type) { |
31 | | - var toolHandler = 'on' + Base.capitalize(type), |
32 | | - keyDown = type === 'keyDown'; |
33 | | - this[type.toLowerCase()] = function(event) { |
34 | | - var code = event.which || event.keyCode, |
35 | | - key = keys[code] || String.fromCharCode(code).toLowerCase(); |
36 | | - activeKeys[key] = keyDown; |
37 | | - |
38 | | - // If the key is a modifier, update the modifiers: |
39 | | - if (modifiers[key] !== undefined) |
40 | | - modifiers[key] = keyDown; |
41 | | - |
42 | | - // Call the onKeyDown or onKeyUp handler if present: |
43 | | - // TODO: don't call the key handler if the key is a modifier? |
44 | | - if (paper.tool && paper.tool[toolHandler]) { |
45 | | - // TODO: Introduce a class for this? |
46 | | - var keyEvent = { |
47 | | - type: keyDown ? 'key-down' : 'key-up', |
48 | | - keyCode: code, |
49 | | - character: key, |
50 | | - modifiers: modifiers, |
51 | | - // 'preventDefault: event.preventDefault' throws |
52 | | - // an error in Safari when called, so we have to wrap |
53 | | - // it into a function. |
54 | | - // PORT: Add to Sg |
55 | | - preventDefault: function() { |
56 | | - if (event.preventDefault) { |
57 | | - event.preventDefault(); |
58 | | - } else { |
59 | | - event.returnValue = false; |
60 | | - } |
61 | | - } |
62 | | - }; |
63 | | - var res = paper.tool[toolHandler](keyEvent); |
64 | | - // PORT: Add to Sg |
65 | | - // When the handler function returns false, prevent the |
66 | | - // default behaviour of the key event: |
67 | | - if (res === false) |
68 | | - keyEvent.preventDefault(); |
| 46 | + |
| 47 | + keyCodes = {}, |
| 48 | + downCode, |
| 49 | + downTimer; |
| 50 | + |
| 51 | + function handleKey(down, code, event) { |
| 52 | + var character = String.fromCharCode(code), |
| 53 | + keyCode = keys[code] || character.toLowerCase(), |
| 54 | + handler = down ? 'onKeyDown' : 'onKeyUp'; |
| 55 | + console.log(handler, keyCode, character); |
| 56 | + if (modifiers[keyCode] !== undefined) { |
| 57 | + modifiers[keyCode] = down; |
| 58 | + } else if (paper.tool && paper.tool[handler]) { |
| 59 | + // Call the onKeyDown or onKeyUp handler if present |
| 60 | + // When the handler function returns false, prevent the |
| 61 | + // default behaviour of the key event: |
| 62 | + // PORT: Add to Sg |
| 63 | + var keyEvent = new KeyEvent(down, keyCode, character, event); |
| 64 | + if (paper.tool[handler](keyEvent) === false) { |
| 65 | + keyEvent.preventDefault(); |
69 | 66 | } |
70 | | - }; |
71 | | - }, {})); |
72 | | - |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + // Since only keypress gest proper keyCodes that are actually representing |
| 71 | + // characters, we need to add a little timeout to keydown events to see if |
| 72 | + // they are follow immediately by a keypress, and if so, map the keyCode |
| 73 | + // from the keydown to the one from keypress, so keyup still knows what |
| 74 | + // code has now been released. |
| 75 | + DomEvent.add(document, { |
| 76 | + keydown: function(event) { |
| 77 | + var code = downCode = event.which || event.keyCode; |
| 78 | + downTimer = setTimeout(function() { |
| 79 | + keyCodes[code] = code; |
| 80 | + handleKey(true, code, event); |
| 81 | + }, 1); |
| 82 | + }, |
| 83 | + |
| 84 | + keypress: function(event) { |
| 85 | + clearTimeout(downTimer); |
| 86 | + var code = event.which || event.keyCode; |
| 87 | + keyCodes[downCode] = code; |
| 88 | + handleKey(true, code, event); |
| 89 | + }, |
| 90 | + |
| 91 | + keyup: function(event) { |
| 92 | + var code = event.which || event.keyCode; |
| 93 | + handleKey(false, keyCodes[code], event); |
| 94 | + delete keyCodes[code]; |
| 95 | + } |
| 96 | + }); |
| 97 | + |
73 | 98 | return { |
74 | 99 | modifiers: modifiers, |
| 100 | + |
75 | 101 | isDown: function(key) { |
76 | 102 | return !!activeKeys[key]; |
77 | 103 | } |
|
0 commit comments