aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorelijahe2013-12-19 14:54:27 (EST)
committerBogdan Gheorghe2013-12-19 16:30:14 (EST)
commit9e051d7fd13f732a46ec7ccd3d6b46157bb6249d (patch)
tree50bb71c351f81b165ae9ce0afbf52986f442d289
parentc2c9303504a1660643eda92449a335f99aa6d3e7 (diff)
downloadorg.eclipse.orion.client-9e051d7fd13f732a46ec7ccd3d6b46157bb6249d.zip
org.eclipse.orion.client-9e051d7fd13f732a46ec7ccd3d6b46157bb6249d.tar.gz
org.eclipse.orion.client-9e051d7fd13f732a46ec7ccd3d6b46157bb6249d.tar.bz2
Bug 421482 - UX: No context menu!
- Improved positioning of context menu and dropdown menu - Refactored positioning code --Signed-off-by: Elijah El-Haddad <elijahe@ca.ibm.com>
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/css/theme.css1
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/orion/webui/contextmenu.js68
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/orion/webui/dropdown.js26
3 files changed, 49 insertions, 46 deletions
diff --git a/bundles/org.eclipse.orion.client.ui/web/css/theme.css b/bundles/org.eclipse.orion.client.ui/web/css/theme.css
index 51286ba..30caff1 100644
--- a/bundles/org.eclipse.orion.client.ui/web/css/theme.css
+++ b/bundles/org.eclipse.orion.client.ui/web/css/theme.css
@@ -365,6 +365,7 @@ a.currentLocation:hover {
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);
display: none; /* don't take part in layout until open */
line-height: normal; /* don't want to inherit strange line-heights from ancestor elements */
+ margin: 0; /* needed for context menu positioning to work properly */
}
.dropdownMenuOpen {
diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/webui/contextmenu.js b/bundles/org.eclipse.orion.client.ui/web/orion/webui/contextmenu.js
index b058123..e9a4e1e 100644
--- a/bundles/org.eclipse.orion.client.ui/web/orion/webui/contextmenu.js
+++ b/bundles/org.eclipse.orion.client.ui/web/orion/webui/contextmenu.js
@@ -60,36 +60,6 @@ define([
this._triggerNode.addEventListener("click", this._boundContextMenuCloser, false);//$NON-NLS-0$
},
- _positionContextMenu: function(event) {
- var mouseLeft = event.clientX;
- var mouseTop = event.clientY;
-
- this._dropdownNode.style.left = mouseLeft + "px"; //$NON-NLS-0$
- this._dropdownNode.style.top = mouseTop + "px"; //$NON-NLS-0$
- this._dropdownNode.style.position = "fixed"; //$NON-NLS-0$ //TODO convert to absolute position
-
- var totalBounds = lib.bounds(this._boundingNode(this._triggerNode));
- var bounds = lib.bounds(this._dropdownNode);
- var bodyBounds = lib.bounds(document.body);
- var triggerBounds = lib.bounds(this._triggerNode);
-
- //ensure menu fits on page horizontally
- if ((bounds.left + bounds.width) > (bodyBounds.left + bodyBounds.width)) {
- if (this._triggerNode.classList.contains("dropdownMenuItem")) { //$NON-NLS-0$
- this._dropdownNode.style.left = -bounds.width + "px"; //$NON-NLS-0$
- } else {
- this._dropdownNode.style.left = (triggerBounds.left - totalBounds.left - bounds.width + triggerBounds.width) + "px"; //$NON-NLS-0$
- }
- }
-
- //ensure menu fits on page vertically
- var overflowY = (bounds.top + bounds.height) - (bodyBounds.top + bodyBounds.height);
- if (0 < overflowY) {
- //TODO improve bottom padding estimate
- this._dropdownNode.style.top = (bounds.top - overflowY) + "px"; //$NON-NLS-0$
- }
- },
-
_contextMenuCloser: function(event){
this.close(event);
},
@@ -105,15 +75,39 @@ define([
ContextMenu.prototype.constructor = ContextMenu;
- // overrides Dropdown.protoype.open
- ContextMenu.prototype.open = function(event /* optional */) {
- var actionTaken = Dropdown.prototype.open.call(this, event); //call function in super class
- if (actionTaken) {
- if (event) {
- this._positionContextMenu(event);
+ // overrides Dropdown.protoype._positionDropdown
+ ContextMenu.prototype._positionDropdown = function(mouseEvent) {
+ if (mouseEvent) {
+ var mouseLeft = mouseEvent.clientX;
+ var mouseTop = mouseEvent.clientY;
+
+ // we want the position to be relative to the mouse event
+ this._dropdownNode.style.position = "fixed"; //$NON-NLS-0$
+
+ // set the initial position
+ this._dropdownNode.style.left = mouseLeft + "px"; //$NON-NLS-0$
+ this._dropdownNode.style.top = mouseTop + "px"; //$NON-NLS-0$
+
+ // ensure that the menu fits on the page...
+ var bounds = lib.bounds(this._dropdownNode);
+ var width = bounds.width;
+ var height = bounds.height;
+ var bodyBounds = lib.bounds(document.body);
+
+ //ensure menu fits on page horizontally
+ var overflowX = (mouseLeft + width) - (bodyBounds.left + bodyBounds.width);
+ if (0 < overflowX) {
+ this._dropdownNode.style.left = Math.floor(mouseLeft - overflowX) + "px"; //$NON-NLS-0$
+ }
+
+ //ensure menu fits on page vertically
+ var overflowY = (mouseTop + height) - (bodyBounds.top + bodyBounds.height);
+ if (0 < overflowY) {
+ this._dropdownNode.style.top = Math.floor(mouseTop - overflowY) + "px"; //$NON-NLS-0$
}
+ } else {
+ Dropdown.prototype._positionDropdown.call(this); //call function in super class
}
- return actionTaken;
};
// overrides Dropdown.protoype.destroy
diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/webui/dropdown.js b/bundles/org.eclipse.orion.client.ui/web/orion/webui/dropdown.js
index 7758fa2..9c236a3 100644
--- a/bundles/org.eclipse.orion.client.ui/web/orion/webui/dropdown.js
+++ b/bundles/org.eclipse.orion.client.ui/web/orion/webui/dropdown.js
@@ -81,7 +81,7 @@ define(['require', 'orion/webui/littlelib', 'orion/EventTarget'], function(requi
var self = this;
// click on trigger opens.
this._triggerNode.addEventListener("click", function(event) { //$NON-NLS-0$
- if (self.toggle()) {
+ if (self.toggle(event)) {
lib.stop(event);
}
}, false);
@@ -104,11 +104,11 @@ define(['require', 'orion/webui/littlelib', 'orion/EventTarget'], function(requi
/**
* Toggle the open/closed state of the dropdown. Return a boolean that indicates whether action was taken.
*/
- toggle: function(event) {
+ toggle: function(mouseEvent /* optional */) {
if (this.isVisible()) {
return this.close();
} else {
- return this.open();
+ return this.open(mouseEvent);
}
},
@@ -122,10 +122,10 @@ define(['require', 'orion/webui/littlelib', 'orion/EventTarget'], function(requi
/**
* Open the dropdown.
*/
- open: function(event /* optional */) {
+ open: function(mouseEvent /* optional */) {
var actionTaken = false;
if (!this.isVisible()) {
- this.dispatchEvent({type: "triggered", dropdown: this, event: event}); //$NON-NLS-0$
+ this.dispatchEvent({type: "triggered", dropdown: this, event: mouseEvent}); //$NON-NLS-0$
lib.setFramesEnabled(false);
if (this._populate) {
this.empty();
@@ -151,7 +151,8 @@ define(['require', 'orion/webui/littlelib', 'orion/EventTarget'], function(requi
this._dropdownNode.classList.add("dropdownMenuOpen"); //$NON-NLS-0$
this._isVisible = true;
- this._positionDropdown();
+ this._positionDropdown(mouseEvent);
+
items[0].focus();
actionTaken = true;
@@ -178,7 +179,15 @@ define(['require', 'orion/webui/littlelib', 'orion/EventTarget'], function(requi
}
},
- _positionDropdown: function() {
+ /**
+ * This method positions the dropdown menu.
+ * The specified mouseEvent is ignored. However, subclasses
+ * can override this method if they wish to take the mouse
+ * position contained in the mouse event into account.
+ *
+ * @param {MouseEvent} mouseEvent
+ */
+ _positionDropdown: function(mouseEvent) {
this._dropdownNode.style.left = "";
this._dropdownNode.style.top = "";
@@ -197,8 +206,7 @@ define(['require', 'orion/webui/littlelib', 'orion/EventTarget'], function(requi
//ensure menu fits on page vertically
var overflowY = (bounds.top + bounds.height) - (bodyBounds.top + bodyBounds.height);
if (0 < overflowY) {
- //TODO (minor) figure out proper bottom padding amount
- this._dropdownNode.style.top = Math.ceil(this._dropdownNode.style.top - overflowY) + "px"; //$NON-NLS-0$
+ this._dropdownNode.style.top = Math.floor(this._dropdownNode.style.top - overflowY) + "px"; //$NON-NLS-0$
}
},