diff options
author | adhitya | 2016-04-11 15:10:54 +0000 |
---|---|---|
committer | adhitya | 2016-04-11 15:10:54 +0000 |
commit | 92f3207b50a1caca07df5c5b238212af3358905b (patch) | |
tree | 38c92f9649c6f1016d2ef70fa2fd33c86b437cba /src/js/util/mxPopupMenu.js | |
parent | ab5fb6e125d82fdd5818aea3ce370c43c2293ddd (diff) | |
download | xcos-on-web-92f3207b50a1caca07df5c5b238212af3358905b.tar.gz xcos-on-web-92f3207b50a1caca07df5c5b238212af3358905b.tar.bz2 xcos-on-web-92f3207b50a1caca07df5c5b238212af3358905b.zip |
Revert last two commits - Keyboard shortcuts are not working
Diffstat (limited to 'src/js/util/mxPopupMenu.js')
-rw-r--r-- | src/js/util/mxPopupMenu.js | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/src/js/util/mxPopupMenu.js b/src/js/util/mxPopupMenu.js new file mode 100644 index 0000000..b188cb6 --- /dev/null +++ b/src/js/util/mxPopupMenu.js @@ -0,0 +1,574 @@ +/** + * $Id: mxPopupMenu.js,v 1.37 2012-04-22 10:16:23 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxPopupMenu + * + * Event handler that pans and creates popupmenus. To use the left + * mousebutton for panning without interfering with cell moving and + * resizing, use <isUseLeftButton> and <isIgnoreCell>. For grid size + * steps while panning, use <useGrid>. This handler is built-into + * <mxGraph.panningHandler> and enabled using <mxGraph.setPanning>. + * + * Constructor: mxPopupMenu + * + * Constructs an event handler that creates a popupmenu. The + * event handler is not installed anywhere in this ctor. + * + * Event: mxEvent.SHOW + * + * Fires after the menu has been shown in <popup>. + */ +function mxPopupMenu(factoryMethod) +{ + this.factoryMethod = factoryMethod; + + if (factoryMethod != null) + { + this.init(); + } +}; + +/** + * Extends mxEventSource. + */ +mxPopupMenu.prototype = new mxEventSource(); +mxPopupMenu.prototype.constructor = mxPopupMenu; + +/** + * Variable: submenuImage + * + * URL of the image to be used for the submenu icon. + */ +mxPopupMenu.prototype.submenuImage = mxClient.imageBasePath + '/submenu.gif'; + +/** + * Variable: zIndex + * + * Specifies the zIndex for the popupmenu and its shadow. Default is 1006. + */ +mxPopupMenu.prototype.zIndex = 10006; + +/** + * Variable: factoryMethod + * + * Function that is used to create the popup menu. The function takes the + * current panning handler, the <mxCell> under the mouse and the mouse + * event that triggered the call as arguments. + */ +mxPopupMenu.prototype.factoryMethod = null; + +/** + * Variable: useLeftButtonForPopup + * + * Specifies if popupmenus should be activated by clicking the left mouse + * button. Default is false. + */ +mxPopupMenu.prototype.useLeftButtonForPopup = false; + +/** + * Variable: enabled + * + * Specifies if events are handled. Default is true. + */ +mxPopupMenu.prototype.enabled = true; + +/** + * Variable: itemCount + * + * Contains the number of times <addItem> has been called for a new menu. + */ +mxPopupMenu.prototype.itemCount = 0; + +/** + * Variable: autoExpand + * + * Specifies if submenus should be expanded on mouseover. Default is false. + */ +mxPopupMenu.prototype.autoExpand = false; + +/** + * Variable: smartSeparators + * + * Specifies if separators should only be added if a menu item follows them. + * Default is false. + */ +mxPopupMenu.prototype.smartSeparators = false; + +/** + * Variable: labels + * + * Specifies if any labels should be visible. Default is true. + */ +mxPopupMenu.prototype.labels = true; + +/** + * Function: init + * + * Initializes the shapes required for this vertex handler. + */ +mxPopupMenu.prototype.init = function() +{ + // Adds the inner table + this.table = document.createElement('table'); + this.table.className = 'mxPopupMenu'; + + this.tbody = document.createElement('tbody'); + this.table.appendChild(this.tbody); + + // Adds the outer div + this.div = document.createElement('div'); + this.div.className = 'mxPopupMenu'; + this.div.style.display = 'inline'; + this.div.style.zIndex = this.zIndex; + this.div.appendChild(this.table); + + // Disables the context menu on the outer div + mxEvent.disableContextMenu(this.div); +}; + +/** + * Function: isEnabled + * + * Returns true if events are handled. This implementation + * returns <enabled>. + */ +mxPopupMenu.prototype.isEnabled = function() +{ + return this.enabled; +}; + +/** + * Function: setEnabled + * + * Enables or disables event handling. This implementation + * updates <enabled>. + */ +mxPopupMenu.prototype.setEnabled = function(enabled) +{ + this.enabled = enabled; +}; + +/** + * Function: isPopupTrigger + * + * Returns true if the given event is a popupmenu trigger for the optional + * given cell. + * + * Parameters: + * + * me - <mxMouseEvent> that represents the mouse event. + */ +mxPopupMenu.prototype.isPopupTrigger = function(me) +{ + return me.isPopupTrigger() || (this.useLeftButtonForPopup && + mxEvent.isLeftMouseButton(me.getEvent())); +}; + +/** + * Function: addItem + * + * Adds the given item to the given parent item. If no parent item is specified + * then the item is added to the top-level menu. The return value may be used + * as the parent argument, ie. as a submenu item. The return value is the table + * row that represents the item. + * + * Paramters: + * + * title - String that represents the title of the menu item. + * image - Optional URL for the image icon. + * funct - Function associated that takes a mouseup or touchend event. + * parent - Optional item returned by <addItem>. + * iconCls - Optional string that represents the CSS class for the image icon. + * IconsCls is ignored if image is given. + * enabled - Optional boolean indicating if the item is enabled. Default is true. + */ +mxPopupMenu.prototype.addItem = function(title, image, funct, parent, iconCls, enabled) +{ + parent = parent || this; + this.itemCount++; + + // Smart separators only added if element contains items + if (parent.willAddSeparator) + { + if (parent.containsItems) + { + this.addSeparator(parent, true); + } + + parent.willAddSeparator = false; + } + + parent.containsItems = true; + var tr = document.createElement('tr'); + tr.className = 'mxPopupMenuItem'; + var col1 = document.createElement('td'); + col1.className = 'mxPopupMenuIcon'; + + // Adds the given image into the first column + if (image != null) + { + var img = document.createElement('img'); + img.src = image; + col1.appendChild(img); + } + else if (iconCls != null) + { + var div = document.createElement('div'); + div.className = iconCls; + col1.appendChild(div); + } + + tr.appendChild(col1); + + if (this.labels) + { + var col2 = document.createElement('td'); + col2.className = 'mxPopupMenuItem' + + ((enabled != null && !enabled) ? ' disabled' : ''); + mxUtils.write(col2, title); + col2.align = 'left'; + tr.appendChild(col2); + + var col3 = document.createElement('td'); + col3.className = 'mxPopupMenuItem' + + ((enabled != null && !enabled) ? ' disabled' : ''); + col3.style.paddingRight = '6px'; + col3.style.textAlign = 'right'; + + tr.appendChild(col3); + + if (parent.div == null) + { + this.createSubmenu(parent); + } + } + + parent.tbody.appendChild(tr); + + if (enabled == null || enabled) + { + var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown'; + var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove'; + var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup'; + + // Consumes the event on mouse down + mxEvent.addListener(tr, md, mxUtils.bind(this, function(evt) + { + this.eventReceiver = tr; + + if (parent.activeRow != tr && parent.activeRow != parent) + { + if (parent.activeRow != null && + parent.activeRow.div.parentNode != null) + { + this.hideSubmenu(parent); + } + + if (tr.div != null) + { + this.showSubmenu(parent, tr); + parent.activeRow = tr; + } + } + + mxEvent.consume(evt); + })); + + mxEvent.addListener(tr, mm, mxUtils.bind(this, function(evt) + { + if (parent.activeRow != tr && parent.activeRow != parent) + { + if (parent.activeRow != null && + parent.activeRow.div.parentNode != null) + { + this.hideSubmenu(parent); + } + + if (this.autoExpand && tr.div != null) + { + this.showSubmenu(parent, tr); + parent.activeRow = tr; + } + } + + // Sets hover style because TR in IE doesn't have hover + tr.className = 'mxPopupMenuItemHover'; + })); + + mxEvent.addListener(tr, mu, mxUtils.bind(this, function(evt) + { + // EventReceiver avoids clicks on a submenu item + // which has just been shown in the mousedown + if (this.eventReceiver == tr) + { + if (parent.activeRow != tr) + { + this.hideMenu(); + } + + if (funct != null) + { + funct(evt); + } + } + + this.eventReceiver = null; + mxEvent.consume(evt); + })); + + // Resets hover style because TR in IE doesn't have hover + mxEvent.addListener(tr, 'mouseout', + mxUtils.bind(this, function(evt) + { + tr.className = 'mxPopupMenuItem'; + }) + ); + } + + return tr; +}; + +/** + * Function: createSubmenu + * + * Creates the nodes required to add submenu items inside the given parent + * item. This is called in <addItem> if a parent item is used for the first + * time. This adds various DOM nodes and a <submenuImage> to the parent. + * + * Parameters: + * + * parent - An item returned by <addItem>. + */ +mxPopupMenu.prototype.createSubmenu = function(parent) +{ + parent.table = document.createElement('table'); + parent.table.className = 'mxPopupMenu'; + + parent.tbody = document.createElement('tbody'); + parent.table.appendChild(parent.tbody); + + parent.div = document.createElement('div'); + parent.div.className = 'mxPopupMenu'; + + parent.div.style.position = 'absolute'; + parent.div.style.display = 'inline'; + parent.div.style.zIndex = this.zIndex; + + parent.div.appendChild(parent.table); + + var img = document.createElement('img'); + img.setAttribute('src', this.submenuImage); + + // Last column of the submenu item in the parent menu + td = parent.firstChild.nextSibling.nextSibling; + td.appendChild(img); +}; + +/** + * Function: showSubmenu + * + * Shows the submenu inside the given parent row. + */ +mxPopupMenu.prototype.showSubmenu = function(parent, row) +{ + if (row.div != null) + { + row.div.style.left = (parent.div.offsetLeft + + row.offsetLeft+row.offsetWidth - 1) + 'px'; + row.div.style.top = (parent.div.offsetTop+row.offsetTop) + 'px'; + document.body.appendChild(row.div); + + // Moves the submenu to the left side if there is no space + var left = parseInt(row.div.offsetLeft); + var width = parseInt(row.div.offsetWidth); + + var b = document.body; + var d = document.documentElement; + + var right = (b.scrollLeft || d.scrollLeft) + (b.clientWidth || d.clientWidth); + + if (left + width > right) + { + row.div.style.left = (parent.div.offsetLeft - width + + ((mxClient.IS_IE) ? 6 : -6)) + 'px'; + } + + mxUtils.fit(row.div); + } +}; + +/** + * Function: addSeparator + * + * Adds a horizontal separator in the given parent item or the top-level menu + * if no parent is specified. + * + * Parameters: + * + * parent - Optional item returned by <addItem>. + * force - Optional boolean to ignore <smartSeparators>. Default is false. + */ +mxPopupMenu.prototype.addSeparator = function(parent, force) +{ + parent = parent || this; + + if (this.smartSeparators && !force) + { + parent.willAddSeparator = true; + } + else if (parent.tbody != null) + { + parent.willAddSeparator = false; + var tr = document.createElement('tr'); + + var col1 = document.createElement('td'); + col1.className = 'mxPopupMenuIcon'; + col1.style.padding = '0 0 0 0px'; + + tr.appendChild(col1); + + var col2 = document.createElement('td'); + col2.style.padding = '0 0 0 0px'; + col2.setAttribute('colSpan', '2'); + + var hr = document.createElement('hr'); + hr.setAttribute('size', '1'); + col2.appendChild(hr); + + tr.appendChild(col2); + + parent.tbody.appendChild(tr); + } +}; + +/** + * Function: popup + * + * Shows the popup menu for the given event and cell. + * + * Example: + * + * (code) + * graph.panningHandler.popup = function(x, y, cell, evt) + * { + * mxUtils.alert('Hello, World!'); + * } + * (end) + */ +mxPopupMenu.prototype.popup = function(x, y, cell, evt) +{ + if (this.div != null && this.tbody != null && this.factoryMethod != null) + { + this.div.style.left = x + 'px'; + this.div.style.top = y + 'px'; + + // Removes all child nodes from the existing menu + while (this.tbody.firstChild != null) + { + mxEvent.release(this.tbody.firstChild); + this.tbody.removeChild(this.tbody.firstChild); + } + + this.itemCount = 0; + this.factoryMethod(this, cell, evt); + + if (this.itemCount > 0) + { + this.showMenu(); + this.fireEvent(new mxEventObject(mxEvent.SHOW)); + } + } +}; + +/** + * Function: isMenuShowing + * + * Returns true if the menu is showing. + */ +mxPopupMenu.prototype.isMenuShowing = function() +{ + return this.div != null && this.div.parentNode == document.body; +}; + +/** + * Function: showMenu + * + * Shows the menu. + */ +mxPopupMenu.prototype.showMenu = function() +{ + // Disables filter-based shadow in IE9 standards mode + if (document.documentMode >= 9) + { + this.div.style.filter = 'none'; + } + + // Fits the div inside the viewport + document.body.appendChild(this.div); + mxUtils.fit(this.div); +}; + +/** + * Function: hideMenu + * + * Removes the menu and all submenus. + */ +mxPopupMenu.prototype.hideMenu = function() +{ + if (this.div != null) + { + if (this.div.parentNode != null) + { + this.div.parentNode.removeChild(this.div); + } + + this.hideSubmenu(this); + this.containsItems = false; + } +}; + +/** + * Function: hideSubmenu + * + * Removes all submenus inside the given parent. + * + * Parameters: + * + * parent - An item returned by <addItem>. + */ +mxPopupMenu.prototype.hideSubmenu = function(parent) +{ + if (parent.activeRow != null) + { + this.hideSubmenu(parent.activeRow); + + if (parent.activeRow.div.parentNode != null) + { + parent.activeRow.div.parentNode.removeChild(parent.activeRow.div); + } + + parent.activeRow = null; + } +}; + +/** + * Function: destroy + * + * Destroys the handler and all its resources and DOM nodes. + */ +mxPopupMenu.prototype.destroy = function() +{ + if (this.div != null) + { + mxEvent.release(this.div); + + if (this.div.parentNode != null) + { + this.div.parentNode.removeChild(this.div); + } + + this.div = null; + } +}; |