diff --git a/javascript/src/js/editor/mxDefaultKeyHandler.js b/javascript/src/js/editor/mxDefaultKeyHandler.js index 237dea444..32b00a77e 100644 --- a/javascript/src/js/editor/mxDefaultKeyHandler.js +++ b/javascript/src/js/editor/mxDefaultKeyHandler.js @@ -2,6 +2,10 @@ * Copyright (c) 2006-2015, JGraph Ltd * Copyright (c) 2006-2015, Gaudenz Alder */ + +import mxKeyHandler from "../handler/mxKeyHandler"; +import mxEventObject from "../util/mxEventObject"; + /** * Class: mxDefaultKeyHandler * @@ -10,117 +14,111 @@ * only cancel the editing, but also hide the properties dialog and fire an * event via . An instance of this class is created * by and stored in . - * + * * Example: - * + * * Bind the delete key to the delete action in an existing editor. - * + * * (code) - * var keyHandler = new mxDefaultKeyHandler(editor); + * let keyHandler = new mxDefaultKeyHandler(editor); * keyHandler.bindAction(46, 'delete'); * (end) * * Codec: - * + * * This class uses the to read configuration * data into an existing instance. See for a * description of the configuration format. - * + * * Keycodes: - * + * * See . - * + * * An event is fired via the editor if the escape key is * pressed. - * + * * Constructor: mxDefaultKeyHandler * * Constructs a new default key handler for the in the * given . (The editor may be null if a prototypical instance for * a is created.) - * + * * Parameters: - * + * * editor - Reference to the enclosing . */ -function mxDefaultKeyHandler(editor) -{ - if (editor != null) - { - this.editor = editor; - this.handler = new mxKeyHandler(editor.graph); - - // Extends the escape function of the internal key - // handle to hide the properties dialog and fire - // the escape event via the editor instance - var old = this.handler.escape; - - this.handler.escape = function(evt) - { - old.apply(this, arguments); - editor.hideProperties(); - editor.fireEvent(new mxEventObject(mxEvent.ESCAPE, 'event', evt)); - }; - } -}; - -/** - * Variable: editor - * - * Reference to the enclosing . - */ -mxDefaultKeyHandler.prototype.editor = null; +class mxDefaultKeyHandler { + /** + * Variable: editor + * + * Reference to the enclosing . + */ + editor = null; -/** - * Variable: handler - * - * Holds the for key event handling. - */ -mxDefaultKeyHandler.prototype.handler = null; + /** + * Variable: handler + * + * Holds the for key event handling. + */ + handler = null; -/** - * Function: bindAction - * - * Binds the specified keycode to the given action in . The - * optional control flag specifies if the control key must be pressed - * to trigger the action. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * action - Name of the action to execute in . - * control - Optional boolean that specifies if control must be pressed. - * Default is false. - */ -mxDefaultKeyHandler.prototype.bindAction = function (code, action, control) -{ - var keyHandler = mxUtils.bind(this, function() - { - this.editor.execute(action); - }); + constructor(editor) { + if (editor != null) { + this.editor = editor; + this.handler = new mxKeyHandler(editor.graph); - // Binds the function to control-down keycode - if (control) - { - this.handler.bindControlKey(code, keyHandler); - } + // Extends the escape function of the internal key + // handle to hide the properties dialog and fire + // the escape event via the editor instance + let old = this.handler.escape; - // Binds the function to the normal keycode - else - { - this.handler.bindKey(code, keyHandler); - } -}; + this.handler.escape = (evt)=>{ + old.apply(this, arguments); + editor.hideProperties(); + editor.fireEvent(new mxEventObject(mxEvent.ESCAPE, 'event', evt)); + }; + } + }; -/** - * Function: destroy - * - * Destroys the associated with this object. This does normally - * not need to be called, the is destroyed automatically when the - * window unloads (in IE) by . - */ -mxDefaultKeyHandler.prototype.destroy = function () -{ - this.handler.destroy(); - this.handler = null; -}; + /** + * Function: bindAction + * + * Binds the specified keycode to the given action in . The + * optional control flag specifies if the control key must be pressed + * to trigger the action. + * + * Parameters: + * + * code - Integer that specifies the keycode. + * action - Name of the action to execute in . + * control - Optional boolean that specifies if control must be pressed. + * Default is false. + */ + bindAction=(code, action, control)=>{ + let keyHandler = mxUtils.bind(this, ()=>{ + this.editor.execute(action); + }); + + if (control) { + // Binds the function to control-down keycode + this.handler.bindControlKey(code, keyHandler); + } else { + // Binds the function to the normal keycode + this.handler.bindKey(code, keyHandler); + } + }; + + /** + * Function: destroy + * + * Destroys the associated with this object. This does normally + * not need to be called, the is destroyed automatically when the + * window unloads (in IE) by . + */ + destroy=()=>{ + this.handler.destroy(); + this.handler = null; + }; +} + +export default mxDefaultKeyHandler; diff --git a/javascript/src/js/editor/mxDefaultPopupMenu.js b/javascript/src/js/editor/mxDefaultPopupMenu.js index 2f2e6e702..837772d88 100644 --- a/javascript/src/js/editor/mxDefaultPopupMenu.js +++ b/javascript/src/js/editor/mxDefaultPopupMenu.js @@ -2,6 +2,8 @@ * Copyright (c) 2006-2015, JGraph Ltd * Copyright (c) 2006-2015, Gaudenz Alder */ + + /** * Class: mxDefaultPopupMenu * @@ -10,18 +12,18 @@ * , the configuration is applied to the context and * the resulting menu items are added to the menu dynamically. See * for a description of the configuration format. - * + * * This class does not create the DOM nodes required for the popup menu, it * only parses an XML description to invoke the respective methods on an * each time the menu is displayed. * * Codec: - * + * * This class uses the to read configuration * data into an existing instance, however, the actual parsing is done * by this class during program execution, so the format is described * below. - * + * * Constructor: mxDefaultPopupMenu * * Constructs a new popupmenu-factory based on given configuration. @@ -30,277 +32,262 @@ * * config - XML node that contains the configuration data. */ -function mxDefaultPopupMenu(config) -{ - this.config = config; -}; +class mxDefaultPopupMenu { + /** + * Variable: imageBasePath + * + * Base path for all icon attributes in the config. Default is null. + */ + imageBasePath = null; -/** - * Variable: imageBasePath - * - * Base path for all icon attributes in the config. Default is null. - */ -mxDefaultPopupMenu.prototype.imageBasePath = null; + /** + * Variable: config + * + * XML node used as the description of new menu items. This node is + * used in to dynamically create the menu items if their + * respective conditions evaluate to true for the given arguments. + */ + config = null; -/** - * Variable: config - * - * XML node used as the description of new menu items. This node is - * used in to dynamically create the menu items if their - * respective conditions evaluate to true for the given arguments. - */ -mxDefaultPopupMenu.prototype.config = null; + constructor(config) { + this.config = config; + }; -/** - * Function: createMenu - * - * This function is called from to add items to the - * given menu based on . The config is a sequence of - * the following nodes and attributes. - * - * Child Nodes: - * - * add - Adds a new menu item. See below for attributes. - * separator - Adds a separator. No attributes. - * condition - Adds a custom condition. Name attribute. - * - * The add-node may have a child node that defines a function to be invoked - * before the action is executed (or instead of an action to be executed). - * - * Attributes: - * - * as - Resource key for the label (needs entry in property file). - * action - Name of the action to execute in enclosing editor. - * icon - Optional icon (relative/absolute URL). - * iconCls - Optional CSS class for the icon. - * if - Optional name of condition that must be true (see below). - * enabled-if - Optional name of condition that specifies if the menu item - * should be enabled. - * name - Name of custom condition. Only for condition nodes. - * - * Conditions: - * - * nocell - No cell under the mouse. - * ncells - More than one cell selected. - * notRoot - Drilling position is other than home. - * cell - Cell under the mouse. - * notEmpty - Exactly one cell with children under mouse. - * expandable - Exactly one expandable cell under mouse. - * collapsable - Exactly one collapsable cell under mouse. - * validRoot - Exactly one cell which is a possible root under mouse. - * swimlane - Exactly one cell which is a swimlane under mouse. - * - * Example: - * - * To add a new item for a given action to the popupmenu: - * - * (code) - * - * - * - * (end) - * - * To add a new item for a custom function: - * - * (code) - * - * - * - * (end) - * - * The above example invokes action1 with an additional third argument via - * the editor instance. The third argument is passed to the function that - * defines action1. If the add-node has no action-attribute, then only the - * function defined in the text content is executed, otherwise first the - * function and then the action defined in the action-attribute is - * executed. The function in the text content has 3 arguments, namely the - * instance, the instance under the mouse, and the - * native mouse event. - * - * Custom Conditions: - * - * To add a new condition for popupmenu items: - * - * (code) - * - * (end) - * - * The new condition can then be used in any item as follows: - * - * (code) - * - * (end) - * - * The order in which the items and conditions appear is not significant as - * all connditions are evaluated before any items are created. - * - * Parameters: - * - * editor - Enclosing instance. - * menu - that is used for adding items and separators. - * cell - Optional which is under the mousepointer. - * evt - Optional mouse event which triggered the menu. - */ -mxDefaultPopupMenu.prototype.createMenu = function(editor, menu, cell, evt) -{ - if (this.config != null) - { - var conditions = this.createConditions(editor, cell, evt); - var item = this.config.firstChild; + /** + * Function: createMenu + * + * This function is called from to add items to the + * given menu based on . The config is a sequence of + * the following nodes and attributes. + * + * Child Nodes: + * + * add - Adds a new menu item. See below for attributes. + * separator - Adds a separator. No attributes. + * condition - Adds a custom condition. Name attribute. + * + * The add-node may have a child node that defines a function to be invoked + * before the action is executed (or instead of an action to be executed). + * + * Attributes: + * + * as - Resource key for the label (needs entry in property file). + * action - Name of the action to execute in enclosing editor. + * icon - Optional icon (relative/absolute URL). + * iconCls - Optional CSS class for the icon. + * if - Optional name of condition that must be true (see below). + * enabled-if - Optional name of condition that specifies if the menu item + * should be enabled. + * name - Name of custom condition. Only for condition nodes. + * + * Conditions: + * + * nocell - No cell under the mouse. + * ncells - More than one cell selected. + * notRoot - Drilling position is other than home. + * cell - Cell under the mouse. + * notEmpty - Exactly one cell with children under mouse. + * expandable - Exactly one expandable cell under mouse. + * collapsable - Exactly one collapsable cell under mouse. + * validRoot - Exactly one cell which is a possible root under mouse. + * swimlane - Exactly one cell which is a swimlane under mouse. + * + * Example: + * + * To add a new item for a given action to the popupmenu: + * + * (code) + * + * + * + * (end) + * + * To add a new item for a custom function: + * + * (code) + * + * + * + * (end) + * + * The above example invokes action1 with an additional third argument via + * the editor instance. The third argument is passed to the function that + * defines action1. If the add-node has no action-attribute, then only the + * function defined in the text content is executed, otherwise first the + * function and then the action defined in the action-attribute is + * executed. The function in the text content has 3 arguments, namely the + * instance, the instance under the mouse, and the + * native mouse event. + * + * Custom Conditions: + * + * To add a new condition for popupmenu items: + * + * (code) + * + * (end) + * + * The new condition can then be used in any item as follows: + * + * (code) + * + * (end) + * + * The order in which the items and conditions appear is not significant as + * all connditions are evaluated before any items are created. + * + * Parameters: + * + * editor - Enclosing instance. + * menu - that is used for adding items and separators. + * cell - Optional which is under the mousepointer. + * evt - Optional mouse event which triggered the menu. + */ + createMenu=(editor, menu, cell, evt)=>{ + if (this.config != null) { + let conditions = this.createConditions(editor, cell, evt); + let item = this.config.firstChild; - this.addItems(editor, menu, cell, evt, conditions, item, null); - } -}; + this.addItems(editor, menu, cell, evt, conditions, item, null); + } + }; -/** - * Function: addItems - * - * Recursively adds the given items and all of its children into the given menu. - * - * Parameters: - * - * editor - Enclosing instance. - * menu - that is used for adding items and separators. - * cell - Optional which is under the mousepointer. - * evt - Optional mouse event which triggered the menu. - * conditions - Array of names boolean conditions. - * item - XML node that represents the current menu item. - * parent - DOM node that represents the parent menu item. - */ -mxDefaultPopupMenu.prototype.addItems = function(editor, menu, cell, evt, conditions, item, parent) -{ - var addSeparator = false; - - while (item != null) - { - if (item.nodeName == 'add') - { - var condition = item.getAttribute('if'); - - if (condition == null || conditions[condition]) - { - var as = item.getAttribute('as'); - as = mxResources.get(as) || as; - var funct = mxUtils.eval(mxUtils.getTextContent(item)); - var action = item.getAttribute('action'); - var icon = item.getAttribute('icon'); - var iconCls = item.getAttribute('iconCls'); - var enabledCond = item.getAttribute('enabled-if'); - var enabled = enabledCond == null || conditions[enabledCond]; - - if (addSeparator) - { - menu.addSeparator(parent); - addSeparator = false; - } - - if (icon != null && this.imageBasePath) - { - icon = this.imageBasePath + icon; - } - - var row = this.addAction(menu, editor, as, icon, funct, action, cell, parent, iconCls, enabled); - this.addItems(editor, menu, cell, evt, conditions, item.firstChild, row); - } - } - else if (item.nodeName == 'separator') - { - addSeparator = true; - } - - item = item.nextSibling; - } -}; + /** + * Function: addItems + * + * Recursively adds the given items and all of its children into the given menu. + * + * Parameters: + * + * editor - Enclosing instance. + * menu - that is used for adding items and separators. + * cell - Optional which is under the mousepointer. + * evt - Optional mouse event which triggered the menu. + * conditions - Array of names boolean conditions. + * item - XML node that represents the current menu item. + * parent - DOM node that represents the parent menu item. + */ + addItems=(editor, menu, cell, evt, conditions, item, parent)=>{ + let addSeparator = false; -/** - * Function: addAction - * - * Helper method to bind an action to a new menu item. - * - * Parameters: - * - * menu - that is used for adding items and separators. - * editor - Enclosing instance. - * lab - String that represents the label of the menu item. - * icon - Optional URL that represents the icon of the menu item. - * action - Optional name of the action to execute in the given editor. - * funct - Optional function to execute before the optional action. The - * function takes an , the under the mouse and the - * mouse event that triggered the call. - * cell - Optional to use as an argument for the action. - * parent - DOM node that represents the parent menu item. - * iconCls - Optional CSS class for the menu icon. - * enabled - Optional boolean that specifies if the menu item is enabled. - * Default is true. - */ -mxDefaultPopupMenu.prototype.addAction = function(menu, editor, lab, icon, funct, action, cell, parent, iconCls, enabled) -{ - var clickHandler = function(evt) - { - if (typeof(funct) == 'function') - { - funct.call(editor, editor, cell, evt); - } - - if (action != null) - { - editor.execute(action, cell, evt); - } - }; - - return menu.addItem(lab, icon, clickHandler, parent, iconCls, enabled); -}; + while (item != null) { + if (item.nodeName === 'add') { + let condition = item.getAttribute('if'); -/** - * Function: createConditions - * - * Evaluates the default conditions for the given context. - */ -mxDefaultPopupMenu.prototype.createConditions = function(editor, cell, evt) -{ - // Creates array with conditions - var model = editor.graph.getModel(); - var childCount = model.getChildCount(cell); - - // Adds some frequently used conditions - var conditions = []; - conditions['nocell'] = cell == null; - conditions['ncells'] = editor.graph.getSelectionCount() > 1; - conditions['notRoot'] = model.getRoot() != - model.getParent(editor.graph.getDefaultParent()); - conditions['cell'] = cell != null; - - var isCell = cell != null && editor.graph.getSelectionCount() == 1; - conditions['nonEmpty'] = isCell && childCount > 0; - conditions['expandable'] = isCell && editor.graph.isCellFoldable(cell, false); - conditions['collapsable'] = isCell && editor.graph.isCellFoldable(cell, true); - conditions['validRoot'] = isCell && editor.graph.isValidRoot(cell); - conditions['emptyValidRoot'] = conditions['validRoot'] && childCount == 0; - conditions['swimlane'] = isCell && editor.graph.isSwimlane(cell); + if (condition == null || conditions[condition]) { + let as = item.getAttribute('as'); + as = mxResources.get(as) || as; + let funct = mxUtils.eval(mxUtils.getTextContent(item)); + let action = item.getAttribute('action'); + let icon = item.getAttribute('icon'); + let iconCls = item.getAttribute('iconCls'); + let enabledCond = item.getAttribute('enabled-if'); + let enabled = enabledCond == null || conditions[enabledCond]; - // Evaluates dynamic conditions from config file - var condNodes = this.config.getElementsByTagName('condition'); - - for (var i=0; i that is used for adding items and separators. + * editor - Enclosing instance. + * lab - String that represents the label of the menu item. + * icon - Optional URL that represents the icon of the menu item. + * action - Optional name of the action to execute in the given editor. + * funct - Optional function to execute before the optional action. The + * function takes an , the under the mouse and the + * mouse event that triggered the call. + * cell - Optional to use as an argument for the action. + * parent - DOM node that represents the parent menu item. + * iconCls - Optional CSS class for the menu icon. + * enabled - Optional boolean that specifies if the menu item is enabled. + * Default is true. + */ + addAction=(menu, editor, lab, icon, funct, action, cell, parent, iconCls, enabled)=>{ + let clickHandler=(evt)=>{ + if (typeof(funct) == 'function') { + funct.call(editor, editor, cell, evt); + } + if (action != null) { + editor.execute(action, cell, evt); + } + }; + return menu.addItem(lab, icon, clickHandler, parent, iconCls, enabled); + }; + + /** + * Function: createConditions + * + * Evaluates the default conditions for the given context. + */ + createConditions=(editor, cell, evt)=>{ + // Creates array with conditions + let model = editor.graph.getModel(); + let childCount = model.getChildCount(cell); + + // Adds some frequently used conditions + let conditions = []; + conditions['nocell'] = cell == null; + conditions['ncells'] = editor.graph.getSelectionCount() > 1; + conditions['notRoot'] = model.getRoot() != model.getParent(editor.graph.getDefaultParent()); + conditions['cell'] = cell != null; + + let isCell = cell != null && editor.graph.getSelectionCount() === 1; + conditions['nonEmpty'] = isCell && childCount > 0; + conditions['expandable'] = isCell && editor.graph.isCellFoldable(cell, false); + conditions['collapsable'] = isCell && editor.graph.isCellFoldable(cell, true); + conditions['validRoot'] = isCell && editor.graph.isValidRoot(cell); + conditions['emptyValidRoot'] = conditions['validRoot'] && childCount === 0; + conditions['swimlane'] = isCell && editor.graph.isSwimlane(cell); + + // Evaluates dynamic conditions from config file + let condNodes = this.config.getElementsByTagName('condition'); + + for (let i=0; i