aboutsummaryrefslogtreecommitdiff
path: root/sources/core/keystrokehandler.js
blob: 8d8b443b54f33d2b181dc87715689b2aa9420f04 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/**
 * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.md or http://ckeditor.com/license
 */

/**
 * Controls keystrokes typing in an editor instance.
 *
 * @class
 * @constructor Creates a keystrokeHandler class instance.
 * @param {CKEDITOR.editor} editor The editor instance.
 */
CKEDITOR.keystrokeHandler = function( editor ) {
	if ( editor.keystrokeHandler )
		return editor.keystrokeHandler;

	/**
	 * A list of keystrokes associated with commands. Each entry points to the
	 * command to be executed.
	 *
	 * Since CKEditor 4 there is no need to modify this property directly during the runtime.
	 * Use {@link CKEDITOR.editor#setKeystroke} instead.
	 */
	this.keystrokes = {};

	/**
	 * A list of keystrokes that should be blocked if not defined in
	 * {@link #keystrokes}. In this way it is possible to block the default
	 * browser behavior for those keystrokes.
	 */
	this.blockedKeystrokes = {};

	this._ = {
		editor: editor
	};

	return this;
};

( function() {
	var cancel;

	var onKeyDown = function( event ) {
			// The DOM event object is passed by the "data" property.
			event = event.data;

			var keyCombination = event.getKeystroke();
			var command = this.keystrokes[ keyCombination ];
			var editor = this._.editor;

			cancel = ( editor.fire( 'key', { keyCode: keyCombination, domEvent: event } ) === false );

			if ( !cancel ) {
				if ( command ) {
					var data = { from: 'keystrokeHandler' };
					cancel = ( editor.execCommand( command, data ) !== false );
				}

				if ( !cancel )
					cancel = !!this.blockedKeystrokes[ keyCombination ];
			}

			if ( cancel )
				event.preventDefault( true );

			return !cancel;
		};

	var onKeyPress = function( event ) {
			if ( cancel ) {
				cancel = false;
				event.data.preventDefault( true );
			}
		};

	CKEDITOR.keystrokeHandler.prototype = {
		/**
		 * Attaches this keystroke handle to a DOM object. Keystrokes typed
		 * over this object will be handled by this keystrokeHandler.
		 *
		 * @param {CKEDITOR.dom.domObject} domObject The DOM object to attach to.
		 */
		attach: function( domObject ) {
			// For most browsers, it is enough to listen to the keydown event
			// only.
			domObject.on( 'keydown', onKeyDown, this );

			// Some browsers instead, don't cancel key events in the keydown, but in the
			// keypress. So we must do a longer trip in those cases.
			if ( CKEDITOR.env.gecko && CKEDITOR.env.mac )
				domObject.on( 'keypress', onKeyPress, this );
		}
	};
} )();

/**
 * A list associating keystrokes with editor commands. Each element in the list
 * is an array where the first item is the keystroke, and the second is the
 * name of the command to be executed.
 *
 * This setting should be used to define (as well as to overwrite or remove) keystrokes
 * set by plugins (like `link` and `basicstyles`). If you want to set a keystroke
 * for your plugin or during the runtime, use {@link CKEDITOR.editor#setKeystroke} instead.
 *
 * Since default keystrokes are set by the {@link CKEDITOR.editor#setKeystroke}
 * method, by default `config.keystrokes` is an empty array.
 *
 * See {@link CKEDITOR.editor#setKeystroke} documentation for more details
 * regarding the start up order.
 *
 *		// Change default Ctrl+L keystroke for 'link' command to Ctrl+Shift+L.
 *		config.keystrokes = [
 *			...
 *			[ CKEDITOR.CTRL + CKEDITOR.SHIFT + 76, 'link' ],	// Ctrl+Shift+L
 *			...
 *		];
 *
 * To reset a particular keystroke, the following approach can be used:
 *
 *		// Disable default Ctrl+L keystroke which executes the 'link' command by default.
 *		config.keystrokes = [
 *			...
 *			[ CKEDITOR.CTRL + 76, null ],						// Ctrl+L
 *			...
 *		];
 *
 * In order to reset all default keystrokes, a {@link CKEDITOR#instanceReady} callback should be
 * used. This is since editor defaults are merged rather than overwritten by
 * user keystrokes.
 *
 * **Note**: This can be potentially harmful for the editor. Avoid this unless you are
 * aware of the consequences.
 *
 *		// Reset all default keystrokes.
 *		config.on.instanceReady = function() {
 *			this.keystrokeHandler.keystrokes = [];
 *		};
 *
 * @cfg {Array} [keystrokes=[]]
 * @member CKEDITOR.config
 */

/**
 * Fired when any keyboard key (or a combination thereof) is pressed in the editing area.
 *
 *		editor.on( 'key', function( evt ) {
 *			if ( evt.data.keyCode == CKEDITOR.CTRL + 90 ) {
 *				// Do something...
 *
 *				// Cancel the event, so other listeners will not be executed and
 *				// the keydown's default behavior will be prevented.
 *				evt.cancel();
 *			}
 *		} );
 *
 * Usually you will want to use the {@link CKEDITOR.editor#setKeystroke} method or
 * the {@link CKEDITOR.config#keystrokes} option to attach a keystroke to some {@link CKEDITOR.command command}.
 * Key event listeners are usuful when some action should be executed conditionally, based
 * for example on precise selection location.
 *
 * @event key
 * @member CKEDITOR.editor
 * @param data
 * @param {Number} data.keyCode A number representing the key code (or a combination thereof).
 * It is the sum of the current key code and the {@link CKEDITOR#CTRL}, {@link CKEDITOR#SHIFT}
 * and {@link CKEDITOR#ALT} constants, if those are pressed.
 * @param {CKEDITOR.dom.event} data.domEvent A `keydown` DOM event instance. Available since CKEditor 4.4.1.
 * @param {CKEDITOR.editor} editor This editor instance.
 */