summaryrefslogtreecommitdiff
path: root/src/js/handler/mxKeyHandler.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/handler/mxKeyHandler.js')
-rw-r--r--src/js/handler/mxKeyHandler.js402
1 files changed, 402 insertions, 0 deletions
diff --git a/src/js/handler/mxKeyHandler.js b/src/js/handler/mxKeyHandler.js
new file mode 100644
index 0000000..cc07e51
--- /dev/null
+++ b/src/js/handler/mxKeyHandler.js
@@ -0,0 +1,402 @@
+/**
+ * $Id: mxKeyHandler.js,v 1.48 2012-03-30 08:30:41 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxKeyHandler
+ *
+ * Event handler that listens to keystroke events. This is not a singleton,
+ * however, it is normally only required once if the target is the document
+ * element (default).
+ *
+ * This handler installs a key event listener in the topmost DOM node and
+ * processes all events that originate from descandants of <mxGraph.container>
+ * or from the topmost DOM node. The latter means that all unhandled keystrokes
+ * are handled by this object regardless of the focused state of the <graph>.
+ *
+ * Example:
+ *
+ * The following example creates a key handler that listens to the delete key
+ * (46) and deletes the selection cells if the graph is enabled.
+ *
+ * (code)
+ * var keyHandler = new mxKeyHandler(graph);
+ * keyHandler.bindKey(46, function(evt)
+ * {
+ * if (graph.isEnabled())
+ * {
+ * graph.removeCells();
+ * }
+ * });
+ * (end)
+ *
+ * Keycodes:
+ *
+ * See http://tinyurl.com/yp8jgl or http://tinyurl.com/229yqw for a list of
+ * keycodes or install a key event listener into the document element and print
+ * the key codes of the respective events to the console.
+ *
+ * To support the Command key and the Control key on the Mac, the following
+ * code can be used.
+ *
+ * (code)
+ * keyHandler.getFunction = function(evt)
+ * {
+ * if (evt != null)
+ * {
+ * return (mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey)) ? this.controlKeys[evt.keyCode] : this.normalKeys[evt.keyCode];
+ * }
+ *
+ * return null;
+ * };
+ * (end)
+ *
+ * Constructor: mxKeyHandler
+ *
+ * Constructs an event handler that executes functions bound to specific
+ * keystrokes.
+ *
+ * Parameters:
+ *
+ * graph - Reference to the associated <mxGraph>.
+ * target - Optional reference to the event target. If null, the document
+ * element is used as the event target, that is, the object where the key
+ * event listener is installed.
+ */
+function mxKeyHandler(graph, target)
+{
+ if (graph != null)
+ {
+ this.graph = graph;
+ this.target = target || document.documentElement;
+
+ // Creates the arrays to map from keycodes to functions
+ this.normalKeys = [];
+ this.shiftKeys = [];
+ this.controlKeys = [];
+ this.controlShiftKeys = [];
+
+ // Installs the keystroke listener in the target
+ mxEvent.addListener(this.target, "keydown",
+ mxUtils.bind(this, function(evt)
+ {
+ this.keyDown(evt);
+ })
+ );
+
+ // Automatically deallocates memory in IE
+ if (mxClient.IS_IE)
+ {
+ mxEvent.addListener(window, 'unload',
+ mxUtils.bind(this, function()
+ {
+ this.destroy();
+ })
+ );
+ }
+ }
+};
+
+/**
+ * Variable: graph
+ *
+ * Reference to the <mxGraph> associated with this handler.
+ */
+mxKeyHandler.prototype.graph = null;
+
+/**
+ * Variable: target
+ *
+ * Reference to the target DOM, that is, the DOM node where the key event
+ * listeners are installed.
+ */
+mxKeyHandler.prototype.target = null;
+
+/**
+ * Variable: normalKeys
+ *
+ * Maps from keycodes to functions for non-pressed control keys.
+ */
+mxKeyHandler.prototype.normalKeys = null;
+
+/**
+ * Variable: shiftKeys
+ *
+ * Maps from keycodes to functions for pressed shift keys.
+ */
+mxKeyHandler.prototype.shiftKeys = null;
+
+/**
+ * Variable: controlKeys
+ *
+ * Maps from keycodes to functions for pressed control keys.
+ */
+mxKeyHandler.prototype.controlKeys = null;
+
+/**
+ * Variable: controlShiftKeys
+ *
+ * Maps from keycodes to functions for pressed control and shift keys.
+ */
+mxKeyHandler.prototype.controlShiftKeys = null;
+
+/**
+ * Variable: enabled
+ *
+ * Specifies if events are handled. Default is true.
+ */
+mxKeyHandler.prototype.enabled = true;
+
+/**
+ * Function: isEnabled
+ *
+ * Returns true if events are handled. This implementation returns
+ * <enabled>.
+ */
+mxKeyHandler.prototype.isEnabled = function()
+{
+ return this.enabled;
+};
+
+/**
+ * Function: setEnabled
+ *
+ * Enables or disables event handling by updating <enabled>.
+ *
+ * Parameters:
+ *
+ * enabled - Boolean that specifies the new enabled state.
+ */
+mxKeyHandler.prototype.setEnabled = function(enabled)
+{
+ this.enabled = enabled;
+};
+
+/**
+ * Function: bindKey
+ *
+ * Binds the specified keycode to the given function. This binding is used
+ * if the control key is not pressed.
+ *
+ * Parameters:
+ *
+ * code - Integer that specifies the keycode.
+ * funct - JavaScript function that takes the key event as an argument.
+ */
+mxKeyHandler.prototype.bindKey = function(code, funct)
+{
+ this.normalKeys[code] = funct;
+};
+
+/**
+ * Function: bindShiftKey
+ *
+ * Binds the specified keycode to the given function. This binding is used
+ * if the shift key is pressed.
+ *
+ * Parameters:
+ *
+ * code - Integer that specifies the keycode.
+ * funct - JavaScript function that takes the key event as an argument.
+ */
+mxKeyHandler.prototype.bindShiftKey = function(code, funct)
+{
+ this.shiftKeys[code] = funct;
+};
+
+/**
+ * Function: bindControlKey
+ *
+ * Binds the specified keycode to the given function. This binding is used
+ * if the control key is pressed.
+ *
+ * Parameters:
+ *
+ * code - Integer that specifies the keycode.
+ * funct - JavaScript function that takes the key event as an argument.
+ */
+mxKeyHandler.prototype.bindControlKey = function(code, funct)
+{
+ this.controlKeys[code] = funct;
+};
+
+/**
+ * Function: bindControlShiftKey
+ *
+ * Binds the specified keycode to the given function. This binding is used
+ * if the control and shift key are pressed.
+ *
+ * Parameters:
+ *
+ * code - Integer that specifies the keycode.
+ * funct - JavaScript function that takes the key event as an argument.
+ */
+mxKeyHandler.prototype.bindControlShiftKey = function(code, funct)
+{
+ this.controlShiftKeys[code] = funct;
+};
+
+/**
+ * Function: isControlDown
+ *
+ * Returns true if the control key is pressed. This uses <mxEvent.isControlDown>.
+ *
+ * Parameters:
+ *
+ * evt - Key event whose control key pressed state should be returned.
+ */
+mxKeyHandler.prototype.isControlDown = function(evt)
+{
+ return mxEvent.isControlDown(evt);
+};
+
+/**
+ * Function: getFunction
+ *
+ * Returns the function associated with the given key event or null if no
+ * function is associated with the given event.
+ *
+ * Parameters:
+ *
+ * evt - Key event whose associated function should be returned.
+ */
+mxKeyHandler.prototype.getFunction = function(evt)
+{
+ if (evt != null)
+ {
+ if (this.isControlDown(evt))
+ {
+ if (mxEvent.isShiftDown(evt))
+ {
+ return this.controlShiftKeys[evt.keyCode];
+ }
+ else
+ {
+ return this.controlKeys[evt.keyCode];
+ }
+ }
+ else
+ {
+ if (mxEvent.isShiftDown(evt))
+ {
+ return this.shiftKeys[evt.keyCode];
+ }
+ else
+ {
+ return this.normalKeys[evt.keyCode];
+ }
+ }
+ }
+
+ return null;
+};
+
+/**
+ * Function: isGraphEvent
+ *
+ * Returns true if the event should be processed by this handler, that is,
+ * if the event source is either the target, one of its direct children, a
+ * descendant of the <mxGraph.container>, or the <mxGraph.cellEditor> of the
+ * <graph>.
+ *
+ * Parameters:
+ *
+ * evt - Key event that represents the keystroke.
+ */
+mxKeyHandler.prototype.isGraphEvent = function(evt)
+{
+ var source = mxEvent.getSource(evt);
+
+ // Accepts events from the target object or
+ // in-place editing inside graph
+ if ((source == this.target || source.parentNode == this.target) ||
+ (this.graph.cellEditor != null && source == this.graph.cellEditor.textarea))
+ {
+ return true;
+ }
+
+ // Accepts events from inside the container
+ var elt = source;
+
+ while (elt != null)
+ {
+ if (elt == this.graph.container)
+ {
+ return true;
+ }
+
+ elt = elt.parentNode;
+ }
+
+ return false;
+};
+
+/**
+ * Function: keyDown
+ *
+ * Handles the event by invoking the function bound to the respective
+ * keystroke if <mxGraph.isEnabled>, <isEnabled> and <isGraphEvent> all
+ * return true for the given event and <mxGraph.isEditing> returns false.
+ * If the graph is editing only the <enter> and <escape> cases are handled
+ * by calling the respective hooks.
+ *
+ * Parameters:
+ *
+ * evt - Key event that represents the keystroke.
+ */
+mxKeyHandler.prototype.keyDown = function(evt)
+{
+ if (this.graph.isEnabled() && !mxEvent.isConsumed(evt) &&
+ this.isGraphEvent(evt) && this.isEnabled())
+ {
+ // Cancels the editing if escape is pressed
+ if (evt.keyCode == 27 /* Escape */)
+ {
+ this.escape(evt);
+ }
+
+ // Invokes the function for the keystroke
+ else if (!this.graph.isEditing())
+ {
+ var boundFunction = this.getFunction(evt);
+
+ if (boundFunction != null)
+ {
+ boundFunction(evt);
+ mxEvent.consume(evt);
+ }
+ }
+ }
+};
+
+/**
+ * Function: escape
+ *
+ * Hook to process ESCAPE keystrokes. This implementation invokes
+ * <mxGraph.stopEditing> to cancel the current editing, connecting
+ * and/or other ongoing modifications.
+ *
+ * Parameters:
+ *
+ * evt - Key event that represents the keystroke. Possible keycode in this
+ * case is 27 (ESCAPE).
+ */
+mxKeyHandler.prototype.escape = function(evt)
+{
+ if (this.graph.isEscapeEnabled())
+ {
+ this.graph.escape(evt);
+ }
+};
+
+/**
+ * Function: destroy
+ *
+ * Destroys the handler and all its references into the DOM. This does
+ * normally not need to be called, it is called automatically when the
+ * window unloads (in IE).
+ */
+mxKeyHandler.prototype.destroy = function()
+{
+ this.target = null;
+};