123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- /**
- * Copyright (c) 2006-2015, JGraph Ltd
- * Copyright (c) 2006-2015, Gaudenz Alder
- */
- /**
- * 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 = [];
-
- this.keydownHandler = mxUtils.bind(this, function(evt)
- {
- this.keyDown(evt);
- });
- // Installs the keystroke listener in the target
- mxEvent.addListener(this.target, 'keydown', this.keydownHandler);
-
- // 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 && !mxEvent.isAltDown(evt))
- {
- 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 && this.graph.cellEditor.isEventSource(evt)))
- {
- return true;
- }
-
- // Accepts events from inside the container
- return mxUtils.isAncestorNode(this.graph.container, source);
- };
- /**
- * Function: keyDown
- *
- * Handles the event by invoking the function bound to the respective keystroke
- * if <isEnabledForEvent> returns true for the given event and if
- * <isEventIgnored> returns false, except for escape for which
- * <isEventIgnored> is not invoked.
- *
- * Parameters:
- *
- * evt - Key event that represents the keystroke.
- */
- mxKeyHandler.prototype.keyDown = function(evt)
- {
- if (this.isEnabledForEvent(evt))
- {
- // Cancels the editing if escape is pressed
- if (evt.keyCode == 27 /* Escape */)
- {
- this.escape(evt);
- }
-
- // Invokes the function for the keystroke
- else if (!this.isEventIgnored(evt))
- {
- var boundFunction = this.getFunction(evt);
-
- if (boundFunction != null)
- {
- boundFunction(evt);
- mxEvent.consume(evt);
- }
- }
- }
- };
- /**
- * Function: isEnabledForEvent
- *
- * Returns true if the given event should be handled. <isEventIgnored> is
- * called later if the event is not an escape key stroke, in which case
- * <escape> is called. This implementation returns true if <isEnabled>
- * returns true for both, this handler and <graph>, if the event is not
- * consumed and if <isGraphEvent> returns true.
- *
- * Parameters:
- *
- * evt - Key event that represents the keystroke.
- */
- mxKeyHandler.prototype.isEnabledForEvent = function(evt)
- {
- return (this.graph.isEnabled() && !mxEvent.isConsumed(evt) &&
- this.isGraphEvent(evt) && this.isEnabled());
- };
- /**
- * Function: isEventIgnored
- *
- * Returns true if the given keystroke should be ignored. This returns
- * graph.isEditing().
- *
- * Parameters:
- *
- * evt - Key event that represents the keystroke.
- */
- mxKeyHandler.prototype.isEventIgnored = function(evt)
- {
- return this.graph.isEditing();
- };
- /**
- * 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()
- {
- if (this.target != null && this.keydownHandler != null)
- {
- mxEvent.removeListener(this.target, 'keydown', this.keydownHandler);
- this.keydownHandler = null;
- }
-
- this.target = null;
- };
- __mxOutput.mxKeyHandler = typeof mxKeyHandler !== 'undefined' ? mxKeyHandler : undefined;
|