Merge branch 'master' of ssh://git.eclipse.org/gitroot/orion/org.eclipse.orion.client
diff --git a/bundles/org.eclipse.orion.client.core/web/css/ide.css b/bundles/org.eclipse.orion.client.core/web/css/ide.css
index f3ca7e5..c8c84d0 100644
--- a/bundles/org.eclipse.orion.client.core/web/css/ide.css
+++ b/bundles/org.eclipse.orion.client.core/web/css/ide.css
@@ -215,7 +215,6 @@
 	background-image: url(../images/core_sprites.png);
 	margin-left: 0px;
 	padding-right: 0px;
-	margin-top: 6px;
 }
 
 .thumbnail {
@@ -396,7 +395,6 @@
 	display: none;
 	vertical-align:middle;
 	font-size:11px;
-	font-weight:bold;
 	z-index: 50;
 }
 
@@ -826,40 +824,6 @@
 	left:50px;
 }
 
-.findSlideoutButton {
-	color: #222;
-	border: 1px solid transparent;
-	text-align: center;
-	vertical-align: top;
-    cursor: pointer;
-    display: inline-block;
-    padding: 2px;
-    margin-left: 8px;
-    border-radius:1px;
-    font-weight: normal;
-	-webkit-touch-callout: none;
-	-webkit-user-select: none;
-	-khtml-user-select: none;
-	-moz-user-select: none;
-	-ms-user-select: none;
-	user-select: none;
-}
-
-.findSlideoutMenu {
-	color: #222;
-	padding: 0;
-    font-weight: normal;
-    margin: 0;
-    margin-left: 8px;
-	text-align: center;
-	vertical-align: top;
-}
-
-.findSlideoutButton:hover {
-	background-color: #efefef;
-	border: 1px solid #222;
-}
-
 .targetSelector{
 
 }
diff --git a/bundles/org.eclipse.orion.client.core/web/css/layout.css b/bundles/org.eclipse.orion.client.core/web/css/layout.css
index 04d2941..f003e69 100644
--- a/bundles/org.eclipse.orion.client.core/web/css/layout.css
+++ b/bundles/org.eclipse.orion.client.core/web/css/layout.css
@@ -98,6 +98,10 @@
 	clear: both;

 }

 

+.hidden {

+	visibility: hidden;

+}

+

 .sidePanelLayout {

 	display: block;

 	position: absolute;

@@ -209,7 +213,7 @@
 	vertical-align: baseline;

 }

 

-.commandList li {

+.commandList > li {

 	float: left;

 	margin-left: 4px;

 	margin-right: 4px;

diff --git a/bundles/org.eclipse.orion.client.core/web/css/theme.css b/bundles/org.eclipse.orion.client.core/web/css/theme.css
index e689e2d..9967c8f 100644
--- a/bundles/org.eclipse.orion.client.core/web/css/theme.css
+++ b/bundles/org.eclipse.orion.client.core/web/css/theme.css
@@ -22,34 +22,37 @@
 }

 

 a:hover {

-	cursor: hand;

+	cursor: pointer;

 	text-decoration: underline;

 }

 

 /* Navigation text */

 

 .primaryNav {

-	font-size: 8pt; /* 7pt */

+	font-size: 8pt; 

 	font-weight:normal;

 	color: #BFBFBF;

-	padding-top: 6px;

 	vertical-align: baseline;

 }

 

-.primaryNav a {

-	font-size: 8pt; /* 7pt */

+.primaryNav > div {

+	padding-top: 6px;

+}

+

+.primaryNav > nav {

+	padding-top: 6px;

+}

+

+.primaryNav > nav > a {

 	color: #BFBFBF;

 	margin-right: 6px;

 	margin-left: 6px; 

-	vertical-align: baseline;

 	text-decoration: none;

 }

 

-.primaryNav a:hover {

-	color: #bfbfbf;

-	cursor: hand;

+.primaryNav > nav > a:hover, .primaryNav span.dropdownTrigger:hover {

+	cursor: pointer;

 	color: white;

-	font-weight:normal;

 }

 

 /* Title area - the place for location/breadcrumbs */

@@ -64,19 +67,6 @@
     min-height:20px;

 }

 

-/* splitter - typically the color of the title area */

-.split {

-	background: #efefef;

-}

-

-.splitTracking {

-	background: #dedede;

-}

-

-.splitThumb {

-	background: #cdcdcd;

-}

-

 /* Row selection */

 

 .checkedRow {

@@ -172,7 +162,6 @@
 	padding-left:20px;

 	padding-right:16px;

 	margin-left:5px;

-	margin-top:6px !important;

 	font: 7pt Lucida Sans Unicode,Lucida Grande,Verdana,Arial,Helvetica,Myriad,Tahoma,clean,sans-serif !important;

 }

 

@@ -202,30 +191,11 @@
 	user-select: none;

 }

 

-.commandButtonOver {

+.commandButton:hover, .commandButton:focus {

 	background-color: #e6e6e6;

 	border: 1px solid #808080;

 }

 

-.commandMenu {

-    color: #222;

-	display: inline-block;

-	vertical-align: baseline;

-	margin: 0;

-	font-size:8pt;

-	font-weight:normal;

-	border: 1px solid #dedede;

-	background-color: #efefef;

-    cursor: pointer;

-    border-radius:1px;

-}

-

-.commandMenuItem {

-	border: 0;

-	padding: 0;

-	margin: 0;

-}

-

 .commandImage {

 	border: 1px solid transparent;

     border-radius: 2px;

@@ -242,7 +212,7 @@
 	user-select: none;

 }

 

-.commandImageOver {

+.commandImage:hover, .commandImage:focus {

 	background-color: #e6e6e6;

 	border: 1px solid #808080;

 }

@@ -252,10 +222,6 @@
 	font-weight:bold;

 }

 

-.commandMenuItemAnchor {

-	padding-right: 40px;

-}

-

 .commandLink {

 	display: inline-block;

 	vertical-align: baseline;

@@ -286,79 +252,132 @@
 .commandInactiveItem {

 }

 

-/* dijit overrides related to theming */

-/* dijit theme overrides per graphic designer.  Mostly affecting drop down and menu appearance and hovers */

-/* buttons */

-

-.claro .dijitButton .dijitButtonNode,

-.claro .dijitDropDownButton .dijitButtonNode,

-.claro .dijitComboButton .dijitButtonNode,

-.claro .dijitToggleButton .dijitButtonNode {

-  background-color: transparent;

-  background-image: none;

-  border: 1px solid transparent;

-  box-shadow: none;

-  border-radius: 3px;

-  padding: 0;

-  padding-bottom: 3px;

-  color: #222;

-  margin: 0;

+/* widget theming */

+/* splitter - typically the color of the title area */

+.split {

+	background: #efefef;

 }

 

-.claro .commandMenu .dijitButtonNode {

-  color: #222;

+.splitTracking {

+	background: #dedede;

 }

 

-/* button hover */

-.claro .dijitButtonHover .dijitButtonNode,

-.claro .dijitDropDownButtonHover .dijitButtonNode,

-.claro .dijitComboButton .dijitButtonNodeHover,

-.claro .dijitComboButton .dijitDownArrowButtonHover,

-.claro .dijitToggleButtonHover .dijitButtonNode {

-    background-color: #e3e3e3;

-    color: black;

-	border: 1px solid #808080;

- }

+.splitThumb {

+	background: #cdcdcd;

+}

 

-/* arrow buttons*/

-.claro .dijitArrowButtonInner {

+/* dropdowns */

+.dropdown {

+} 

+

+.dropdownArrowDown {

 	background-position: 0 -422px;	

 	width: 5px; height: 3px;

 	background-image: url(../images/core_sprites.png); 

 	display: inline-block; 

-	margin: 1px;

+	margin: 4px 4px 0;

+	vertical-align: top; 

+}

+

+.dropdownArrowRight {

+	background-position: 0 -654px; 

+	width: 6px; height: 11px;

+	background-image: url(../images/core_sprites.png); 

+	margin-right: 4px;

 	vertical-align: middle; 

+	float: right;

 }

 

-/* menus and menu items */

-

-.claro .dijitMenu {

-   background-color: #FFFFFF;

-   border: 1px solid #9a9a9a;

+.dropdownTrigger {

+	font-weight: normal;

 }

 

-.claro .dijitMenuItem {

-   outline: none;

-   padding-top:4px;

+.dropdownTrigger a {

+	text-decoration: none;

 }

 

-.claro .dijitMenuSeparatorTop {

-	height: auto;

-	margin-top: 1px;

-	border-bottom: 1px solid #DDD;

+.dropdownTriggerOpen {

+	

 }

 

-.claro .dijitMenuItemLabel {

-	position: relative;

-	padding: 5px;

+.dropdownMenu {

+	color: #222;

+	background-color: #fbfbfb;

+	display: none;

+	z-index: 150;

+	min-width: 120px;

+	position: absolute;

+	list-style-type: none;

+	border-radius: 3px;

+	border: 1px solid #DDD;

+	padding: 0;

 }

 

-.claro .dijitMenuActive .dijitMenuItemHover, .claro .dijitMenuActive .dijitMenuItemSelected, .claro .dijitMenuActive .dijitMenuItemActive {

-   background-color: #e3e3e3;

-   color: black;

-   background-image: none;

+.dropdownSubMenu {

+	position: relative

 }

 

+.dropdownSubMenu > ul {

+	top: 0;

+	left: 100%;

+}

+

+.dropdownMenu > li {

+	min-width: 120px;

+	padding: 0 2px;

+	display: block;

+}

+

+.dropdownMenu > li > a, .dropdownMenu > li > span {

+	width: 100%;

+	margin: 0;

+	padding: 4px 0;

+}

+

+.dropdownMenu > li:hover {

+	text-decoration: none;

+	background: #ffeecc;

+}

+

+.dropdownMenu > li > *:focus {

+	outline: 1px dotted #aaa;

+	background: #ffeecc;

+}

+

+.dropdownMenuOpen {

+	display: block;

+}

+

+.dropdownSeparator {

+	height: 1px;

+	background-color: #ddd;

+	color: #ddd;

+	padding: 0 !important;

+	margin: 0;

+}

+

+.dropdownMenuItem, .dropdownMenuItem a {

+	display: inline-block;

+	vertical-align: baseline;

+	color: #222;

+	-webkit-touch-callout: none;

+	-webkit-user-select: none;

+	-khtml-user-select: none;

+	-moz-user-select: none;

+	-ms-user-select: none;

+	user-select: none;

+}

+

+.checkedMenuItem {

+	margin: 4px 6px 2px 0;

+	vertical-align: bottom;

+}

+

+/* dijit overrides related to theming */

+/* dijit theme overrides per graphic designer.  Mostly affecting drop down and menu appearance and hovers */

+/* buttons */

+

+

 /* tooltips */

 .claro .dijitTooltip {

 	max-width: 300px;

diff --git a/bundles/org.eclipse.orion.client.core/web/edit/edit.css b/bundles/org.eclipse.orion.client.core/web/edit/edit.css
index 1bdda41..7c743d8 100644
--- a/bundles/org.eclipse.orion.client.core/web/edit/edit.css
+++ b/bundles/org.eclipse.orion.client.core/web/edit/edit.css
@@ -23,3 +23,44 @@
 .outlineExplorer {
 	overflow-y: none;
 }
+
+.findOptionsDiv {
+	display: inline-block;
+	margin: 0;
+	padding: 0;
+}
+
+.findSlideoutButton {
+	color: #222;
+	border: 1px solid transparent;
+	text-align: center;
+	vertical-align: top;
+    cursor: pointer;
+    display: inline-block;
+    padding: 2px;
+    margin-left: 8px;
+    border-radius:1px;
+    font-weight: normal;
+	-webkit-touch-callout: none;
+	-webkit-user-select: none;
+	-khtml-user-select: none;
+	-moz-user-select: none;
+	-ms-user-select: none;
+	user-select: none;
+}
+
+.findSlideoutMenu {
+	color: #222;
+	background-color: transparent;
+	border: 1px solid transparent;
+	padding: 2px;
+    font-weight: normal;
+    margin: 0;
+    margin-left: 8px;
+	text-align: center;
+}
+
+.findSlideoutButton:hover {
+	background-color: #efefef;
+	border: 1px solid #222;
+}
diff --git a/bundles/org.eclipse.orion.client.core/web/js-tests/commands/testcase.js b/bundles/org.eclipse.orion.client.core/web/js-tests/commands/testcase.js
index 8d29d6e..3edd2f5 100644
--- a/bundles/org.eclipse.orion.client.core/web/js-tests/commands/testcase.js
+++ b/bundles/org.eclipse.orion.client.core/web/js-tests/commands/testcase.js
@@ -8,19 +8,26 @@
  * 
  * Contributors: IBM Corporation - initial API and implementation
  ******************************************************************************/
-/*global define dojo dijit orion window document */
+/*global define orion window document */
 
-define(['require', 'dojo', 'dijit', 'orion/assert', 'orion/serviceregistry', 'orion/commands', 'orion/selection', 'dijit/Menu'], 
-			function(require, dojo, dijit, assert, mServiceregistry, mCommands, mSelection) {
+define(['require', 'orion/assert', 'orion/serviceregistry', 'orion/commands', 'orion/selection', 'orion/Deferred', 'orion/webui/littlelib', 'orion/webui/dropdown'], 
+			function(require, assert, mServiceregistry, mCommands, mSelection, Deferred, lib, mDropdown) {
 			
 	/**
 	 * dom elements we need
 	 */
-	var parentDiv = dojo.create("div");
-	var parentUl = dojo.create("ul");
-	var parentMenu = new dijit.Menu({
-		style: "display: none;"
-	});
+	var parentDiv = document.createElement("div");
+	var parentUl = document.createElement("ul");
+	var menuDiv = document.createElement("div");
+	document.body.appendChild(menuDiv);
+	var dropdownTrigger = document.createElement("span");
+	menuDiv.appendChild(dropdownTrigger);
+	dropdownTrigger.classList.add("dropdownTrigger");
+	dropdownTrigger.classList.add("commandButton");
+	var dropdownMenu = document.createElement("ul");
+	menuDiv.appendChild(dropdownMenu);
+	dropdownMenu.classList.add("dropdownMenu");
+	var parentMenu = new mDropdown.Dropdown({dropdown: dropdownMenu});
 		
 	/**
 	 * mock services
@@ -65,7 +72,7 @@
 	var isMac = window.navigator.platform.indexOf("Mac") !== -1;
 
 	var visibleWhenAllValid = function(items) {
-		if (dojo.isArray(items)) {
+		if (Array.isArray(items)) {
 			for (var i=0; i<items.length; i++) {
 				if (!items[0].IsValid) {
 					return false;
@@ -78,7 +85,7 @@
 	};
 	
 	var visibleWhenOnlyOne = function(items) {
-		if (dojo.isArray(items)) {
+		if (Array.isArray(items)) {
 			return items.length === 1 && items[0].IsValid;
 		} else {
 			return items.IsValid;
@@ -196,13 +203,9 @@
 	function init(testId) {
 		window.console.log("Initializing data for test " + testId);
 		contributionId = testId;
+		parentMenu.empty();
 		commandService.destroy(parentDiv);
 		commandService.destroy(parentUl);
-		parentMenu.focusedChild = null;
-		dojo.forEach(parentMenu.getChildren(), function(child) {
-			parentMenu.removeChild(child);
-			child.destroy();
-		});
 		initializeItems();
 	}
 	
@@ -238,7 +241,7 @@
 		commandService.registerCommandContribution(contributionId, "test.link", 3);
 		commandService.renderCommands(contributionId, parentDiv, item1, window, "button");
 		assert.equal(parentDiv.childNodes.length, 3);
-		assert.equal(dojo.query("a", parentDiv).length, 1);
+		assert.equal(lib.$$("a", parentDiv).length, 1);
 	};
 	
 	/**
@@ -251,7 +254,7 @@
 		commandService.registerCommandContribution(contributionId, "test.link", 3);
 		commandService.renderCommands(contributionId, parentDiv, item1, window, "tool");
 		assert.equal(parentDiv.childNodes.length, 3);
-		assert.equal(dojo.query("a", parentDiv).length, 1);
+		assert.equal(lib.$$("a", parentDiv).length, 1);
 	};
 	
 	/**
@@ -263,8 +266,8 @@
 		commandService.registerCommandContribution(contributionId, "test.noIcon", 3);
 		commandService.renderCommands(contributionId, parentDiv, allItems, window, "tool");
 		assert.equal(parentDiv.childNodes.length, 2);
-		assert.equal(dojo.query(".commandSprite", parentDiv).length, 1);
-		assert.equal(dojo.query("..commandMissingImageButton", parentDiv).length, 1);
+		assert.equal(lib.$$(".commandSprite", parentDiv).length, 1);
+		assert.equal(lib.$$(".commandMissingImageButton", parentDiv).length, 1);
 	};
 	
 	/**
@@ -275,8 +278,8 @@
 		commandService.registerCommandContribution(contributionId, "test.delete", 1);
 		commandService.registerCommandContribution(contributionId, "test.new", 2);
 		commandService.registerCommandContribution(contributionId, "test.noIcon", 3);
-		commandService.renderCommands(contributionId, parentMenu, item1, window, "menu");
-		assert.equal(parentMenu.getChildren().length, 3);
+		commandService.renderCommands(contributionId, dropdownMenu, item1, window, "menu");
+		assert.equal(parentMenu.getItems().length, 3);
 	};
 	
 	/**
@@ -290,7 +293,7 @@
 		commandService.registerCommandContribution(contributionId, "test.new", 2, "testGroup");
 		commandService.registerCommandContribution(contributionId, "test.noIcon", 1, "testGroup2");
 		commandService.renderCommands(contributionId, parentDiv, item1, window, "button");
-		assert.equal(dojo.query(".commandSeparator", parentDiv).length, 1);
+		assert.equal(lib.$$(".commandSeparator", parentDiv).length, 1);
 	};
 	
 	/**
@@ -303,7 +306,7 @@
 		commandService.registerCommandContribution(contributionId, "test.new", 2, "testGroup");
 		commandService.registerCommandContribution(contributionId, "test.noIcon", 3, "testGroup");
 		commandService.renderCommands(contributionId, parentDiv, item1, window, "button");
-		assert.equal(dojo.query(".commandMenu", parentDiv).length, 1);
+		assert.equal(lib.$$(".commandButton.dropdownTrigger", parentDiv).length, 1);
 	};
 	
 	/**
@@ -315,8 +318,8 @@
 		commandService.registerCommandContribution(contributionId, "test.delete", 1, "testGroup");
 		commandService.registerCommandContribution(contributionId, "test.new", 2, "testGroup");
 		commandService.registerCommandContribution(contributionId, "test.noIcon", 3, "testGroup");
-		commandService.renderCommands(contributionId, parentMenu, item1, window, "menu");
-		assert.equal(parentMenu.getChildren().length, 1);  // everything is in a submenu
+		commandService.renderCommands(contributionId, dropdownMenu, item1, window, "menu");
+		assert.equal(parentMenu.getItems().length, 1);  // everything is in a submenu
 	};
 	
 	/**
@@ -330,11 +333,10 @@
 		commandService.registerCommandContribution(contributionId, "test.delete", 1, "testGroup");
 		commandService.registerCommandContribution(contributionId, "test.new", 2, "testGroup/testGroup2");
 		commandService.registerCommandContribution(contributionId, "test.noIcon", 3, "testGroup/testGroup2/testGroup3");
-		commandService.renderCommands(contributionId, parentDiv, item1, window, "button");
-		assert.equal(dojo.query(".commandMenu", parentDiv).length, 1);  // just one menu since the others should be grouped
-		var topMenuNode = dojo.query(".commandMenu", parentDiv).at(0);
-		// we could traverse further down in this menu if we had an id set to retrieve the dijit but currently the 
-		// command framework does not set an id on auto generated menus.
+		commandService.renderCommands(contributionId, menuDiv, item1, window, "menu");
+		assert.equal(lib.$$(".dropdownTrigger", menuDiv).length, 4);  // four menus
+		assert.equal(lib.$$(".dropdownTrigger.dropdownMenuItem", menuDiv).length, 3);  // three sub menus
+		assert.equal(lib.$$(".dropdownTrigger.commandButton", menuDiv).length, 1);  // one top menu
 	};
 	
 	/**
@@ -373,10 +375,10 @@
 		commandService.registerCommandContribution(contributionId, "test.new", 2);
 		commandService.registerCommandContribution(contributionId, "test.link", 3);
 		commandService.renderCommands(contributionId, parentUl, item1, window, "button");
-		assert.equal(dojo.query("a", parentUl).length, 1);
-		assert.equal(dojo.query("li > a", parentUl).length, 1);
+		assert.equal(lib.$$("a", parentUl).length, 1);
+		assert.equal(lib.$$("li > a", parentUl).length, 1);
 		assert.equal(parentUl.childNodes.length, 3);
-		assert.equal(dojo.query("li", parentUl).length, 3);
+		assert.equal(lib.$$("li", parentUl).length, 3);
 	};	
 	
 	/**
@@ -390,7 +392,7 @@
 		hitCounters = {};
 		commandService.runCommand("test.parameters");
 		commandService.runCommand("test.parameters");
-		var d = new dojo.Deferred();
+		var d = new Deferred();
 		window.setTimeout(function(){
 			try {
 				assert.equal(hitCounters["test.parameters"], 2);
@@ -415,7 +417,7 @@
 		assert.equal(parentDiv.childNodes.length, 1);
 		hitCounters["test.delete"] = 0;
 		fakeKeystroke('z');
-		var d = new dojo.Deferred();
+		var d = new Deferred();
 		window.setTimeout(function(){
 			try {
 				assert.equal(hitCounters["test.delete"], 1);
@@ -437,7 +439,7 @@
 		assert.equal(parentDiv.childNodes.length, 0);
 		hitCounters["test.noIcon"] = 0;
 		fakeKeystroke('z', true, true);
-		var d = new dojo.Deferred();
+		var d = new Deferred();
 		window.setTimeout(function(){
 			try {
 				assert.equal(hitCounters["test.noIcon"], 1);
@@ -458,7 +460,7 @@
 		commandService.renderCommands(contributionId, parentDiv, item1, window, "button");
 		assert.equal(parentDiv.childNodes.length, 1);
 		commandService.processURL("#,foo=fred");
-		var d = new dojo.Deferred();
+		var d = new Deferred();
 		window.setTimeout(function(){
 			try {
 				assert.equal(parameters.lastValueForName, "fred");
@@ -479,7 +481,7 @@
 		commandService.renderCommands(contributionId, parentDiv, item1, window, "button");
 		assert.equal(parentDiv.childNodes.length, 0);
 		commandService.processURL("#,foo=wilma");
-		var d = new dojo.Deferred();
+		var d = new Deferred();
 		window.setTimeout(function(){
 			try {
 				assert.equal(parameters.lastValueForName, "wilma");
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/commands.js b/bundles/org.eclipse.orion.client.core/web/orion/commands.js
index c85037c..faf6fbb 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/commands.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/commands.js
@@ -11,30 +11,10 @@
 /*jslint sub:true*/
  /*global define document window Image */
  
-define(['i18n!orion/nls/messages', 'require', 'dojo', 'dijit', 'orion/uiUtils', 'orion/PageUtil', 'orion/explorers/navigationUtils', 'dijit/Menu', 'dijit/form/DropDownButton', 'dijit/MenuItem', 'dijit/PopupMenuItem', 'dijit/MenuSeparator', 'dijit/Tooltip', 'dijit/TooltipDialog' ], function(messages, require, dojo, dijit, UIUtil, PageUtil, mNavUtils){
+define(['i18n!orion/nls/messages', 'require', 'dojo', 'dijit', 'orion/uiUtils', 'orion/PageUtil', 'orion/webui/littlelib', 'orion/webui/dropdown', 'orion/explorers/navigationUtils', 'dijit/Tooltip', 'dijit/TooltipDialog' ], function(messages, require, dojo, dijit, UIUtil, PageUtil, lib, mDropdown, mNavUtils){
 
 	var isMac = window.navigator.platform.indexOf("Mac") !== -1; //$NON-NLS-0$
 
-	/*
-	 * stateless helper function
-	 */
-	function _setupActivateVisuals(domNode, focusNode, overClass) {
-		var makeActive = function() {
-			if (overClass) {
-				dojo.addClass(this, overClass);
-			}
-		};
-		var makeInactive = function() {
-			if (overClass) {
-				dojo.removeClass(this, overClass);
-			}
-		};
-		dojo.connect(domNode, "onmouseover", domNode, makeActive); //$NON-NLS-0$
-		dojo.connect(focusNode, "onfocus", domNode, makeActive); //$NON-NLS-0$
-		dojo.connect(domNode, "onmouseout", domNode, makeInactive); //$NON-NLS-0$
-		dojo.connect(focusNode, "onblur", domNode, makeInactive); //$NON-NLS-0$
-	}
-
 	/**
 	 * CommandInvocation is a data structure that carries all relevant information about a command invocation.
 	 * It represents a unique invocation of a command by the user.  Each time a user invokes a command (by click, keystroke, URL),
@@ -90,95 +70,6 @@
 	CommandInvocation.prototype.constructor = CommandInvocation;
 
 	/**
-	 * Override the dijit MenuItem so that the inherited click behavior is not used.
-	 * This is done when the command is defined with a link, so that the normal browser
-	 * link behavior (and interpretations of various mouse clicks) is used.  We also style
-	 * link specially (padding, etc.) to help reduce the difference in perceived
-	 * responsive area (the menu item) with the actual area (the link)
-	 * 
-	 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=350584
-	 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=371265
-	 */
-	var CommandMenuItem = dojo.declare(dijit.MenuItem, {
-		constructor: function() {
-			var options = arguments[0] || {};
-			options.onKeyDown = dojo.hitch(this, function(evt) {
-				if (evt.keyCode === dojo.keys.ENTER || evt.keyCode === dojo.keys.SPACE) {
-					if(this._anchorLocation) { 
-						if(evt.ctrlKey) {
-							window.open(this._anchorLocation);
-						} else {
-							window.location=this._anchorLocation;
-						}
-					}
-				}
-			});
-			this.inherited(arguments || [options]);
-		},
-	
-		// if it has a link and the anchor is already in the dom, style it with some padding.
-		postCreate: function() {
-			var anchor = dojo.query("a", this.domNode)[0]; //$NON-NLS-0$
-			if (anchor) {
-				dojo.addClass(anchor, "commandMenuItemAnchor"); //$NON-NLS-0$
-				this._anchorLocation = anchor.href;
-			}
-		},
-
-		// Override setter for 'label' attribute to prevent the use of innerHTML and allow a DOM node instead.
-		_setLabelAttr: function(value) {
-			if (typeof value === "string") {
-				this.containerNode.textContent = value;
-			} else if (value) {
-				dojo.empty(this.containerNode);
-				this.containerNode.appendChild(value.cloneNode(true));
-			}
-		},
-		
-		setLink: function(href, name) {
-			href = PageUtil.validateURLScheme(href);
-			var a = dojo.create("a", {className: "commandMenuItemAnchor", href: href});
-			a.textContent = name;
-			dojo.place(a, this.containerNode, "only");
-			this._anchorLocation = href;
-		},
-		
-		_onClick: function(evt) {
-			if (!this.hasLink) {
-				this.inherited(arguments);
-			}
-		}
-	});
-
-	var CommandDropDownButton = dojo.declare(dijit.form.DropDownButton, {
-		// Override setter for 'label' attribute to prevent the use of innerHTML
-		_setLabelAttr: function(/*String*/ content) {
-			if (typeof content === "string") {
-				this._set("label", content);
-				this.containerNode.textContent = content;
-				if(this.showLabel === false && !this.params.title){
-					this.titleNode.title = dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
-				}
-			} else if (content) {
-				dojo.empty(this.containerNode);
-				this.containerNode.appendChild(content.cloneNode(true));
-			}
-		}
-	});
-
-	var CommandPopupMenuItem = dojo.declare(dijit.PopupMenuItem, {
-		// Override setter for 'label' attribute to prevent the use of innerHTML
-		_setLabelAttr: function(content) {
-			if (typeof content === "string") {
-				this.containerNode.textContent = content;
-			} else {
-				dojo.empty(this.containerNode);
-				this.containerNode.appendChild(content.cloneNode(true));
-			}
-		}
-	});
-
-	/**
 	 * Override the dijit Tooltip to handle cases where the tooltip is not dismissing
 	 * when expected.
 	 * Case 1:  the tooltip should close when the command dom node that generated it is hidden.
@@ -268,7 +159,7 @@
 
 		_setLabelAttr: function(content) {
 			this.label = null;
-			if (typeof content === "string") {
+			if (typeof content === "string") {  //$NON-NLS-0$
 				this.domNode.textContent = content;
 			} else {
 				dojo.empty(this.domNode);
@@ -290,7 +181,6 @@
 		this._urlBindings = {};
 		this._init(options);
 		this._parameterCollector = null;
-		this.showMenuIcons = false;
 	}
 	CommandService.prototype = /** @lends orion.commands.CommandService.prototype */ {
 		_init: function(options) {
@@ -595,13 +485,7 @@
 						})(parameterArea);
 						if (parameterArea.childNodes.length > 0) {
 							tooltipDialog.set("content", parameterArea); //$NON-NLS-0$
-							var menu = dijit.byId(commandInvocation.domParent.id);
-							var pos;
-							if (menu) {
-								pos = dojo.position(menu.eclipseScopeId, true);
-							} else {
-								pos = dojo.position(commandInvocation.domNode, true);
-							}
+							var pos = dojo.position(commandInvocation.domNode, true);
 							if (pos.x && pos.y && pos.w) {
 								dijit.popup.open({popup: tooltipDialog, x: pos.x + pos.w - 8, y: pos.y + 8});
 								window.setTimeout(function() {
@@ -665,7 +549,7 @@
 			}
 			for (var scopedBinding in scopes) {
 				if (scopes[scopedBinding].length && scopes[scopedBinding].length > 0) {
-					dojo.place("<h2>"+scopedBinding+"</h2>", targetNode, "last"); //$NON-NLS-1$ //$NON-NLS-0$ //$NON-NLS-3$ 
+					dojo.place("<h2>"+scopedBinding+"</h2>", targetNode, "last"); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$ 
 					for (var i=0; i<scopes[scopedBinding].length; i++) {
 						binding = scopes[scopedBinding][i];
 						bindingString = UIUtil.getUserKeyString(binding.keyBinding);
@@ -799,13 +683,30 @@
 			parentTable.sortedContributions = null;
 		},
 		
-		_isLastChildSeparator: function(parent, style) {
+		_checkForTrailingSeparator: function(parent, style, autoRemove) {
+			var last;
 			if (style === "tool" || style === "button") { //$NON-NLS-1$ //$NON-NLS-0$
-				return parent.childNodes.length > 0 && dojo.hasClass(parent.childNodes[parent.childNodes.length - 1], "commandSeparator"); //$NON-NLS-0$
+				last = parent.childNodes.length > 0 ? parent.childNodes[parent.childNodes.length-1] : null;
+				if (last && last.classList.contains("commandSeparator")) { //$NON-NLS-0$
+					if (autoRemove) {
+						parent.removeChild(last);
+						return false;
+					} 
+					return true;
+				}
 			}
 			if (style === "menu") { //$NON-NLS-0$
-				var menuChildren = parent.getChildren();
-				return menuChildren.length > 0 && (menuChildren[menuChildren.length-1] instanceof dijit.MenuSeparator);
+				var items = lib.$$array("li > *", parent); //$NON-NLS-0$
+				if (items.length > 0 && items[items.length - 1].classList.contains("dropdownSeparator")) { //$NON-NLS-0$
+					last = items[items.length - 1];
+					if (autoRemove) {
+						// reachy reachy.  Remove the anchor's li parent
+						last.parentNode.parentNode.removeChild(last.parentNode);
+						return false;
+					} else {
+						return true;
+					}
+				}
 			}
 			return false;
 		},
@@ -821,8 +722,7 @@
 		 *  service will be used to determine which items are involved. 
 		 * @param {Object} handler The object that should perform the command
 		 * @param {String} renderType The style in which the command should be rendered.  "tool" will render
-		 *  a tool image in the dom.  "button" will render a text button.  "menu" will render menu items.  The caller
-		 *  must supply the parent menu.
+		 *  a tool image in the dom.  "button" will render a text button.  "menu" will render menu items.  
 		 * @param {Object} userData Optional user data that should be attached to generated command callbacks
 		 * @param {Array} domNodeWrapperList Optional an array used to record any DOM nodes that are rendered during this call.
 		 *  If an array is provided, then as commands are rendered, an object will be created to represent the command's node.  
@@ -856,17 +756,7 @@
 			if (contributions) {
 				this._render(this._contributionsByScopeId[scopeId], parent, items, handler, renderType, userData, domNodeWrapperList);
 				// If the last thing we rendered was a group, it's possible there is an unnecessary trailing separator.
-				if (renderType === "tool" || renderType === "button") { //$NON-NLS-1$ //$NON-NLS-0$
-					if (this._isLastChildSeparator(parent, renderType)) {
-						parent.removeChild(parent.childNodes[parent.childNodes.length-1]);
-					}
-				} else if (renderType=== "menu") { //$NON-NLS-0$
-					if (this._isLastChildSeparator(parent, renderType)) {
-						var child = parent.getChildren()[parent.getChildren().length-1];
-						parent.removeChild(child);
-						child.destroy();
-					}
-				}
+				this._checkForTrailingSeparator(parent, renderType, true);
 			}
 		},
 		
@@ -878,9 +768,7 @@
 		 * @param {String|DOMElement} parent The id or DOM node that should be emptied.
 		 */
 		destroy: function(parent) {
-			if (typeof(parent) === "string") { //$NON-NLS-0$
-				parent = dojo.byId(parent);
-			}
+			parent = lib.node(parent);
 			if (!parent) { 
 				throw "no parent";  //$NON-NLS-0$
 			}
@@ -916,74 +804,36 @@
 			}
 			// now traverse the sorted contributions and render as we go
 			for (var i = 0; i < sortedByPosition.length; i++) {
-				var id, menuButton, invocation;
+				var id, invocation;
 				if (sortedByPosition[i].children && Object.getOwnPropertyNames(sortedByPosition[i].children).length > 0) {
 					var group = sortedByPosition[i];
-					var children;
 					var childContributions = sortedByPosition[i].children;
 					var commandService = this;
+					var created;
 					if (renderType === "tool" || renderType === "button") { //$NON-NLS-1$ //$NON-NLS-0$
 						if (group.title) {
 							// We need a named menu button.  We used to first render into the menu and only 
-							// add a menu button in the dom when we knew it was needed.  For performance, though, we need
-							// to be asynchronous in traversing children, so we will add the menu and only remove it
-							// if it turns out we didn't need it.  
-							// If we wait until the end of asynch processing to add the menu button, the order will
-							// not be right, and we could have css ripple.  The down side to this approach is that a dropdown
-							// could appear and then not be needed.  It would be dangerous to assume that null items or an empty
-							// item array always mean "don't render" since some commands ignore the items.  It seems the best we
-							// can do is add it as not visible (thus reserving space) and make it visible when needed.   This could
-							// still cause ripple but helps with cases like the "More" menu which is always last.
-							
-							var newMenu= new dijit.Menu({
-								style: "display: none;" //$NON-NLS-0$
-							});
-							menuButton = new CommandDropDownButton({
-								label: group.title === "*" ? messages["Actions"] : group.title, //TODO undocumented hack, even mode dangerous when we have globalization //$NON-NLS-0$
-								showLabel:  group.title !== "*", //$NON-NLS-0$
-								style: "visibility: hidden;", //$NON-NLS-0$
-								dropDown: newMenu
-						        });
-							dojo.addClass(menuButton.domNode, "commandMenu"); //$NON-NLS-0$
+							// add a menu button in the dom when we knew items were actually rendered.
+							// For performance, though, we need to be asynchronous in traversing children, so we will 
+							// add the menu button always and then remove it if we don't need it.  
+							// If we wait until the end of asynch processing to add the menu button, the layout will have 
+							// to be redone. The down side to always adding the menu button is that we may find out we didn't
+							// need it after all, which could cause layout to change.
+							created = this._createDropdownMenu(parent, group.title); 
 							if(domNodeWrapperList){
-								//we need to add the menuButton as the optional widget param
-								mNavUtils.generateNavGrid(domNodeWrapperList, menuButton.domNode, menuButton);
+								mNavUtils.generateNavGrid(domNodeWrapperList, created.menuButton);
 							}
-							var menuParent = parent;
-							if (parent.nodeName.toLowerCase() === "ul") { //$NON-NLS-0$
-								menuParent = dojo.create("li", {}, parent); //$NON-NLS-0$
-							} else {
-								dojo.addClass(menuButton.domNode, "commandMargins"); //$NON-NLS-0$
-							}
-							dojo.removeAttr(menuButton.titleNode, "title"); // there is no need for a native browser tooltip //$NON-NLS-0$
-							dojo.destroy(menuButton.valueNode); // the valueNode gets picked up by screen readers; since it's not used, we can get rid of it
-							_setupActivateVisuals(menuButton.domNode, menuButton.focusNode);
-							dojo.place(menuButton.domNode, menuParent, "last"); //$NON-NLS-0$
-							// we'll need to identify a menu with the dom id of its original parent
-							newMenu.eclipseScopeId = parent.eclipseScopeId || parent.id;
+
 							// render the children asynchronously
 							window.setTimeout(dojo.hitch({contributions: childContributions, emptyGroupMessage: group.emptyGroupMessage}, function() {
-								// it is possible that commands were destroyed by the time we get here.  Bail out if
-								// the parent menu has been destroyed.  We are reaching into the widget to make this
-								// determination.
-								// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=382394
-								if (newMenu._destroyed) {
-									return;
-								}
-								commandService._render(this.contributions, newMenu, items, handler, "menu", userData, domNodeWrapperList);  //$NON-NLS-0$
+								commandService._render(this.contributions, created.menu, items, handler, "menu", userData, domNodeWrapperList);  //$NON-NLS-0$
 								// special post-processing when we've created a menu in an image bar.  We want to get rid 
 								// of a trailing separator in the menu first, and then decide if our menu is necessary
-								children = newMenu.getChildren();
-								if (commandService._isLastChildSeparator(newMenu, "menu")) { //$NON-NLS-0$
-									var trailingSep = children[children.length-1];
-									newMenu.removeChild(trailingSep);
-									trailingSep.destroy();
-									children = newMenu.getChildren();
-								}
+								commandService._checkForTrailingSeparator(created.menu, "menu", true);  //$NON-NLS-0$
 								// now determine if we actually needed the menu or not
-								if (children.length === 0) {
+								if (created.menu.childNodes.length === 0) {
 									if (this.emptyGroupMessage) {
-										dojo.connect(menuButton.focusNode, "onclick", this, function() { //$NON-NLS-0$
+										dojo.connect(created.menuButton, "onclick", this, function() { //$NON-NLS-0$
 											//Show the empty group message.
 											var emptyGroupMessage = document.createElement("p"); //$NON-NLS-0$
 											emptyGroupMessage.textContent = this.emptyGroupMessage;
@@ -994,22 +844,23 @@
 													tooltipDialog.destroyRecursive();
 												}
 											});		
-											dijit.popup.open({popup: tooltipDialog, around: menuButton.domNode});
+											dijit.popup.open({popup: tooltipDialog, around: created.menuButton});
 											// in case the user's mouse never entered this popup and thus couldn't leave
 											window.setTimeout(function() {
 												dijit.popup.close(tooltipDialog);
 												tooltipDialog.destroyRecursive();
 											}, 15000);
 										});
-										dojo.style(menuButton.domNode, "visibility", "visible"); //$NON-NLS-1$ //$NON-NLS-0$
+										dojo.style(created.menuButton, "visibility", "visible"); //$NON-NLS-1$ //$NON-NLS-0$
 									} else {
 										if(domNodeWrapperList){
-											mNavUtils.removeNavGrid(domNodeWrapperList, menuButton.domNode);
+											mNavUtils.removeNavGrid(domNodeWrapperList, created.menuButton);
 										}
-										menuButton.destroyRecursive();
+										created.menu.parentNode.removeChild(created.menu);
+										parent.removeChild(created.destroyButton);
 									}
 								} else {
-									dojo.style(menuButton.domNode, "visibility", "visible"); //$NON-NLS-1$ //$NON-NLS-0$
+									dojo.style(created.menuButton, "visibility", "visible"); //$NON-NLS-1$ //$NON-NLS-0$
 								}
 							}), 0);
 						} else {  
@@ -1017,7 +868,7 @@
 							// non grouped items.
 							var sep;
 							// Only draw a separator if there is a non-separator preceding it.
-							if (parent.childNodes.length > 0 && !this._isLastChildSeparator(parent, renderType)) {
+							if (parent.childNodes.length > 0 && !this._checkForTrailingSeparator(parent, renderType)) {
 								sep = this.generateSeparatorImage(parent);
 							}
 							commandService._render(childContributions, parent, items, handler, renderType, userData, domNodeWrapperList); 
@@ -1033,36 +884,22 @@
 					} else {
 						// group within a menu
 						if (group.title) {
-							var subMenu = new dijit.Menu();
-							// popup menu placeholder must be added synchronously to respect order.
-							// We will remove it if it ends up empty
-							var groupPopup = new CommandPopupMenuItem({
-								label: group.title,
-								popup: subMenu
-							});
-							parent.addChild(groupPopup);
-							commandService._render(childContributions, subMenu, items, handler, renderType, userData, domNodeWrapperList); 
-							if (subMenu.getChildren().length === 0) {
-								groupPopup.set("label", "removeme"); //$NON-NLS-1$ //$NON-NLS-0$
-								parent.removeChild(groupPopup);
-								groupPopup.destroyRecursive();
+							var trigger = dojo.create("li", {}, parent); //$NON-NLS-0$
+							var subMenu = this._createDropdownMenu(trigger, group.title, true);
+							commandService._render(childContributions, subMenu.menu, items, handler, "menu", userData, domNodeWrapperList);  //$NON-NLS-0$
+							if (subMenu.menu.childNodes.length === 0) {
+								parent.removeChild(trigger);
 							}
 						} else {  
 							// menu items with leading and trailing separators
-							// don't render a separator if there is nothing preceding, or if the last thing was a separator
-							var menuSep;
-							if (parent.getChildren().length > 0 && !this._isLastChildSeparator(parent, renderType)) {
-								menuSep = new dijit.MenuSeparator();
-								parent.addChild(menuSep);
+							// don't render a separator if there is nothing preceding
+							if (parent.childNodes.length > 0) {
+								this._generateMenuSeparator(parent);
 							}
 							// synchronously render the children since order matters
 							commandService._render(childContributions, parent, items, handler, renderType, userData, domNodeWrapperList); 
 							// Add a trailing separator if children rendered.
-							var menuChildren = parent.getChildren();
-							if (menuChildren[menuChildren.length - 1] !== menuSep) {
-								menuSep = new dijit.MenuSeparator();
-								parent.addChild(menuSep);
-							}
+							this._generateMenuSeparator(parent);
 						}
 					}
 				} else {
@@ -1106,50 +943,30 @@
 					if (render) {
 						// special case.  The item wants to provide a set of choices
 						if (command.choiceCallback) {
-							var choicesMenu = new dijit.Menu({
-								style: "display: none;" //$NON-NLS-0$
-							});
+							var menuParent;
+							var nodeClass;
 							if (renderType === "tool" || renderType === "button") { //$NON-NLS-1$ //$NON-NLS-0$
-								menuButton = new CommandDropDownButton({
-										label: command.name,
-										dropDown: choicesMenu,
-										postCreate: function() {
-											// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=383035#c1
-											dojo.connect(this._buttonNode, "mousedown", this, function(e) { //$NON-NLS-0$
-												this.eclipseCommand.populateChoicesMenu(this.eclipseChoices, items, handler, userData);
-											});
-											CommandDropDownButton.prototype.postCreate.apply(this, Array.prototype.slice.call(arguments));
-										}});
-								dojo.addClass(menuButton.domNode, "commandMenu"); //$NON-NLS-0$
-								dojo.removeAttr(menuButton.titleNode, "title"); // there is no need for a native browser tooltip //$NON-NLS-0$
-								dojo.destroy(menuButton.valueNode); // the valueNode gets picked up by screen readers; since it's not used, we can get rid of it
-								if (command.image) {
-									dojo.addClass(menuButton.iconNode, "commandImage"); //$NON-NLS-0$
-									menuButton.iconNode.src = command.image;
+								menuParent = parent;
+								if (parent.nodeName.toLowerCase() === "ul") { //$NON-NLS-0$
+									menuParent = dojo.create("li", {}, parent); //$NON-NLS-0$
+								} else {
+									nodeClass = "commandMargins"; //$NON-NLS-0$
 								}
-								dojo.place(menuButton.domNode, parent, "last"); //$NON-NLS-0$
-								menuButton.eclipseCommand = command;
-								menuButton.eclipseChoices = choicesMenu;
-							} else if (renderType === "menu") { //$NON-NLS-0$
-								// parent is already a menu
-								var popup = new CommandPopupMenuItem({
-									label: command.name,
-									popup: choicesMenu
-								});
-								parent.addChild(popup);
-								popup.eclipseCommand = command;
-								popup.eclipseChoices = choicesMenu;
-								// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=338887
-								dojo.connect(parent, "_openPopup", popup, function(event) { //$NON-NLS-0$
-									this.eclipseCommand.populateChoicesMenu(this.eclipseChoices, items, handler, userData);
-								});
+							} else {
+								menuParent = parent;
 							}
+							// dropdown button
+							var self = this;
+							var populateFunction = dojo.hitch(command, function(menu) {
+								this.populateChoicesMenu(menu, items, handler, userData, self);
+							});
+							this._createDropdownMenu(menuParent, command.name, true, populateFunction);
 						} else {
 							if (renderType === "tool") { //$NON-NLS-0$
-								id = "tool" + command.id + i;  // using the index ensures unique ids within the DOM when a command repeats for each item //$NON-NLS-0$
+								id = "tool" + command.id + i;  //$NON-NLS-0$ // using the index ensures unique ids within the DOM when a command repeats for each item
 								command._addTool(parent, id, invocation, domNodeWrapperList);	
 							} else if (renderType === "button") { //$NON-NLS-0$
-								id = "button" + command.id + i;  // using the index ensures unique ids within the DOM when a command repeats for each item //$NON-NLS-0$
+								id = "button" + command.id + i;  //$NON-NLS-0$ // using the index ensures unique ids within the DOM when a command repeats for each item 
 								command._addButton(parent, id, invocation, domNodeWrapperList);	
 							} else if (renderType === "menu") { //$NON-NLS-0$
 								command._addMenuItem(parent, invocation, domNodeWrapperList);
@@ -1160,6 +977,74 @@
 			}
 		},
 		
+		_createDropdownMenu: function(parent, name, nested, populateFunction) {
+			parent = lib.node(parent);
+			var destroyButton, arrowClass, extraClass;
+			var menuButton = dojo.create("span"); //$NON-NLS-0$
+			menuButton.classList.add("dropdownTrigger"); //$NON-NLS-0$
+			if (nested) {
+				menuButton.classList.add("dropdownMenuItem"); //$NON-NLS-0$
+				extraClass = "dropdownSubMenu"; //$NON-NLS-0$
+				arrowClass = "dropdownArrowRight"; //$NON-NLS-0$
+				menuButton.tabIndex = 0;
+				menuButton.role = "menuitem"; //$NON-NLS-0$
+			} else {
+				menuButton.classList.add("commandButton"); //$NON-NLS-0$
+				arrowClass = "dropdownArrowDown"; //$NON-NLS-0$
+				menuButton.tabIndex = 0; 
+				menuButton.role = "button"; //$NON-NLS-0$
+			}
+			var title = document.createTextNode(name);
+			menuButton.appendChild(title);
+			var arrow = document.createElement("span"); //$NON-NLS-0$
+			arrow.classList.add(arrowClass); //$NON-NLS-0$
+			menuButton.appendChild(arrow);
+			var menuParent = parent;
+			if (parent.nodeName.toLowerCase() === "ul") { //$NON-NLS-0$
+				menuParent = dojo.create("li", {}, parent); //$NON-NLS-0$
+				destroyButton = menuParent;
+			} else {
+				menuButton.classList.add("commandMargins"); //$NON-NLS-0$
+				destroyButton = menuButton;
+			}
+			menuParent.appendChild(menuButton);
+			if (extraClass) {
+				menuParent.classList.add(extraClass);
+			}
+			var newMenu = dojo.create("ul", {}, menuParent); //$NON-NLS-0$
+			dojo.addClass(newMenu, "dropdownMenu"); //$NON-NLS-0$
+			menuButton.dropdown = new mDropdown.Dropdown({dropdown: newMenu, populate: populateFunction});
+			newMenu.dropdown = menuButton.dropdown;
+			return {menuButton: menuButton, menu: newMenu, dropdown: menuButton.dropdown, destroyButton: destroyButton};
+		},
+		
+		_generateCheckedMenuItem: function(dropdown, name, checked, onChange) {
+			var itemNode = dojo.create("li", {}, dropdown); //$NON-NLS-0$
+			var node = document.createElement("input"); //$NON-NLS-0$
+			node.type = "checkbox";//$NON-NLS-0$
+			node.role = "menuitem"; //$NON-NLS-0$
+			node.value = checked.toString();
+			node.classList.add("dropdownMenuItem"); //$NON-NLS-0$
+			node.classList.add("checkedMenuItem"); //$NON-NLS-0$
+			var span = document.createElement("span"); //$NON-NLS-0$
+			var text = document.createTextNode(name); //$NON-NLS-0$
+			span.appendChild(text);
+			itemNode.appendChild(node);
+			itemNode.appendChild(span);
+			node.addEventListener("change", onChange, false); //$NON-NLS-0$
+		},
+		
+		_generateMenuSeparator: function(dropdown) {
+			if (!this._checkForTrailingSeparator(dropdown, "menu")) { //$NON-NLS-0$
+				var item = document.createElement("li"); //$NON-NLS-0$
+				item.classList.add("dropdownSeparator"); //$NON-NLS-0$
+				var sep = document.createElement("span"); //$NON-NLS-0$
+				sep.classList.add("dropdownSeparator"); //$NON-NLS-0$
+				item.appendChild(sep);
+				dropdown.appendChild(item);
+			}
+		},
+		
 				
 		/**
 		 * Add a dom node appropriate for using a separator between different groups
@@ -1264,7 +1149,7 @@
 			context.handler = context.handler || this;
 			var element, image;
 			if (this.hrefCallback) {
-				element = this._makeLink(context);
+				element = this._makeLink(context, "commandLink"); //$NON-NLS-0$
 				if (!element) {
 					return;
 				}
@@ -1277,11 +1162,11 @@
 				} else {
 					image = addImageToElement(this, element, name);
 					// ensure there is accessible text describing this image
-					this._addAccessibleLabel(element);
+					if (this.name) {
+						element.setAttribute("aria-label", this.name); //$NON-NLS-0$
+					}
 				}
 				this._hookCallback(element, context);
-				_setupActivateVisuals(element, element, image ? "commandImageOver" : "commandButtonOver");			 //$NON-NLS-1$ //$NON-NLS-0$
-
 			}
 			context.domNode = element;
 			context.domParent = parent;
@@ -1312,39 +1197,20 @@
 			context.handler = context.handler || this;
 			var element;
 			if (this.hrefCallback) {
-				element = this._makeLink(context);
-				if (!element) {
-					return;
+				element = this._makeLink(parent, context, "commandLink"); //$NON-NLS-0$
+			} else if (!this.name && this.hasImage()) {
+				// rare case but can happen for some icons we force with text
+				element = dojo.create("span", {tabindex: "0", role: "button"}); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+				addImageToElement(this, element, name);
+				// ensure there is accessible text describing this image if we have any
+				if (this.tooltip) {
+					element.setAttribute("aria-label", this.tooltip); //$NON-NLS-0$
 				}
 			} else {
-				element = dojo.create("span", {tabindex: "0", role: "button"}); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+				element = this._makeButton(parent, context, "commandButton"); //$NON-NLS-0$
 				this._hookCallback(element, context);
-				var overClass;
-				if (this.name) {
-					dojo.place(window.document.createTextNode(this.name), element, "last"); //$NON-NLS-0$
-					dojo.addClass(element, "commandButton"); //$NON-NLS-0$
-					overClass = "commandButtonOver"; //$NON-NLS-0$
-				} else {
-					// TODO we need a way to force a button contribution to look like a tool.  This is a very rare case.
-					addImageToElement(this, element, name);
-					overClass = "commandImageOver"; //$NON-NLS-0$
-					// ensure there is accessible text describing this image
-					this._addAccessibleLabel(element);
-				}
-				_setupActivateVisuals(element, element, overClass);			
-			}
-			element.id = name;
-			if (this.tooltip) {
-				new CommandTooltip({
-					connectId: [element],
-					label: this.tooltip,
-					position: ["above", "left", "right", "below"], // otherwise defaults to right and obscures adjacent commands //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
-					commandParent: parent,
-					commandService: context.commandService
-				});
 			}
 			context.domParent = parent;
-			context.domNode = element;
 			if (parent.nodeName.toLowerCase() === "ul") { //$NON-NLS-0$
 				parent = dojo.create("li", {}, parent); //$NON-NLS-0$
 			} else {
@@ -1353,101 +1219,108 @@
 			dojo.place(element, parent, "last"); //$NON-NLS-0$
 			mNavUtils.generateNavGrid(domNodeWrapperList, context.domNode);
 		},
+		
 		_addMenuItem: function(parent, context, domNodeWrapperList) {
-			var showIcon = context.commandService.showMenuIcons;
-			context.domParent = parent.domNode;
-			var menuitem = new CommandMenuItem({
-				labelType: this.hrefCallback ? "html" : "text", //$NON-NLS-1$ //$NON-NLS-0$
-				label: this.name,
-				iconClass: showIcon ? this.imageClass : null,
-				hasLink: !!this.hrefCallback
-			});
-			if (this.tooltip) {
-				new CommandTooltip({
-					connectId: [menuitem.domNode],
-					label: this.tooltip,
-					commandParent: parent,
-					commandService: context.commandService
-				});
-			}
+			context.domParent = parent;
+			var element;
+			var dropdown = parent.dropdown;
 			if (this.hrefCallback) {
-				var loc = this.hrefCallback.call(context.handler, context);
-				if (loc) {
-					if (loc.then) {
-						loc.then(dojo.hitch(this, function(l) { 
-							menuitem.setLink(l, this.name); 
-						}));
-					} else if (loc) {
-						menuitem.setLink(loc, this.name);
-					} else {
-						return;
-					}
+				element = this._makeLink(parent, context, "dropdownMenuItem"); //$NON-NLS-0$
+			} else {
+				element = this._makeButton(parent, context, "dropdownMenuItem"); //$NON-NLS-0$
+				if (this.callback) {
+					this._hookCallback(element, context, function() {dropdown.close(true);});
 				}
-			} else if (this.callback) {
-				menuitem.onClick = dojo.hitch(this, function() {
-					context.commandService._invoke(context);
-				});
 			}
+			element.role = "menuitem";  //$NON-NLS-0$
 			
-			// we may need to refer back to the command.  
-			menuitem.eclipseCommand = this;
-			parent.addChild(menuitem);
-			if (showIcon) {
-				if (this.imageClass) {
-					dojo.addClass(menuitem.iconNode, this.spriteClass);
-				} else if (this.image) {
-					dojo.addClass(menuitem.iconNode, "commandMenuItem"); //$NON-NLS-0$
-					// reaching...
-					menuitem.iconNode.src = this.image;
-				}
-			}
-			context.domNode = menuitem.domNode;
 			mNavUtils.generateNavGrid(domNodeWrapperList, context.domNode);
+			if (parent.nodeName.toLowerCase() === "ul") { //$NON-NLS-0$
+				parent = dojo.create("li", {}, parent); //$NON-NLS-0$
+			} else {
+				dojo.addClass(element, "commandMargins"); //$NON-NLS-0$
+			}
+			dojo.place(element, parent, "last"); //$NON-NLS-0$
+
 		},
 		
 		/*
 		 * stateless helper
 		 */
-		 _makeLink: function(context) {
-			var element = dojo.create("a", {tabindex: "0"}); //$NON-NLS-1$ //$NON-NLS-0$
-			dojo.addClass(element, "commandLink"); //$NON-NLS-0$
-			dojo.place(window.document.createTextNode(this.name), element, "last"); //$NON-NLS-0$
-			var href = this.hrefCallback.call(context.handler, context);
-			if (href.then){
-				href.then(function(l){
-					element.href = l;
-				});
-			} else if (href) {
-				element.href = href; 
-			} else {  // no href, we don't want the link
-				return null;
+		_makeButton: function(parent, context, aClass) {
+			var element = document.createElement("span"); //$NON-NLS-0$
+			element.tabIndex = 0; 
+			element.id = this.name;
+			var text = document.createTextNode(this.name);
+			element.appendChild(text);
+			if (aClass) {
+				element.classList.add(aClass); //$NON-NLS-0$
 			}
+			if (this.tooltip) {
+				new CommandTooltip({
+					connectId: [element],
+					label: this.tooltip,
+					commandParent: parent,
+					commandService: context.commandService
+				});
+			}
+			context.domNode = element;
 			return element;
 		 },
 		
 		/*
 		 * stateless helper
 		 */
-		_hookCallback: function(domNode, context) {
-			dojo.connect(domNode, "onclick", this, function() { //$NON-NLS-0$
-				context.commandService._invoke(context);
-			});
-			// onClick events do not register for spans when using the keyboard
-			dojo.connect(domNode, "onkeypress", this, function(e) { //$NON-NLS-0$
-				if (e.keyCode === dojo.keys.ENTER || e.charCode === dojo.keys.SPACE) {						
-					context.commandService._invoke(context);					
-				}				
-			});
-		},
+		 _makeLink: function(parent, context, aClass) {
+			var element = dojo.create("a", {tabindex: "0"}); //$NON-NLS-1$ //$NON-NLS-0$
+			element.id = this.name;
+			if (aClass) {
+				dojo.addClass(element, aClass); //$NON-NLS-0$
+			}
+			dojo.place(window.document.createTextNode(this.name), element, "last"); //$NON-NLS-0$
+			if (this.hrefCallback) {
+				var href = this.hrefCallback.call(context.handler, context);
+				if (href.then){
+					href.then(function(l){
+						element.href = l;
+					});
+				} else if (href) {
+					element.href = href; 
+				} else {  // no href
+					element.href = "#"; //$NON-NLS-0$
+				}
+			}
+			if (this.tooltip) {
+				new CommandTooltip({
+					connectId: [element],
+					label: this.tooltip,
+					commandParent: parent,
+					commandService: context.commandService
+				});
+			}
+
+			context.domNode = element;
+			return element;
+		 },
 		
 		/*
 		 * stateless helper
 		 */
-		_addAccessibleLabel: function(element) {
-			var label = this.name || this.tooltip;
-			if (label) {
-				dojo.attr(element, "aria-label", label); //$NON-NLS-0$
-			}
+		_hookCallback: function(domNode, context, before, after) {
+			domNode.addEventListener("click", function(e) { //$NON-NLS-0$
+				if (before) { before(); }
+				context.commandService._invoke(context);
+				if (after) { after(); }
+				lib.stop(e);
+			}, false);
+			domNode.addEventListener("keydown", function(e) { //$NON-NLS-0$
+				if (e.keyCode === lib.KEY.ENTER || e.charCode === lib.KEY.SPACE) {						
+					if (before) { before(); }
+					context.commandService._invoke(context);					
+					if (after) { after(); }
+					lib.stop(e);
+				}				
+			}, false);
 		},
 		
 		/**
@@ -1455,38 +1328,35 @@
 		 * Used internally by the command service.  Not intended to be overridden or called
 		 * externally.
 		 */
-		 populateChoicesMenu: function(menu, items, handler, userData) {
-			// see http://bugs.dojotoolkit.org/ticket/10296
-			menu.focusedChild = null;
-			dojo.forEach(menu.getChildren(), function(child) {
-				menu.removeChild(child);
-				child.destroy();
-			});
-
+		 populateChoicesMenu: function(parent, items, handler, userData, commandService) {
 			var choices = this.getChoices(items, handler, userData);
-			var showIcon = this.showMenuIcons;
-
 			for (var j=0; j<choices.length; j++) {
 				var choice = choices[j];
-				var menuitem;
 				if (choice.name) {
-					menuitem = new dijit.MenuItem({
-						label: choice.name,
-						iconClass: showIcon ? choice.imageClass : null,
-						onClick: this.makeChoiceCallback(choice, items)
-					});
-					if (showIcon) {
-						if (choice.imageClass) {
-							dojo.addClass(menuitem.iconNode, choice.spriteClass || "commandSprite"); //$NON-NLS-0$
-						} else if (choice.image) {
-							dojo.addClass(menuitem.iconNode, "commandImage"); //$NON-NLS-0$
-							menuitem.iconNode.src = choice.image;
+					var itemNode = dojo.create("li", {}, parent); //$NON-NLS-0$
+					var node = document.createElement("span"); //$NON-NLS-0$
+					node.tabIndex = 0; 
+					node.role = "menuitem"; //$NON-NLS-0$
+					node.classList.add("dropdownMenuItem"); //$NON-NLS-0$
+					var text = document.createTextNode(choice.name); //$NON-NLS-0$
+					node.appendChild(text);
+					itemNode.appendChild(node);
+					node.choice = choice;
+					node.addEventListener("click", function(event) { //$NON-NLS-0$
+						if (event.target.choice) {
+							event.target.choice.callback.call(event.target.choice, items);
 						}
-					}
+					}, false); 
+					node.addEventListener("keydown", function(event) { //$NON-NLS-0$
+						if (event.keyCode === lib.KEY.ENTER || event.charCode === lib.KEY.SPACE) {
+							if (event.target.choice) {
+								event.target.choice.callback.call(event.target.choice, items);
+							}
+						}
+					}, false);
 				} else {  // anything not named is a separator
-					menuitem = new dijit.MenuSeparator();
+					commandService._generateMenuSeparator(parent);
 				}
-				menu.addChild(menuitem);
 			}
 		},
 		
@@ -1831,7 +1701,6 @@
 		CommandKeyBinding: CommandKeyBinding,
 		Command: Command,
 		CommandInvocation: CommandInvocation,
-		CommandMenuItem: CommandMenuItem,
 		URLBinding: URLBinding,
 		ParametersDescription: ParametersDescription,
 		CommandParameter: CommandParameter,
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/commonHTMLFragments.js b/bundles/org.eclipse.orion.client.core/web/orion/commonHTMLFragments.js
index fef5bc8..636f1e9 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/commonHTMLFragments.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/commonHTMLFragments.js
@@ -12,8 +12,8 @@
 /*global window document define login logout localStorage orion */
 /*browser:true*/
 
-define(['i18n!orion/nls/messages', 'require'], 
-        function(messages, require){
+define(['i18n!orion/nls/messages', 'require', 'orion/webui/littlelib'], 
+        function(messages, require, lib){
 	
 	function asHTMLText(input) {
 		if (!input) {
@@ -35,16 +35,21 @@
 	
 	'<header id="banner" role="banner" class="headerLayout">' + //$NON-NLS-0$
 		//Top row:  Logo + discovery links + user
-		'<div id="staticBanner" class="layoutBlock topRowBanner">' + //$NON-NLS-0$
+		'<div id="staticBanner" class="primaryNav layoutBlock topRowBanner">' + //$NON-NLS-0$
 			'<a id="home" class="layoutLeft logo" href="' + require.toUrl("navigate/table.html") + '" aria-label="Orion Home"></a>' + //$NON-NLS-8$ //$NON-NLS-6$ //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
-			'<nav id="primaryNav" class="layoutLeft primaryNav" role="navigation"></nav>' + //$NON-NLS-0$
+			'<nav id="primaryNav" class="layoutLeft" role="navigation"></nav>' + //$NON-NLS-0$
 			'<div class="layoutRight">' + //$NON-NLS-0$
 				'<div id="globalActions" class="spacingLeft layoutLeft"></div>' + //$NON-NLS-0$
-				'<div id="relatedLinks" class="spacingLeft layoutLeft" style="padding-top:1px;"></div>' + //$NON-NLS-0$
+				'<div id="relatedLinks" class="spacingLeft layoutLeft" style="padding-top:1px;">' + //$NON-NLS-0$
+					'<span tabindex="0" role="button" id="relatedTrigger" class="dropdownTrigger hidden">' + messages["Related"] + '<span class="dropdownArrowDown"></span></span>' +  //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+					'<ul id="relatedDropdown" class="dropdownMenu" role="menu"></ul>' + //$NON-NLS-0$
+				'</div>' + //$NON-NLS-0$
 				'<input type="text" id="search" autocomplete="off" placeholder="Search" title="Type a keyword or wild card to search in root" class="layoutLeft spacingLeft searchbox" role="search">' + //$NON-NLS-2$ //$NON-NLS-0$
 				'<div id="searchOptions" class="layoutLeft" style="padding-top:1px;"></div>' + //$NON-NLS-0$
-				// '<div id="userInfo" style= "display:none;" class="layoutLeft primaryNav"></div>' + //$NON-NLS-0$
-				'<div id="userMenu" class="spacingLeft layoutLeft"></div>' + //$NON-NLS-0$
+				'<div id="userMenu" class="spacingLeft layoutLeft">' + //$NON-NLS-0$
+					'<span id="userTrigger" tabindex="0" role="button" class="dropdownTrigger">' + messages["Options"] + '<span class="dropdownArrowDown"></span></span>' +  //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+					'<ul id="userDropdown" class="dropdownMenu" role="menu"></ul>' + //$NON-NLS-0$
+				'</div>' + //$NON-NLS-0$
 			'</div>' + //$NON-NLS-0$
 		'</div>' + //$NON-NLS-0$
 		//Title area
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/compare/compareTreeExplorer.js b/bundles/org.eclipse.orion.client.core/web/orion/compare/compareTreeExplorer.js
index 64a0177..6b8f1e8 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/compare/compareTreeExplorer.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/compare/compareTreeExplorer.js
@@ -353,29 +353,13 @@
 
 	CompareTreeExplorer.prototype._addOptions = function() {
 		var that = this;
-		var optionMenu = dijit.byId("compareTreeOptMenu"); //$NON-NLS-0$
-		if (optionMenu) {
-			optionMenu.destroy();
-		}
-		var newMenu = new dijit.Menu({
-			style : "display: none;", //$NON-NLS-0$
-			id : "compareTreeOptMenu" //$NON-NLS-0$
-		});
-		
-		newMenu.addChild(new dijit.CheckedMenuItem({
-			label: messages["Sort by folders"],
-			checked: false,
-			onChange : function(checked) {
-				that._sortByFolder = checked;
+		var optionMenu = that._commandService._createDropdownMenu("pageNavigationActions", messages['Options']);
+		that._commandService._generateCheckedMenuItem(optionMenu.menu, messages["Sort by folders"], false,
+			function(event) {
+				that._sortByFolder = event.target.checked;
 				that._renderUI();
-			}
-		}));
-		var menuButton = new dijit.form.DropDownButton({
-			label : messages["Options"],
-			dropDown : newMenu
-		});
-		dojo.addClass(menuButton.domNode, "commandMenu"); //$NON-NLS-0$
-		dojo.place(menuButton.domNode, "pageNavigationActions", "last"); //$NON-NLS-1$ //$NON-NLS-0$
+				optionMenu.dropdown.close(true);
+			});
 	};
 
 	CompareTreeExplorer.prototype._renderUI = function() {
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/globalCommands.js b/bundles/org.eclipse.orion.client.core/web/orion/globalCommands.js
index 1f1e94e..db95136 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/globalCommands.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/globalCommands.js
@@ -13,9 +13,13 @@
 /*browser:true*/
 
 define(['i18n!orion/nls/messages', 'require', 'dojo', 'dijit', 'orion/commonHTMLFragments', 'orion/commands', 'orion/parameterCollectors', 
-	'orion/extensionCommands', 'orion/uiUtils', 'orion/textview/keyBinding', 'orion/breadcrumbs', 'orion/splitter', 'orion/favorites', 'orion/contentTypes', 'orion/URITemplate', 'orion/PageUtil', 'orion/widgets/themes/container/ThemeSheetWriter', 'orion/searchUtils', 'orion/inputCompletion/inputCompletion', 'orion/globalSearch/advSearchOptContainer', "orion/Deferred",
-	'dojo/DeferredList', 'dijit/Menu', 'dijit/MenuItem', 'dijit/form/DropDownButton', 'orion/widgets/OpenResourceDialog', 'orion/widgets/UserMenu', 'orion/widgets/UserMenuDropDown'], 
-        function(messages, require, dojo, dijit, commonHTML, mCommands, mParameterCollectors, mExtensionCommands, mUIUtils, mKeyBinding, mBreadcrumbs, mSplitter, mFavorites, mContentTypes, URITemplate, PageUtil, ThemeSheetWriter, mSearchUtils, mInputCompletion, mAdvSearchOptContainer, Deferred){
+	'orion/extensionCommands', 'orion/uiUtils', 'orion/textview/keyBinding', 'orion/breadcrumbs', 'orion/webui/littlelib', 'orion/webui/splitter', 
+	'orion/webui/dropdown', 'orion/favorites', 'orion/contentTypes', 'orion/URITemplate', 'orion/PageUtil', 'orion/widgets/themes/container/ThemeSheetWriter', 
+	'orion/searchUtils', 'orion/inputCompletion/inputCompletion', 'orion/globalSearch/advSearchOptContainer', 'orion/Deferred',
+	'orion/widgets/UserMenu', 'dojo/DeferredList', 'orion/widgets/OpenResourceDialog'], 
+        function(messages, require, dojo, dijit, commonHTML, mCommands, mParameterCollectors, mExtensionCommands, mUIUtils, mKeyBinding, mBreadcrumbs, lib, mSplitter, 
+        mDropdown, mFavorites, mContentTypes, URITemplate, PageUtil, ThemeSheetWriter, mSearchUtils, mInputCompletion, 
+        mAdvSearchOptContainer, Deferred, mUserMenu){
 
 	/**
 	 * This class contains static utility methods. It is not intended to be instantiated.
@@ -33,7 +37,6 @@
 
 	var notifyAuthenticationSite = qualifyURL(require.toUrl('auth/NotifyAuthentication.html')); //$NON-NLS-0$
 	var authRendered = {};
-	var userMenu = new orion.widgets.UserMenu();
 	
 	function getLabel(authService, serviceReference){
 		if(authService.getLabel){
@@ -54,17 +57,29 @@
 		}
 	}
 	
-	function setUserName(registry, dropdown){
+	function setUserName(registry, node){
 			
 			var authService = registry.getService("orion.core.auth"); //$NON-NLS-0$
 			if (authService !== null) {
 				authService.getUser().then(function(jsonData){
+					var text;
 					if( jsonData.Name ){
-						//dropdown.set( 'label', jsonData.Name ); //$NON-NLS-0$
-						dropdown.containerNode.textContent = jsonData.Name;
+						text = document.createTextNode(jsonData.Name); 
 					}else if( jsonData.login ){
-						dropdown.containerNode.textContent = jsonData.login;
+						var text = document.createTextNode(jsonData.login);
 					} 
+					if (text) {
+						if (node.childNodes.length > 0) {
+							if (node.childNodes[0].nodeType === 3) {
+								// replace original text
+								node.replaceChild(text, node.childNodes[0]);
+							} else {
+								node.insertBefore(text, node.childNodes[0]);
+							}
+						} else {
+							node.appendChild(text);
+						}
+					}
 				});
 			}
 		}
@@ -74,7 +89,7 @@
 	 * @name orion.globalCommands#generateUserInfo
 	 * @function
 	 */
-	function generateUserInfo(serviceRegistry) {
+	function generateUserInfo(serviceRegistry, keyAssistFunction) {
 		
 		var authServices = serviceRegistry.getServiceReferences("orion.core.auth"); //$NON-NLS-0$
 		authenticationIds = [];
@@ -82,30 +97,22 @@
 		if(!userMenuPlaceholder){
 			return;
 		}
+		var dropdownNode = lib.node("userDropdown"); //$NON-NLS-0$
+		var userDropdown = new mDropdown.Dropdown({
+			dropdown: dropdownNode
+		});
+		var menuGenerator = new mUserMenu.UserMenu({dropdownNode: dropdownNode, dropdown: userDropdown});
+		var dropdownTrigger = lib.node("userTrigger"); //$NON-NLS-0$
 		
-		if(!dijit.byId('logins')){ //$NON-NLS-0$
-			var menuButton = new orion.widgets.UserMenuDropDown({
-				id: "logins", //$NON-NLS-0$
-				dropDown: userMenu,
-				label: messages["Options"], 
-				showLabel: true
-			});
-			dojo.place(menuButton.domNode, userMenuPlaceholder, "only"); //$NON-NLS-0$
-			if(menuButton.valueNode) {  // accessibility, remove value node so screen reader does not stop there.
-		        dojo.destroy(menuButton.valueNode);
-			}
-			if(menuButton.titleNode && dojo.attr(menuButton.titleNode, "title")) { //$NON-NLS-0$
-				dojo.removeAttr(menuButton.titleNode, "title"); //$NON-NLS-0$
-			}
-			new mCommands.CommandTooltip({
-				connectId: [menuButton.focusNode],
-				label: messages['Options'],
-				position: ["above", "left", "right", "below"] // otherwise defaults to right and obscures adjacent commands //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
-			});
+		new mCommands.CommandTooltip({
+			connectId: [dropdownTrigger],
+			label: messages['Options'],
+			position: ["above", "left", "right", "below"] // otherwise defaults to right and obscures adjacent commands //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+		});
 			
-			setUserName( serviceRegistry, menuButton );
-		}
-		
+		setUserName(serviceRegistry, dropdownTrigger);
+		menuGenerator.setKeyAssist(keyAssistFunction);
+
 		for(var i=0; i<authServices.length; i++){
 			var servicePtr = authServices[i];
 			var authService = serviceRegistry.getService(servicePtr);		
@@ -114,10 +121,10 @@
 					authService.getKey().then(function(key){
 						authenticationIds.push(key);
 						authService.getUser().then(function(jsonData){
-							userMenu.addUserItem(key, authService, label, jsonData);
+							menuGenerator.addUserItem(key, authService, label, jsonData);
 						}, 
 						function(errorData, jsonData){
-							userMenu.addUserItem(key, authService, label, jsonData);
+							menuGenerator.addUserItem(key, authService, label, jsonData);
 						});
 						window.addEventListener("storage", function(e){ //$NON-NLS-0$
 							if(authRendered[key] === localStorage.getItem(key)){
@@ -127,10 +134,10 @@
 							authRendered[key] = localStorage.getItem(key);
 							
 							authService.getUser().then(function(jsonData){
-								userMenu.addUserItem(key, authService, label, jsonData);
+								menuGenerator.addUserItem(key, authService, label, jsonData);
 							}, 
 							function(errorData){
-								userMenu.addUserItem(key, authService, label);
+								menuGenerator.addUserItem(key, authService, label);
 							});				
 						}, false);
 					});							
@@ -165,10 +172,9 @@
 		dojo.addClass(dropDownImage, "bannerMenuSearchOptions"); //$NON-NLS-0$
 	}
 	
-	// Related links menu management.  The related drop down widget and its associated dropdown menu
-	// are created when needed.  The links menu is reused as content changes.  If the links menu becomes
+	// Related links menu management.  The related menu is reused as content changes.  If the menu becomes
 	// empty, we hide the dropdown.
-	var linksMenu;
+	var linksDropdown;
 	var pageItem;
 	var exclusions = [];
 	var favoriteTarget = null;
@@ -180,57 +186,31 @@
 			// document not loaded
 			return;
 		}
-		if (linksMenu) {
-			var dropdown = dijit.byId("related"); //$NON-NLS-0$
-			if (dropdown) {
-				dropdown.closeDropDown();
-			}
-			// see http://bugs.dojotoolkit.org/ticket/10296
-			linksMenu.focusedChild = null;
-			dojo.forEach(linksMenu.getChildren(), function(child) {
-				linksMenu.removeChild(child);
-				child.destroy();
-			});
+		if (linksDropdown) {
+			linksDropdown.close();
+			linksDropdown.empty();
 		}
 	}
 	
 	function _checkForEmptyLinksMenu() {
-		var dropdownNode = dojo.byId("relatedLinks"); //$NON-NLS-0$
-		if (linksMenu && dropdownNode) {
-			if (linksMenu.getChildren().length === 0) {
-				dojo.style(dropdownNode, "visibility", "hidden"); //$NON-NLS-0$ //$NON-NLS-1$
+		var triggerNode = lib.node("relatedTrigger"); //$NON-NLS-0$
+		if (linksDropdown && triggerNode) {
+			if (linksDropdown.getItems().length === 0) {
+				dojo.style(triggerNode, "visibility", "hidden"); //$NON-NLS-0$ //$NON-NLS-1$
 			} else {
-				dojo.style(dropdownNode, "visibility", "visible");//$NON-NLS-0$ //$NON-NLS-1$
+				dojo.style(triggerNode, "visibility", "visible");//$NON-NLS-0$ //$NON-NLS-1$
 			}
 		}
 	}
 	
 	function _addRelatedLinkCommand(command, invocation) {
-		if (!linksMenu) {
-			linksMenu = new dijit.Menu({
-				style: "display: none;padding:3px;border-radius:3px;", //$NON-NLS-0$
-				id: "relatedLinksMenu" //$NON-NLS-0$
+		var dropdownNode = lib.node("relatedDropdown"); //$NON-NLS-0$
+		if (!linksDropdown) {
+			linksDropdown = new mDropdown.Dropdown({
+				dropdown: dropdownNode
 			});
 		}
-		command._addMenuItem(linksMenu, invocation);
-
-		var menuButton = dijit.byId("related"); //$NON-NLS-0$
-		var domNode = dojo.byId("relatedLinks"); //$NON-NLS-0$
-		if (domNode && !menuButton) {
-			menuButton = new orion.widgets.UserMenuDropDown({
-				id: "related", //$NON-NLS-0$
-				label: messages["Related"],
-				dropDown: linksMenu
-			});
-			if(menuButton.valueNode) {  // accessibility, remove value node so screen reader does not stop there.
-				dojo.destroy(menuButton.valueNode);
-			}
-			if(menuButton.titleNode && dojo.attr(menuButton.titleNode, "title")) { //$NON-NLS-0$
-				dojo.removeAttr(menuButton.titleNode, "title"); //$NON-NLS-0$
-			}
-			dojo.addClass(menuButton.domNode, "bannerMenu"); //$NON-NLS-0$
-			dojo.place(menuButton.domNode, domNode, "only"); //$NON-NLS-0$
-		}	
+		command._addMenuItem(dropdownNode, invocation);
 	}	
 	/**
 	 * Adds the related links to the banner
@@ -1074,12 +1054,11 @@
 			editor.getTextView().setAction(keyAssistCommand.id, keyAssistCommand.callback, keyAssistCommand);
 		}
 		
-		userMenu.setKeyAssist(keyAssistCommand.callback);
 		checkFavoritesButton(serviceRegistry, commandService);
 
 		renderGlobalCommands(commandService);
 		
-		generateUserInfo(serviceRegistry);
+		generateUserInfo(serviceRegistry, keyAssistCommand.callback);
 		
 		// now that footer containing progress pane is added
 		startProgressService(serviceRegistry);
@@ -1115,8 +1094,6 @@
 	
 	//return the module exports
 	return {
-		generateUserInfo: generateUserInfo,
-		generateRelatedLinks: generateRelatedLinks,
 		generateBanner: generateBanner,
 		getToolbarElements: getToolbarElements,
 		layoutToolbarElements: layoutToolbarElements,
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/searchAndReplace/textSearcher.js b/bundles/org.eclipse.orion.client.core/web/orion/searchAndReplace/textSearcher.js
index f30f6fe..74a0796 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/searchAndReplace/textSearcher.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/searchAndReplace/textSearcher.js
@@ -10,8 +10,8 @@
  ******************************************************************************/
 /*global define window document navigator*/
 
-define(['i18n!orion/search/nls/messages', 'require', 'orion/textview/annotations', 'dojo', 'dijit', 'orion/commands', 'orion/editor/regex', 'orion/searchUtils', 'dijit/Menu', 'dijit/MenuItem', 'dijit/form/DropDownButton' ], 
-	function(messages, require, mAnnotations, dojo, dijit, mCommands, mRegex, mSearchUtils){
+define(['i18n!orion/search/nls/messages', 'require', 'orion/textview/annotations', 'dojo', 'orion/commands', 'orion/editor/regex', 'orion/searchUtils' ], 
+	function(messages, require, mAnnotations, dojo, mCommands, mRegex, mSearchUtils){
 	
 var orion = orion || {};
 
@@ -81,19 +81,14 @@
 				that.createButton(messages["Replace"], parentDiv, function() {that.replace();});				
 				that.createButton(messages["Replace All"], parentDiv, function() {that.replaceAll();});	
 
-				var optionMenu = dijit.byId("searchOptMenu"); //$NON-NLS-0$
-				if (optionMenu) {
-					optionMenu.destroy();
-				}
-				var newMenu = new dijit.Menu({
-					style : "display: none;", //$NON-NLS-0$
-					id : "searchOptMenu" //$NON-NLS-0$
-				});
-				
-				newMenu.addChild(new dijit.CheckedMenuItem({
-					label: messages["Show all"],
-					checked: that._showAllOccurrence,
-					onChange : function(checked) {
+				var optionsDiv = document.createElement("div"); //$NON-NLS-0$
+				parentDiv.appendChild(optionsDiv);
+				optionsDiv.classList.add("findOptionsDiv"); //$NON-NLS-0$
+				var optionMenu = that._commandService._createDropdownMenu(optionsDiv, messages['Options']);
+				optionMenu.menuButton.classList.add("findSlideoutMenu"); //$NON-NLS-0$
+				that._commandService._generateCheckedMenuItem(optionMenu.menu, messages["Show all"], that._showAllOccurrence,
+					function(event) {
+						var checked = event.target.checked;
 						that.setOptions({showAllOccurrence: checked});
 						if(checked){
 							that.markAllOccurrences(true);
@@ -103,62 +98,45 @@
 								annotationModel.removeAnnotations(mAnnotations.AnnotationType.ANNOTATION_MATCHING_SEARCH);
 							}
 						}
-					}
-				}));
+						optionMenu.dropdown.close(true);
+					});
 				
-				newMenu.addChild(new dijit.CheckedMenuItem({
-					label: messages["Case sensitive"],
-					checked: !that._ignoreCase,
-					onChange : function(checked) {
-						that.setOptions({ignoreCase: !checked});
-					}
-				}));
+				that._commandService._generateCheckedMenuItem(optionMenu.menu, messages["Case sensitive"], !that._ignoreCase,
+					function(event) {
+						that.setOptions({ignoreCase: !event.target.checked});
+						optionMenu.dropdown.close(true);
+					});
 				
-				newMenu.addChild(new dijit.CheckedMenuItem({
-					label: messages["Wrap search"],
-					checked: that._wrapSearch,
-					onChange : function(checked) {
-						that.setOptions({wrapSearch: checked});
-					}
-				}));
-				newMenu.addChild(new dijit.CheckedMenuItem({
-					label: messages["Incremental search"],
-					checked: that._incremental,
-					onChange : function(checked) {
-						that.setOptions({incremental: checked});
-					}
-				}));
+				that._commandService._generateCheckedMenuItem(optionMenu.menu,  messages["Wrap search"], that._wrapSearch,
+					function(event) {
+						that.setOptions({wrapSearch: event.target.checked});
+						optionMenu.dropdown.close(true);
+					});
+					
+				that._commandService._generateCheckedMenuItem(optionMenu.menu,  messages["Incremental search"], that._incremental,
+					function(event) {
+						that.setOptions({incremental: event.target.checked});
+						optionMenu.dropdown.close(true);
+					});
+					
+				that._commandService._generateCheckedMenuItem(optionMenu.menu,  messages["Whole Word"], that._wholeWord,
+					function(event) {
+						that.setOptions({wholeWord: event.target.checked});
+						optionMenu.dropdown.close(true);
+					});
+					
+				that._commandService._generateCheckedMenuItem(optionMenu.menu,  messages["Regular expression"], that._useRegExp,
+					function(event) {
+						that.setOptions({useRegExp: event.target.checked});
+						optionMenu.dropdown.close(true);
+					});
 				
-				newMenu.addChild(new dijit.CheckedMenuItem({
-					label: messages["Whole Word"],
-					checked: that._wholeWord,
-					onChange : function(checked) {
-						that.setOptions({wholeWord: checked});
-					}
-				}));
-				
-				newMenu.addChild(new dijit.CheckedMenuItem({
-					label: messages["Regular expression"],
-					checked: that._useRegExp,
-					onChange : function(checked) {
-						that.setOptions({useRegExp: checked});
-					}
-				}));
-				
-				newMenu.addChild(new dijit.CheckedMenuItem({
-					label: messages["Find after replace"],
-					checked: that._findAfterReplace,
-					onChange : function(checked) {
-						that.setOptions({findAfterReplace: checked});
-					}
-				}));
-				
-				var menuButton = new dijit.form.DropDownButton({
-					label : messages["Options"],
-					dropDown : newMenu
-				});
-				dojo.addClass(menuButton.domNode, "findSlideoutMenu"); //$NON-NLS-0$
-				dojo.place(menuButton.domNode, parentDiv, "last"); //$NON-NLS-0$
+				that._commandService._generateCheckedMenuItem(optionMenu.menu,  messages["Find after replace"], that._findAfterReplace,
+					function(event) {
+						that.setOptions({findAfterReplace: event.target.checked});
+						optionMenu.dropdown.close(true);
+					});
+					
 				return searchStringDiv;
 			},
 			function(){that.closeUI();});
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/searchExplorer.js b/bundles/org.eclipse.orion.client.core/web/orion/searchExplorer.js
index 955e781..a219523 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/searchExplorer.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/searchExplorer.js
@@ -1263,38 +1263,22 @@
 		this._commandService.destroy("pageNavigationActions"); //$NON-NLS-0$
 		this._commandService.renderCommands("pageNavigationActions", "pageNavigationActions", that, that, "button"); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
 		
-		var optionMenu = dijit.byId("globalSearchOptMenu"); //$NON-NLS-0$
-		if (optionMenu) {
-			optionMenu.destroy();
-		}
-		var newMenu = new dijit.Menu({
-			style : "display: none;", //$NON-NLS-0$
-			id : "globalSearchOptMenu" //$NON-NLS-0$
-		});
+		var newMenu = this._commandService._createDropdownMenu("pageNavigationActions", messages['Options'], false, function() { //$NON-NLS-0$
+			if(!that.model.replaceMode()){
+				that._commandService._generateCheckedMenuItem(newMenu.menu, messages["Sort by Name"], that.model.sortByName,
+					function(event) {
+						that.sortWithName(event.target.checked);
+						window.setTimeout(function() {newMenu.dropdown.close(true);}, 100);  // so user can see the check take effect briefly before it closes
+					});
+			} else {
+				that._commandService._generateCheckedMenuItem(newMenu.menu, messages["Compare changes"], true,
+					function(event) {
+						that.toggleCompare(event.target.checked);
+						window.setTimeout(function() {newMenu.dropdown.close(true);}, 100);
+					});
+			}		
+		}); 
 		
-		if(!this.model.replaceMode()){
-			newMenu.addChild(new dijit.CheckedMenuItem({
-				label: messages["Sort by Name"],
-				checked: that.model.sortByName,
-				onChange : function(checked) {
-					that.sortWithName(checked);
-				}
-			}));
-		} else {
-			newMenu.addChild(new dijit.CheckedMenuItem({
-				label: messages["Compare changes"],
-				checked: true,
-				onChange : function(checked) {
-					that.toggleCompare(checked);
-				}
-			}));
-		}
-		var menuButton = new dijit.form.DropDownButton({
-			label : messages['Options'],
-			dropDown : newMenu
-		});
-		dojo.addClass(menuButton.domNode, "commandMenu"); //$NON-NLS-0$
-		dojo.place(menuButton.domNode, "pageNavigationActions", "last"); //$NON-NLS-1$ //$NON-NLS-0$
 	};
 	
 	SearchResultExplorer.prototype.reportStatus = function(message) {
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/searchUtils.js b/bundles/org.eclipse.orion.client.core/web/orion/searchUtils.js
index 1e9ee6c..baf4353 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/searchUtils.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/searchUtils.js
@@ -10,7 +10,7 @@
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 
-define(['i18n!orion/nls/messages', 'require', 'dojo', 'dijit', 'orion/editor/regex', 'orion/commands', 'orion/widgets/UserMenuDropDown'], function(messages, require, dojo, dijit, mRegex, mCommands) {
+define(['i18n!orion/nls/messages', 'require', 'dojo', 'orion/editor/regex', 'orion/commands'], function(messages, require, dojo, mRegex, mCommands) {
 
 var exports = exports || {};
 
@@ -749,82 +749,5 @@
 	}
 };
 
-exports.searchUtils._addSearchOptions = function(serviceRegistry, commandService, searcher) {
-	exports.searchUtils.getOpenSearchPref(serviceRegistry, function(openInNewTab){
-		var optionMenu = dijit.byId("searchOptionsDropDown"); //$NON-NLS-0$
-		if (optionMenu) {
-			optionMenu.destroy();
-		}
-		var newMenu = new dijit.Menu({
-			style: "display: none;padding:0px;border-radius:3px;", //$NON-NLS-0$
-			id : "searchOptionsMenu" //$NON-NLS-0$
-		});
-		dojo.addClass(newMenu.domNode, "commandMenu"); //$NON-NLS-0$
-		
-		newMenu.addChild(new dijit.CheckedMenuItem({
-			label: messages["Open in new tab"],
-			checked: openInNewTab,
-			onChange : function(checked) {
-				exports.searchUtils.setOpenSearchPref(serviceRegistry, checked);
-			}
-		}));
-		newMenu.addChild(new dijit.MenuSeparator());
-		
-		newMenu.addChild(new dijit.CheckedMenuItem({
-			label: messages["Regular expression"],
-			checked: false,
-			onChange : function(checked) {
-				searcher.useRegEx = checked;
-			}
-		}));
-		newMenu.addChild(new dijit.MenuSeparator());
-		
-		//Add the recent searches as popups
-		exports.searchUtils._addSearchPopUp(newMenu,  messages["Recent searches"], serviceRegistry, "recentSearch", function(theSearch){ //$NON-NLS-0$
-			return createSearchLink(searcher.createSearchQuery(theSearch.name, false, null, false, null, theSearch.regEx), theSearch.name);
-		});
-		//Add the saved searches as popups
-		exports.searchUtils._addSearchPopUp(newMenu,  messages["Saved searches"], serviceRegistry, "search", function(theSearch){ //$NON-NLS-0$
-			return createSearchLink(theSearch.query, theSearch.name);
-		});
-		
-		var menuButton = new orion.widgets.UserMenuDropDown({
-			label : messages["Search options"],
-			showLabel: false,
-			id : "searchOptionsDropDown", //$NON-NLS-0$
-			dropDown : newMenu
-		});
-		if(menuButton.valueNode) {  // accessibility, remove value node so screen reader does not stop there.
-			dojo.destroy(menuButton.valueNode);
-		}
-		if(menuButton.titleNode && dojo.attr(menuButton.titleNode, "title")) { //$NON-NLS-0$
-			dojo.removeAttr(menuButton.titleNode, "title"); //$NON-NLS-0$
-		}
-	
-		dojo.addClass(menuButton.domNode, "bannerMenu"); //$NON-NLS-0$
-		dojo.addClass(menuButton.domNode, "bannerMenuSearchOptions"); //$NON-NLS-0$
-		dojo.place(menuButton.domNode, "searchOptions", "last"); //$NON-NLS-1$ //$NON-NLS-0$
-	});
-};
-
-exports.searchUtils._addSearchPopUp = function(mainMenu, popUpLabel, serviceRegistry, type, makeLabelFunc){
-	var choicesMenu = new dijit.Menu({
-		style: "display: none;" //$NON-NLS-0$
-	});
-	var popup = new dijit.PopupMenuItem({
-		label: popUpLabel,
-		popup: choicesMenu
-	});
-	mainMenu.addChild(popup);
-	exports.searchUtils.populateSearchMenu(serviceRegistry, choicesMenu, type, function(theSearch){
-		return makeLabelFunc(theSearch);
-	});
-	dojo.connect(mainMenu, "_openPopup", popup, function(event) { //$NON-NLS-0$
-		exports.searchUtils.populateSearchMenu(serviceRegistry, choicesMenu, type, function(theSearch){
-			return makeLabelFunc(theSearch);
-		});
-	});
-};
-
 return exports.searchUtils;
 });
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/splitter.js b/bundles/org.eclipse.orion.client.core/web/orion/splitter.js
deleted file mode 100644
index 54bead9..0000000
--- a/bundles/org.eclipse.orion.client.core/web/orion/splitter.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/*******************************************************************************
- * @license
- * Copyright (c) 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-/*global window define document localStorage */
-
-define(['require', 'dojo'], function(require, dojo) {
-
-	function stop(event) {
-		if (window.document.all) { 
-			event.keyCode = 0;
-		} else { 
-			event.preventDefault();
-			event.stopPropagation();
-		}
-	}
-
-	/**
-	 * Constructs a new Splitter with the given options.  A splitter manages the layout
-	 * of two panels, a side panel and a main panel.  A toggle button will open or close the side panel.
-	 * @param {Object} options The options object which must specify the split dom node
-	 * @param options.node The node for the splitter presentation.  Required.
-	 * @param options.sidePanel The node for the side (toggling) panel.  Required.
-	 * @param options.mainPanel The node for the main panel.  Required.
-	 * @name orion.splitter.Splitter
-	 */
-	function Splitter(options) {
-		this._init(options);		
-	}
-	Splitter.prototype = /** @lends orion.splitter.Splitter.prototype */ {
-			
-		_init: function(options) {
-			this._tracking = null;
-			this._resizeListeners = [];
-			this._animationDelay = 501;  // longer than CSS transitions in layout.css
-			this._prefix = "/orion/splitter/" + document.body.id;  //$NON-NLS-0$
-			function nodeFromOption(value) {
-				var node = value;
-				if (typeof(value) === "string") { //$NON-NLS-0$
-					node = dojo.byId(value);
-				}	
-				return node;
-			}
-			this._node = nodeFromOption(options.node);
-			if (!this._node) { throw "no dom node for splitter found"; } //$NON-NLS-0$
-			this._sideNode = nodeFromOption(options.sidePanel);
-			if (!this._sideNode) { throw "no dom node for side panel found"; } //$NON-NLS-0$
-			this._mainNode = nodeFromOption(options.mainPanel);
-			if (!this._mainNode) { throw "no dom node for main panel found"; } //$NON-NLS-0$
-		
-			dojo.place("<div id='splitThumb' class='splitThumb splitThumbLayout'></div>", this._node, "only"); //$NON-NLS-0$ //$NON-NLS-1$
-			this._initializeFromStoredSettings();
-			this._thumb = dojo.query("#splitThumb", this._node)[0]; //$NON-NLS-0$
-			
-			if (this._closed) {
-				this._closed = false;  // _thumbDown will toggle it, so turn it off and then call _thumbDown.
-				this._thumbDown();
-			} else {
-				this._adjustToSplitPosition();
-			}
-			dojo.style(this._node, {visibility: "visible"}); //$NON-NLS-0$ 
-			dojo.style(this._mainNode, {display: "block"}); //$NON-NLS-0$ 
-			dojo.style(this._sideNode, {display: "block"}); //$NON-NLS-0$ 
-			dojo.connect(this._node, "onmousedown", this, this._mouseDown); //$NON-NLS-0$
-			dojo.connect(window, "onmouseup", this, this._mouseUp); //$NON-NLS-0$
-			dojo.connect(window, "onresize", this, this._resize);  //$NON-NLS-0$
-		},
-		/**
-		 * Toggle the open/closed state of the side panel.
-		 */			
-		toggleSidePanel: function() {
-			this._thumbDown();		
-		},
-		
-		/**
-		 * Close the side panel.  This function has no effect if the side panel is already closed.
-		 */
-		 openSidePanel: function() {
-			if (!this._closed) {
-				this._thumbDown();
-			}
-		 },
-		 /**
-		 * Adds an event listener for resizing the main and side panels.
-		 * @param {Function} listener The function called when a resize occurs.  The DOM node that has
-		 * been resized is passed as an argument.
-		 */
-		 addResizeListener: function(listener) {
-			this._resizeListeners.push(listener);
-		 },
-		 
-		 /* We use local storage vs. prefs because we don't presume the user wants the same window
-		    positioning across browsers and devices.
-		  */
-		 _initializeFromStoredSettings: function() {
-			this._closed = localStorage.getItem(this._prefix+"/toggleState") === "closed";  //$NON-NLS-1$ //$NON-NLS-0$
-			var pos = localStorage.getItem(this._prefix+"/xPosition"); //$NON-NLS-0$
-			if (pos) {
-				this._splitLeft = parseInt(pos, 10);
-			}
-			
-		 },
-		 
-		_adjustToSplitPosition: function(updateStorage) {
-			var pos = dojo.position(this._node);
-			this._splitWidth = pos.w;
-			if (updateStorage || !this._splitLeft){
-				this._splitLeft = pos.x;
-				localStorage.setItem(this._prefix+"/xPosition", this._splitLeft);  //$NON-NLS-1$ //$NON-NLS-0$
-			}
-			dojo.style(this._sideNode, {width: this._splitLeft + "px", right: this._splitLeft - 1 +"px", display: "block"}); //$NON-NLS-0$ //$NON-NLS-1$ //$NON-NLS-2$ 
-			dojo.style(this._node, {left: this._splitLeft + "px"}); //$NON-NLS-0$ 
-			this._resize();
-		},
-		
-		_resize: function(animationDelay) {
-			animationDelay = animationDelay || 0;
-			var pos = dojo.position(this._node.parentNode);
-			this._totalWidth = pos.w;
-			pos = dojo.position(this._node);
-			dojo.style(this._mainNode, {width: (this._totalWidth - pos.x - pos.w) +"px"}); //$NON-NLS-0$ 
-			window.setTimeout(dojo.hitch(this, function() { this._notifyResizeListeners(this._mainNode); }), animationDelay);
-			window.setTimeout(dojo.hitch(this, function() { this._notifyResizeListeners(this._sideNode); }), animationDelay);
-		},
-		
-		_notifyResizeListeners: function(node) {
-			for (var i = 0; i <this._resizeListeners.length; i++) {
-				this._resizeListeners[i](node);
-			}
-		}, 
-		
-		_thumbDown: function() {
-			if (this._closed) {
-				this._closed = false;
-				this._addAnimation();
-				dojo.style(this._sideNode, {width: this._splitLeft+"px"}); //$NON-NLS-0$ 
-				dojo.style(this._node, {left: this._splitLeft+"px"}); //$NON-NLS-0$
-				this._resize(this._animationDelay);
-				this._removeAnimation();
-			} else {
-				this._closed = true;
-				this._addAnimation();
-				dojo.style(this._sideNode, {width: 0}); 
-				dojo.style(this._node, {left: "1px"}); //$NON-NLS-0$ 
-				this._resize(this._animationDelay);
-				this._removeAnimation();
-			}
-			localStorage.setItem(this._prefix+"/toggleState", this._closed ? "closed" : null);  //$NON-NLS-1$  //$NON-NLS-0$
-
-		},
-		
-		_removeAnimation: function() {
-			// in a timeout to ensure the animations are complete.
-			window.setTimeout(dojo.hitch(this, function() {
-				dojo.removeClass(this._sideNode, "sidePanelLayoutAnimation"); //$NON-NLS-0$ 
-				dojo.removeClass(this._mainNode, "mainPanelLayoutAnimation"); //$NON-NLS-0$ 
-				dojo.removeClass(this._node, "splitLayoutAnimation"); //$NON-NLS-0$ 
-				dojo.removeClass(this._thumb, "splitLayoutAnimation"); //$NON-NLS-0$ 
-			}), this._animationDelay);
-		},
-		
-		_addAnimation: function() {
-			dojo.addClass(this._sideNode, "sidePanelLayoutAnimation"); //$NON-NLS-0$ 
-			dojo.addClass(this._mainNode, "mainPanelLayoutAnimation"); //$NON-NLS-0$ 
-			dojo.addClass(this._node, "splitLayoutAnimation"); //$NON-NLS-0$ 
-			dojo.addClass(this._thumb, "splitLayoutAnimation"); //$NON-NLS-0$ 
-		},
-		
-		_mouseDown: function(event) {
-			if (event.target === this._thumb) {
-				return this._thumbDown(event);
-			}
-			if (this._tracking) {
-				return;
-			}
-			dojo.addClass(this._node, "splitTracking"); //$NON-NLS-0$
-			dojo.addClass(this._mainNode, "panelTracking"); //$NON-NLS-0$
-			dojo.addClass(this._sideNode, "panelTracking"); //$NON-NLS-0$
-			this._tracking = dojo.connect(window, "onmousemove", this, this._mouseMove); //$NON-NLS-0$
-		},
-		
-		_mouseMove: function(event) {
-			if (this._tracking) {
-				this._splitLeft = event.clientX;
-				dojo.style(this._node, {left: event.clientX + "px"}); //$NON-NLS-0$ 
-				this._adjustToSplitPosition(true);
-				stop(event);
-			}
-		},
-		
-		_mouseUp: function(event) {
-			if (this._tracking) {
-				dojo.disconnect(this._tracking);
-				this._tracking = null;
-				dojo.removeClass(this._node, "splitTracking"); //$NON-NLS-0$
-				dojo.removeClass(this._mainNode, "panelTracking"); //$NON-NLS-0$
-				dojo.removeClass(this._sideNode, "panelTracking"); //$NON-NLS-0$
-			}
-		}
-	};
-	Splitter.prototype.constructor = Splitter;
-	//return the module exports
-	return {Splitter: Splitter};
-});
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/webui/dropdown.js b/bundles/org.eclipse.orion.client.core/web/orion/webui/dropdown.js
new file mode 100644
index 0000000..32cf2ad
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.core/web/orion/webui/dropdown.js
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made 
+ * available under the terms of the Eclipse Public License v1.0 
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
+ * 
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+/*global window define document localStorage */
+
+define(['require', 'orion/webui/littlelib'], function(require, lib) {
+
+	/**
+	 * Attaches dropdown behavior to a given node.  Assumes the triggering node and dropdown node
+	 * have the same parent.  Trigger should have "dropdownTrigger" class, and the dropdown node should 
+	 * have "dropdownMenu" class.
+	 * @param {Object} options The options object, which must minimally specify the dropdown dom node
+	 * @param options.dropdown The node for the dropdown presentation.  Required.
+	 * @param options.populate A function that should be called to populate the dropdown before it
+	 * opens each time.  Optional.
+	 * @name orion.webui.dropdown.Dropdown
+	 *
+	 */
+	function Dropdown(options) {
+		this._init(options);		
+	}
+	Dropdown.prototype = /** @lends orion.webui.dropdown.Dropdown.prototype */ {
+			
+		_init: function(options) {
+			this._dropdownNode = lib.node(options.dropdown);
+			if (!this._dropdownNode) { throw "no dom node for dropdown found"; } //$NON-NLS-0$
+			this._triggerNode = lib.$(".dropdownTrigger", this._dropdownNode.parentNode); //$NON-NLS-0$
+			if (!this._triggerNode) { throw "no dom node for dropdown trigger found"; } //$NON-NLS-0$
+			this._populate = options.populate;
+			var self = this;
+			
+			// click on trigger opens.
+			this._triggerNode.addEventListener("click", function(event) { //$NON-NLS-0$
+				self.toggle();
+				lib.stop(event);
+			}, false);
+			
+			// if trigger node is not key enabled...
+			if (this._triggerNode.tagName.toLowerCase() === "span") { //$NON-NLS-0$
+				this._triggerNode.addEventListener("keydown", function(event) { //$NON-NLS-0$
+					if (event.keyCode === lib.KEY.ENTER || event.charCode === lib.KEY.SPACE) {
+						self.toggle();
+						lib.stop(event);
+					}
+				}, false);
+			}
+			
+			// auto dismissal.  Click anywhere else means close.
+			document.addEventListener("click", function(event) { //$NON-NLS-0$
+				if (event.target !== self._triggerNode && !lib.contains(self._dropdownNode, event.target)) {
+					self.close(); 
+				}
+				// don't stop event
+			}, true); //$NON-NLS-0$
+			
+			// keys
+			this._dropdownNode.addEventListener("keydown", this._dropdownKeyDown.bind(this), false); //$NON-NLS-0$
+			
+		},
+		
+		/**
+		 * Toggle the open/closed state of the dropdown.
+		 */			
+		toggle: function(event) {
+			if (this._triggerNode.classList.contains("dropdownTriggerOpen")) { //$NON-NLS-0$
+				this.close();
+			} else {
+				this.open();
+			}
+		},
+		
+		/**
+		 * Open the dropdown.
+		 */			
+		open: function() {
+			if (this._populate) {
+				this.empty();
+				this._populate(this._dropdownNode);
+			}
+			var items = this.getItems();
+			if (items.length > 0) {
+				this._triggerNode.classList.add("dropdownTriggerOpen"); //$NON-NLS-0$
+				this._dropdownNode.classList.add("dropdownMenuOpen"); //$NON-NLS-0$
+				items[0].focus();
+			}
+		},
+		
+		/**
+		 * Close the dropdown.
+		 */			
+		close: function(restoreFocus) {
+			this._triggerNode.classList.remove("dropdownTriggerOpen"); //$NON-NLS-0$
+			this._dropdownNode.classList.remove("dropdownMenuOpen"); //$NON-NLS-0$
+			if (restoreFocus) {
+				this._triggerNode.focus();
+			}
+		},
+		
+		/**
+		 *
+		 */
+		getItems: function() {
+			var items = lib.$$array("li:not(.dropdownSeparator) > .dropdownMenuItem", this._dropdownNode, true); //$NON-NLS-0$
+			// We only want the direct li children, not any descendants.  But we can't preface a query with ">"
+			// So we do some reachy filtering here.
+			var filtered = [];
+			for (var i=0; i<items.length; i++) {
+				if (items[i].parentNode.parentNode === this._dropdownNode) {
+					filtered.push(items[i]);
+				}
+			}
+			return filtered;
+		},
+		
+		/**
+		 *
+		 */
+		empty: function() {
+			var items = lib.$$array("li", this._dropdownNode); //$NON-NLS-0$
+			// We only want the direct li children, not any descendants. 
+			for (var i=0; i<items.length; i++) {
+				if (items[i].parentNode === this._dropdownNode) {
+					items[i].parentNode.removeChild(items[i]);
+				}
+			}
+		},
+		
+		 
+		/**
+		 * A key is down in the dropdown node
+		 */
+		 _dropdownKeyDown: function(event) {
+			if (event.keyCode === lib.KEY.UP || event.keyCode === lib.KEY.DOWN || event.keyCode === lib.KEY.RIGHT || event.keyCode === lib.KEY.ENTER || event.keyCode === lib.KEY.LEFT) {
+				var items = this.getItems();	
+				var focusItem = document.activeElement;
+				if (items.length && items.length > 0 && focusItem) {
+					var index = items.indexOf(focusItem);
+					if (index >= 0) {
+						if (event.keyCode === lib.KEY.UP && index > 0) {
+							index--;
+							items[index].focus();
+						} else if (event.keyCode === lib.KEY.DOWN && index < items.length - 1) {
+							index++;
+							items[index].focus();
+						} else if (event.keyCode === lib.KEY.ENTER || event.keyCode === lib.KEY.RIGHT) {
+							if (focusItem.classList.contains("dropdownTrigger") && focusItem.dropdown) { //$NON-NLS-0$
+								focusItem.dropdown.open();
+								lib.stop(event);
+							}
+						} else if (event.keyCode === lib.KEY.LEFT && focusItem.parentNode.parentNode.classList.contains("dropdownMenuOpen")) { //$NON-NLS-0$
+							this.close(true);
+						}
+					}
+				}
+				lib.stop(event);
+			} else if (event.keyCode === lib.KEY.ESCAPE) {
+				this.close(true);
+				lib.stop(event);
+			}
+		 }
+	};
+	Dropdown.prototype.constructor = Dropdown;
+	//return the module exports
+	return {Dropdown: Dropdown};
+});
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/webui/littlelib.js b/bundles/org.eclipse.orion.client.core/web/orion/webui/littlelib.js
new file mode 100644
index 0000000..eaf66fa
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.core/web/orion/webui/littlelib.js
@@ -0,0 +1,75 @@
+/*******************************************************************************

+ * @license

+ * Copyright (c) 2012 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials are made 

+ * available under the terms of the Eclipse Public License v1.0 

+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 

+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 

+ * 

+ * Contributors: IBM Corporation - initial API and implementation

+ ******************************************************************************/

+/*global window document */

+

+define(['require'], function(require) {

+

+	function $(selector, node) {

+		if (!node) {

+			node = document;

+		}

+		return node.querySelector(selector);

+	}

+	

+	function $$(selector, node) {

+		if (!node) {

+			node = document;

+		}

+		return node.querySelectorAll(selector);

+	}

+	

+	function $$array(selector, node) {

+		return Array.prototype.slice.call($$(selector,node));

+	}

+		

+	function node(either) {

+		var theNode = either;

+		if (typeof(either) === "string") { //$NON-NLS-0$

+			theNode = document.getElementById(either);

+		}	

+		return theNode;

+	}

+	

+	function contains(parent, child) {

+		return parent === child || Boolean(parent.compareDocumentPosition(child) & 16);

+	}

+	

+	// TODO check IE10 to see if necessary

+	function stop(event) {

+		if (window.document.all) { 

+			event.keyCode = 0;

+		} else { 

+			event.preventDefault();

+			event.stopPropagation();

+		}

+	}

+	

+	var KEY = {

+		ENTER: 13,

+		ESCAPE: 27,

+		SPACE: 32,

+		LEFT: 37,

+		UP: 38,

+		RIGHT: 39,

+		DOWN: 40

+	};

+		

+	//return module exports

+	return {

+		$: $,

+		$$: $$,

+		$$array: $$array,

+		node: node,

+		contains: contains,

+		stop: stop,

+		KEY: KEY

+	};

+});
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/webui/splitter.js b/bundles/org.eclipse.orion.client.core/web/orion/webui/splitter.js
new file mode 100644
index 0000000..887b955
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.core/web/orion/webui/splitter.js
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made 
+ * available under the terms of the Eclipse Public License v1.0 
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
+ * 
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+/*global window define document localStorage */
+
+define(['require', 'orion/webui/littlelib'], function(require, lib) {
+
+	/**
+	 * Constructs a new Splitter with the given options.  A splitter manages the layout
+	 * of two panels, a side panel and a main panel.  A toggle button will open or close the side panel.
+	 * @param {Object} options The options object which must specify the split dom node
+	 * @param options.node The node for the splitter presentation.  Required.
+	 * @param options.sidePanel The node for the side (toggling) panel.  Required.
+	 * @param options.mainPanel The node for the main panel.  Required.
+	 * @name orion.splitter.Splitter
+	 */
+	function Splitter(options) {
+		this._init(options);		
+	}
+	Splitter.prototype = /** @lends orion.splitter.Splitter.prototype */ {
+			
+		_init: function(options) {
+			this._tracking = null;
+			this._resizeListeners = [];
+			this._animationDelay = 501;  // longer than CSS transitions in layout.css
+			this._prefix = "/orion/splitter/" + document.body.id;  //$NON-NLS-0$
+			this._node = lib.node(options.node);
+			if (!this._node) { throw "no dom node for splitter found"; } //$NON-NLS-0$
+			this._sideNode = lib.node(options.sidePanel);
+			if (!this._sideNode) { throw "no dom node for side panel found"; } //$NON-NLS-0$
+			this._mainNode = lib.node(options.mainPanel);
+			if (!this._mainNode) { throw "no dom node for main panel found"; } //$NON-NLS-0$
+			this._thumb = document.createElement("div"); //$NON-NLS-0$
+			this._node.appendChild(this._thumb);
+			this._thumb.classList.add("splitThumb"); //$NON-NLS-0$
+			this._thumb.classList.add("splitThumbLayout"); //$NON-NLS-0$
+			this._initializeFromStoredSettings();
+			
+			if (this._closed) {
+				this._closed = false;  // _thumbDown will toggle it, so turn it off and then call _thumbDown.
+				this._thumbDown();
+			} else {
+				this._adjustToSplitPosition();
+			}
+			this._node.style.visibility = "visible"; //$NON-NLS-0$ 
+			this._mainNode.style.display = "block"; //$NON-NLS-0$ 
+			this._sideNode.style.display = "block"; //$NON-NLS-0$ 
+			this._node.addEventListener("mousedown", this._mouseDown.bind(this), false); //$NON-NLS-0$
+			window.addEventListener("mouseup", this._mouseUp.bind(this), false); //$NON-NLS-0$
+			window.addEventListener("resize", this._resize.bind(this), false);  //$NON-NLS-0$
+		},
+		/**
+		 * Toggle the open/closed state of the side panel.
+		 */			
+		toggleSidePanel: function() {
+			this._thumbDown();		
+		},
+		
+		/**
+		 * Close the side panel.  This function has no effect if the side panel is already closed.
+		 */
+		 openSidePanel: function() {
+			if (!this._closed) {
+				this._thumbDown();
+			}
+		 },
+		 /**
+		 * Adds an event listener for resizing the main and side panels.
+		 * @param {Function} listener The function called when a resize occurs.  The DOM node that has
+		 * been resized is passed as an argument.
+		 */
+		 addResizeListener: function(listener) {
+			this._resizeListeners.push(listener);
+		 },
+		 
+		 /* We use local storage vs. prefs because we don't presume the user wants the same window
+		    positioning across browsers and devices.
+		  */
+		 _initializeFromStoredSettings: function() {
+			this._closed = localStorage.getItem(this._prefix+"/toggleState") === "closed";  //$NON-NLS-1$ //$NON-NLS-0$
+			var pos = localStorage.getItem(this._prefix+"/xPosition"); //$NON-NLS-0$
+			if (pos) {
+				this._splitLeft = parseInt(pos, 10);
+			}
+			
+		 },
+		 
+		_adjustToSplitPosition: function(updateStorage) {
+			var rect = this._node.getBoundingClientRect();
+			this._splitWidth = rect.right - rect.left;
+			if (updateStorage || !this._splitLeft){
+				this._splitLeft = rect.left;
+				localStorage.setItem(this._prefix+"/xPosition", this._splitLeft);  //$NON-NLS-1$ //$NON-NLS-0$
+			}
+			this._sideNode.style.width = this._splitLeft + "px"; //$NON-NLS-0$
+			this._sideNode.style.right = this._splitLeft - 1 +"px"; //$NON-NLS-0$
+			this._sideNode.style.display = "block"; //$NON-NLS-0$ 
+			this._node.style.left = this._splitLeft + "px"; //$NON-NLS-0$ 
+			this._resize();
+		},
+		
+		_resize: function(animationDelay) {
+			animationDelay = animationDelay || 0;
+			var rect = this._node.parentNode.getBoundingClientRect();
+			this._totalWidth = rect.right - rect.left;
+			rect = this._node.getBoundingClientRect();
+			this._mainNode.style.width = (this._totalWidth - rect.right) +"px"; //$NON-NLS-0$ 
+			var self = this;
+			window.setTimeout(function() { self._notifyResizeListeners(self._mainNode); }, animationDelay);
+			window.setTimeout(function() { self._notifyResizeListeners(self._sideNode); }, animationDelay);
+		},
+		
+		_notifyResizeListeners: function(node) {
+			for (var i = 0; i <this._resizeListeners.length; i++) {
+				this._resizeListeners[i](node);
+			}
+		}, 
+		
+		_thumbDown: function() {
+			if (this._closed) {
+				this._closed = false;
+				this._addAnimation();
+				this._sideNode.style.width = this._splitLeft+"px"; //$NON-NLS-0$ 
+				this._node.style.left = this._splitLeft+"px"; //$NON-NLS-0$
+				this._resize(this._animationDelay);
+				this._removeAnimation();
+			} else {
+				this._closed = true;
+				this._addAnimation();
+				this._sideNode.style.width = 0;
+				this._node.style.left = "1px"; //$NON-NLS-0$ 
+				this._resize(this._animationDelay);
+				this._removeAnimation();
+			}
+			localStorage.setItem(this._prefix+"/toggleState", this._closed ? "closed" : null);  //$NON-NLS-1$  //$NON-NLS-0$
+
+		},
+		
+		_removeAnimation: function() {
+			// in a timeout to ensure the animations are complete.
+			var self = this;
+			window.setTimeout(function() {
+				self._sideNode.classList.remove("sidePanelLayoutAnimation"); //$NON-NLS-0$ 
+				self._mainNode.classList.remove("mainPanelLayoutAnimation"); //$NON-NLS-0$ 
+				self._node.classList.remove("splitLayoutAnimation"); //$NON-NLS-0$ 
+				self._thumb.classList.remove("splitLayoutAnimation"); //$NON-NLS-0$ 
+			}, this._animationDelay);
+		},
+		
+		_addAnimation: function() {
+			this._sideNode.classList.add("sidePanelLayoutAnimation"); //$NON-NLS-0$ 
+			this._mainNode.classList.add("mainPanelLayoutAnimation"); //$NON-NLS-0$ 
+			this._node.classList.add("splitLayoutAnimation"); //$NON-NLS-0$ 
+			this._thumb.classList.add("splitLayoutAnimation"); //$NON-NLS-0$ 
+		},
+		
+		_mouseDown: function(event) {
+			if (event.target === this._thumb) {
+				return this._thumbDown(event);
+			}
+			if (this._tracking) {
+				return;
+			}
+			this._node.classList.add("splitTracking"); //$NON-NLS-0$
+			this._mainNode.classList.add("panelTracking"); //$NON-NLS-0$
+			this._sideNode.classList.add("panelTracking"); //$NON-NLS-0$
+			this._tracking = this._mouseMove.bind(this);
+			window.addEventListener("mousemove", this._tracking); //$NON-NLS-0$
+		},
+		
+		_mouseMove: function(event) {
+			if (this._tracking) {
+				this._splitLeft = event.clientX;
+				this._node.style.left = event.clientX + "px"; //$NON-NLS-0$ 
+				this._adjustToSplitPosition(true);
+				lib.stop(event);
+			}
+		},
+		
+		_mouseUp: function(event) {
+			if (this._tracking) {
+				window.removeEventListener("mousemove", this._tracking); //$NON-NLS-0$
+				this._tracking = null;
+				this._node.classList.remove("splitTracking"); //$NON-NLS-0$
+				this._mainNode.classList.remove("panelTracking"); //$NON-NLS-0$
+				this._sideNode.classList.remove("panelTracking"); //$NON-NLS-0$
+			}
+		}
+	};
+	Splitter.prototype.constructor = Splitter;
+	//return the module exports
+	return {Splitter: Splitter};
+});
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/widgets/UserMenu.js b/bundles/org.eclipse.orion.client.core/web/orion/widgets/UserMenu.js
index d6fbfb6..e1b4188 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/widgets/UserMenu.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/widgets/UserMenu.js
@@ -9,30 +9,19 @@
  * Contributors: IBM Corporation - initial API and implementation

  ******************************************************************************/

 

-/*global define window eclipse localStorage*/

+/*global define window document localStorage*/

 

-define(['i18n!orion/widgets/nls/messages', 'require', 'dojo', 'dijit', 'orion/commands', 'dijit/Menu'], function(messages, require, dojo, dijit, mCommands) {

-	dojo.declare("orion.widgets.UserMenu", [dijit.Menu], {

+define(['i18n!orion/widgets/nls/messages', 'require', 'orion/webui/littlelib'], function(messages, require, lib) {

 	

-		widgetsInTemplate: false,

-		id: "userMenu", //$NON-NLS-0$

-		

-		templateString: '<table role="menu" tabIndex="${tabIndex}" dojoAttachEvent="onkeypress:_onKeyPress" cellspacing="0">' + //$NON-NLS-0$

-						'<tbody class="dijitReset" dojoAttachPoint="containerNode"></tbody>' + //$NON-NLS-0$

-						'</table>', //$NON-NLS-0$

-		

-		postCreate : function() {

-			this.inherited(arguments);

-

-			this.label = messages['test'];

+	function UserMenu(options) {

+		this._init(options);		

+	}

+	UserMenu.prototype = /** @lends orion.widgets.UserMenu.UserMenu.prototype */ {

 			

-			dojo.style( this.domNode, 'border-radius', '3px' ); //$NON-NLS-1$ //$NON-NLS-0$

-			dojo.style( this.domNode, 'border', '1px solid #DDD' ); //$NON-NLS-1$ //$NON-NLS-0$

-		},

-		

-		constructor : function() {

-			this.inherited(arguments);

-			this.options = arguments[0] || {};

+		_init: function(options) {

+			this._dropdownNode = lib.node(options.dropdownNode);

+			if (!this._dropdownNode) { throw "no dom node for dropdown found"; } //$NON-NLS-0$

+			this._dropdown = options.dropdown;

 			this.authenticatedServices = {};

 			this.unauthenticatedServices = {};

 		},

@@ -46,173 +35,106 @@
 		length: function(obj) {

 			var length = 0;

 			for(var prop in obj) {

-				if(obj.hasOwnProperty(prop))

+				if(obj.hasOwnProperty(prop)) {

 					length++;

+				}

 			}

 			return length;

 		},

 		

-		_renderAuthenticatedService: function(key, startIndex, who){

+		_makeMenuItem: function(name, click) {

+			var element = document.createElement("span"); //$NON-NLS-0$

+			element.role = "menuitem";  //$NON-NLS-0$

+			element.tabIndex = 0; //$NON-NLS-0$

+			var text = document.createTextNode(name);

+			element.appendChild(text);

+			element.classList.add("dropdownMenuItem"); //$NON-NLS-0$

+			element.addEventListener("click", click, false); //$NON-NLS-0$

+			// onClick events do not register for spans when using the keyboard

+			element.addEventListener("keydown", this, function(e) { //$NON-NLS-0$

+				if (e.keyCode === lib.key.ENTER || e.charCode === lib.key.SPACE) {	

+					click();

+				}

+			}, false);

+			return element;

+		},

+		

+		_renderAuthenticatedService: function(key, startIndex){

 			var _self = this;

 			var authService = this.authenticatedServices[key].authService;

-			if(authService && authService.logout){

-					this.addChild(new mCommands.CommandMenuItem({

-						label: who ? messages["Sign Out "] + who : messages["Sign Out"],

-						onClick: dojo.hitch(this, function(authService, key){

-							return function(){

-								authService.logout().then(dojo.hitch(_self, function(){

-									this.addUserItem(key, authService, this.authenticatedServices[key].label);

-									localStorage.removeItem(key);

-									localStorage.removeItem("lastLogin");

-									//TODO: Bug 368481 - Re-examine localStorage caching and lifecycle

-									for (var i = localStorage.length - 1; i >= 0; i--) {
-										var name = localStorage.key(i);
-										if (name && name.indexOf("/orion/preferences/user") === 0) {
-											localStorage.removeItem(name);
-										}
-									}

-									authService.getAuthForm(window.location.href).then(function(formURL) {

-										window.location = formURL;

-									});

-								}));

-							};

-						})(authService, key)

-					}));

-			}

-		},

-		

-		_renderUnauthenticatedService: function(key, startIndex, where){

-			var _self = this;

-			var authService = this.unauthenticatedServices[key].authService;

-			

-			if(!authService){

-				var loginForm = this.unauthenticatedServices[key].SignInLocation;

-				if(loginForm.indexOf("?")===-1){ //$NON-NLS-0$

-					loginForm+= "?redirect=" + eclipse.globalCommandUtils.notifyAuthenticationSite + "?key=" + key; //$NON-NLS-1$ //$NON-NLS-0$

-				}else{

-					loginForm+= "&redirect=" + eclipse.globalCommandUtils.notifyAuthenticationSite + "?key=" + key; //$NON-NLS-1$ //$NON-NLS-0$

-				}

-				var link = document.createElement("a"); //$NON-NLS-0$

-				link.target = "_blank"; //$NON-NLS-0$

-				link.href = loginForm;

-				if (where) {

-					link.textContent = messages["Sign In To "] + where;

-				} else {

-					link.textContent = messages["Sign In"];

-				}

-				this.addChild(new mCommands.Command.MenuItem({

-					label: link,

-					hasLink: true

-				}), startIndex);

-				

-			}else if(authService.getAuthForm){

-				dojo.hitch(_self, function(key){

-					authService.getAuthForm(eclipse.globalCommandUtils.notifyAuthenticationSite).then(function(loginForm){

-						if(loginForm.indexOf("?")===-1){ //$NON-NLS-0$

-							loginForm+= "?redirect=" + eclipse.globalCommandUtils.notifyAuthenticationSite + "?key=" + key; //$NON-NLS-1$ //$NON-NLS-0$

-						}else{

-							loginForm+= "&redirect=" + eclipse.globalCommandUtils.notifyAuthenticationSite + "?key=" + key; //$NON-NLS-1$ //$NON-NLS-0$

+			if (authService && authService.logout){

+				var item = document.createElement("li");//$NON-NLS-0$

+				var element = this._makeMenuItem(messages["Sign Out"], function() {

+					authService.logout().then(function(){

+						_self.addUserItem(key, authService, _self.authenticatedServices[key].label);

+						localStorage.removeItem(key);

+						localStorage.removeItem("lastLogin"); //$NON-NLS-0$

+						//TODO: Bug 368481 - Re-examine localStorage caching and lifecycle

+						for (var i = localStorage.length - 1; i >= 0; i--) {

+							var name = localStorage.key(i);

+							if (name && name.indexOf("/orion/preferences/user") === 0) { //$NON-NLS-0$

+								localStorage.removeItem(name);

+							}

 						}

-						_self.addChild(new mCommands.CommandMenuItem({

-							label: where ? "<a target='_blank' href="+loginForm+">"+messages['Sign In To ']+where+"</a>" : "<a target='_blank' href="+loginForm+">"+messages["Sign In"]+"</a>", //$NON-NLS-7$ //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-1$ //$NON-NLS-0$

-							hasLink: true

-						}), startIndex);

+						authService.getAuthForm(window.location.href).then(function(formURL) {

+							window.location = formURL;

+						});

 					});

-				})(key);

-			}else if(authService.login){

-				this.addChild(new mCommands.CommandMenuItem({

-					label: where ? "Sign In To " + where : "Sign In", //$NON-NLS-1$ //$NON-NLS-0$

-					onClick:  dojo.hitch(_self, function(authService){

-						return function(){authService.login(eclipse.globalCommandUtils.notifyAuthenticationSite);};

-					})(authService)

-				}), startIndex);

-				

+				});

+				item.appendChild(element);

+				this._dropdownNode.appendChild(item);

 			}

 		},

 		

+

 		renderServices: function(){

-			var children = this.getChildren();

-			for(var i=0; i<children.length; i++){

-				this.removeChild(children[i]);

-			}

+			this._dropdown.empty();

+						 

+			var item = document.createElement("li");//$NON-NLS-0$

+			var link = document.createElement("a"); //$NON-NLS-0$

+			link.role = "menuitem"; //$NON-NLS-0$

+			link.classList.add("dropdownMenuItem"); //$NON-NLS-0$

+			link.href = require.toUrl("help/index.jsp"); //$NON-NLS-0$

+			var text = document.createTextNode(messages["Help"]);//$NON-NLS-0$

+			link.appendChild(text);

+			item.appendChild(link);

+			this._dropdownNode.appendChild(item);

 			

-//			 this.addChild(new dijit.MenuItem({

-//				 label: "<a href="+require.toUrl("operations/list.html") + ">Background Operations</a>",

-//				 onKeyDown: function(evt){

-//					if(evt.keyCode === 13 || evt.keyCode === 32) {

-//						if(evt.ctrlKey) {

-//							window.open(require.toUrl("operations/list.html"));

-//						} else {

-//							window.location=require.toUrl("operations/list.html");

-//						}

-//					}

-//				 },

-//				 _onClick: function(evt) { this.getParent().onItemClick(this, evt); }

-//			 }));

-			 

-			var helpLink = document.createElement("a"); //$NON-NLS-0$

-			helpLink.href = require.toUrl("help/index.jsp"); //$NON-NLS-0$

-			helpLink.textContent = messages["Help"];

-			this.addChild(new mCommands.CommandMenuItem({

-				 label: helpLink,

-				 hasLink: true

-			 }));

+			var element;

 			if(this.keyAssistFunction){

-				this.addChild(new mCommands.CommandMenuItem({

-					 label: messages["Keyboard Shortcuts"],

-					 onClick: this.keyAssistFunction

-				 }));	

+				item = document.createElement("li");//$NON-NLS-0$

+				element = this._makeMenuItem(messages["Keyboard Shortcuts"], this.keyAssistFunction);

+				item.appendChild(element);

+				this._dropdownNode.appendChild(item);

 			}

 			

-			this.addChild(new dijit.MenuSeparator());

-			

-			var settingsLink = document.createElement("a"); //$NON-NLS-0$

-			settingsLink.href = require.toUrl("settings/settings.html"); //$NON-NLS-0$

-			settingsLink.textContent = messages["Settings"];

-			

-			 this.addChild(new mCommands.CommandMenuItem({

-				 label: settingsLink,

-				 hasLink: true

-			 }));

-			 

-			 if(this.isSingleService()){

+			// separator

+			item = document.createElement("li"); //$NON-NLS-0$

+			item.classList.add("dropdownSeparator"); //$NON-NLS-0$

+			element = document.createElement("span"); //$NON-NLS-0$

+			element.classList.add("dropdownSeparator"); //$NON-NLS-0$

+			item.appendChild(element);

+			this._dropdownNode.appendChild(item);

+	

+			item = document.createElement("li");//$NON-NLS-0$

+			link = document.createElement("a"); //$NON-NLS-0$

+			link.role = "menuitem";  //$NON-NLS-0$

+			link.classList.add("dropdownMenuItem");  //$NON-NLS-0$

+			link.href = require.toUrl("settings/settings.html"); //$NON-NLS-0$

+			text = document.createTextNode(messages["Settings"]);//$NON-NLS-0$

+			link.appendChild(text);

+			item.appendChild(link);

+			this._dropdownNode.appendChild(item);

+

+			if(this.isSingleService()){

 				//add sign out only for single service.

-				//When there are more services user may use Sign out on the tooltip that is always available 

 				for(var i in this.authenticatedServices){

-					this._renderAuthenticatedService(i, 0);

+					if (this.authenticatedServices.hasOwnProperty(i)) {

+						this._renderAuthenticatedService(i, 0);

+					}

 				}

 			}

 			

-//			this.addChild(new dijit.MenuItem({

-//				 label: "<a href='"+require.toUrl("help/about.html") + "'>About Orion</a>",

-//				 onKeyDown: function(evt){

-//					if(evt.keyCode === 13 || evt.keyCode === 32) {

-//						if(evt.ctrlKey) {

-//							window.open(require.toUrl("help/about.html"));

-//						} else {

-//							window.location=require.toUrl("help/about.html");

-//						}

-//					}

-//				 },

-//				 _onClick: function(evt) { this.getParent().onItemClick(this, evt); }

-//			 }));

-			

-		},

-		

-		getUserLabel: function(userData){

-			if(userData.data){

-				var userName = (userData.data.Name && userData.data.Name.replace(/^\s+|\s+$/g,"")!=="") ? userData.data.Name : userData.data.login; //$NON-NLS-0$

-				if(userName.length > 40)

-					userName = userName.substring(0, 30) + "..."; //$NON-NLS-0$

-				userName+=" ("+userData.label+")"; //$NON-NLS-1$ //$NON-NLS-0$

-				return userName;

-			} else {

-				return userData.label;

-			}

-		},

-		

-		setUserName: function( name ){

-		

 		},

 		

 		setKeyAssist: function(keyAssistFunction){

@@ -221,7 +143,6 @@
 		},

 	

 		addUserItem: function(key, authService, label, jsonData){

-			var _self = this;

 			if(jsonData){

 				if(this.unauthenticatedServices[key]){

 					delete this.unauthenticatedServices[key];

@@ -237,66 +158,11 @@
 					this.unauthenticatedServices[key] = {authService: authService, label: label};

 				}

 			}

-			dojo.hitch(this, this.renderServices)();

-			

-			if(!dojo.byId('userInfo')){ //$NON-NLS-0$

-				return;

-			}

-			

-			if(this.isSingleService() && jsonData){

-				var userName = (jsonData.Name && jsonData.Name.replace(/^\s+|\s+$/g,"")!=="") ? jsonData.Name : jsonData.login; //$NON-NLS-0$

-				var displayName = userName;

-				if(displayName.length > 40)

-					displayName = displayName.substring(0, 30) + "..."; //$NON-NLS-0$

-				var profileLink = dojo.create("a", { //$NON-NLS-0$

-									  href: require.toUrl("profile/user-profile.html") + "#" + jsonData.Location, //$NON-NLS-1$ //$NON-NLS-0$

-									  style: "margin-right: 0px" //$NON-NLS-0$

-								  }, dojo.byId('userInfo'), "only"); //$NON-NLS-1$ //$NON-NLS-0$

-				profileLink.textContent = displayName;

-				profileLink.setAttribute("aria-label", messages["View profile of "] + userName); //$NON-NLS-0$

-				new mCommands.CommandTooltip({

-					connectId: [profileLink],

-					label: messages['View profile of '] + userName,

-					position: ["above", "left", "right", "below"] // otherwise defaults to right and obscures adjacent commands //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$

-				});

-			}else if(this.isSingleService() && !jsonData){

-				if(authService.getAuthForm){

-					dojo.hitch(this, function(key){

-						authService.getAuthForm(eclipse.globalCommandUtils.notifyAuthenticationSite).then(function(loginForm){

-							if(loginForm.indexOf("?")===-1){ //$NON-NLS-0$

-								loginForm+= "?redirect=" + eclipse.globalCommandUtils.notifyAuthenticationSite + "?key=" + key; //$NON-NLS-1$ //$NON-NLS-0$

-							}else{

-								loginForm+= "&redirect=" + eclipse.globalCommandUtils.notifyAuthenticationSite + "?key=" + key; //$NON-NLS-1$ //$NON-NLS-0$

-							}

-							var link = dojo.create("a", { //$NON-NLS-0$

-								href: loginForm,

-								style: "margin-right: 0px", //$NON-NLS-0$

-								target: "_blank" //$NON-NLS-0$

-							}, dojo.byId('userInfo'), "only"); //$NON-NLS-1$ //$NON-NLS-0$

-							link.textContent = messages['Sign In'];

-						});

-					})(key);

-				}else if(authService.login){

-					var a = dojo.create("a", { //$NON-NLS-0$

-						style: "margin-right: 0px" //$NON-NLS-0$

-					}, dojo.byId('userInfo'), "only"); //$NON-NLS-1$ //$NON-NLS-0$

-					a.textContent = messages['Sign In'];

-					

-					dojo.connect(a, "onmouseover", a, function() { //$NON-NLS-0$

-						a.style.cursor = "pointer"; //$NON-NLS-0$

-					});

-					dojo.connect(a, "onmouseout", a, function() { //$NON-NLS-0$

-						a.style.cursor = "default"; //$NON-NLS-0$

-					});

-					

-					dojo.connect(a, "onclick", function(){ //$NON-NLS-0$

-							authService.login(eclipse.globalCommandUtils.notifyAuthenticationSite);

-						});

-					

-				}

-			} else {

-				dojo.empty(dojo.byId('userInfo')); //$NON-NLS-0$

-			}

+			this.renderServices();

 		}

-	});

+	};

+	UserMenu.prototype.constructor = UserMenu;

+	//return the module exports

+	return {UserMenu: UserMenu};

+

 });

diff --git a/bundles/org.eclipse.orion.client.core/web/orion/widgets/UserMenuDropDown.js b/bundles/org.eclipse.orion.client.core/web/orion/widgets/UserMenuDropDown.js
deleted file mode 100644
index 16a2d13..0000000
--- a/bundles/org.eclipse.orion.client.core/web/orion/widgets/UserMenuDropDown.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/*******************************************************************************

- * @license

- * Copyright (c) 2012 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials are made 

- * available under the terms of the Eclipse Public License v1.0 

- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 

- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 

- * 

- * Contributors: IBM Corporation - initial API and implementation

- ******************************************************************************/

-

-/*global define window eclipse localStorage*/

-

-define(['require', 'dojo', 'dijit', 'dijit/form/DropDownButton'], function(require, dojo, dijit) {

-	dojo.declare("orion.widgets.UserMenuDropDown", [dijit.form.DropDownButton], { //$NON-NLS-0$

-	

-		templateString: '<span class="dijit dijitReset dijitInline" style="padding-top: 3px;">' +  //$NON-NLS-0$

-							'<span class="primaryNav" dojoAttachEvent="ondijitclick:_onButtonClick" dojoAttachPoint="_buttonNode">' + //$NON-NLS-0$

-							'<span class="dijitReset dijitStretch dijitButtonContents" dojoAttachPoint="focusNode,titleNode,_arrowWrapperNode"  role="button" aria-haspopup="true" aria-labelledby="${id}_label">' +  //$NON-NLS-0$

-							'<span class="dijitReset dijitInline dijitIcon" dojoAttachPoint="iconNode"></span>' + //$NON-NLS-0$

-							'<span class="dijitReset dijitInline dijitButtonText" dojoAttachPoint="containerNode,_popupStateNode" id="${id}_label" style="padding-right:3px"></span>' +  //$NON-NLS-0$

-							'<span class="dijitReset dijitInline dijitArrowButtonInner"></span>' + //$NON-NLS-0$

-							'<span class="dijitReset dijitInline dijitArrowButtonChar">&#9660;</span></span></span>' +  //$NON-NLS-0$

-							'<input ${!nameAttrSetting} type="${type}" value="${value}" class="dijitOffScreen" dojoAttachPoint="valueNode"/></span>' //$NON-NLS-0$

-	

-	

-	

-	});

-});
\ No newline at end of file