summaryrefslogtreecommitdiff
path: root/src/js/util/mxPopupMenu.js
diff options
context:
space:
mode:
authoradhitya2016-04-11 15:10:54 +0000
committeradhitya2016-04-11 15:10:54 +0000
commit92f3207b50a1caca07df5c5b238212af3358905b (patch)
tree38c92f9649c6f1016d2ef70fa2fd33c86b437cba /src/js/util/mxPopupMenu.js
parentab5fb6e125d82fdd5818aea3ce370c43c2293ddd (diff)
downloadxcos-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.js574
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;
+ }
+};