Bug 370669 - Mouse actions that affect the current row for key board navigation.
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/explorer-table.js b/bundles/org.eclipse.orion.client.core/web/orion/explorer-table.js
index 66e9010..a5261c8 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/explorer-table.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/explorer-table.js
@@ -76,6 +76,12 @@
 		return dojo.byId(tableRowId+"NameColumn");
 	};
 	
+	FileRenderer.prototype.onRowIterate = function(model){
+		if(this.explorer.navHandler){
+			this.explorer.navHandler.cursorOn(model);
+		}
+	};
+	
 	FileRenderer.prototype.getCellElement = function(col_no, item, tableRow){
 		function isImage(contentType) {
 			switch (contentType && contentType.id) {
@@ -162,6 +168,18 @@
 				var fileDate = new Date(item.LocalTimeStamp);
 				dateColumn.innerHTML = dojo.date.locale.format(fileDate);
 			}
+			var that = this;
+			if(this.onRowIterate){
+				dojo.connect(dateColumn, "onclick", dateColumn, function() {
+					that.onRowIterate(item);
+				});
+				dojo.connect(dateColumn, "onmouseover", dateColumn, function() {
+					dateColumn.style.cursor ="pointer";
+				});
+				dojo.connect(dateColumn, "onmouseout", dateColumn, function() {
+					dateColumn.style.cursor ="default";
+				});
+			}
 
 			return dateColumn;
 		case 2:
@@ -298,7 +316,8 @@
 						postLoad();
 					}
 					this.model = new Model(this.registry, this.treeRoot, this.fileClient);
-					this.createTree(this.parentId, this.model);
+					this.createTree(this.parentId, this.model, { onCollapse: function(model){if(self.navHandler){ 
+																							 self.navHandler.onCollapse(model);}}});
 					//Hook up iterator
 					if(!this.navHandler){
 						this.navHandler = new mNavHandler.ExplorerNavHandler(this);
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/explorerNavHandler.js b/bundles/org.eclipse.orion.client.core/web/orion/explorerNavHandler.js
index 487709f..9448b02 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/explorerNavHandler.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/explorerNavHandler.js
@@ -32,8 +32,6 @@
 		this.myTree = this.explorer.myTree;
 		
 	    this._listeners = [];
-	    var parentDiv = this.myTree._parent;
-	    parentDiv.focus();
 		
 		this._modelIterator = new mTreeModelIterator.TreeModelIterator([],
 		   		   {isExpanded: dojo.hitch(this, function(model) {
@@ -52,6 +50,8 @@
 		   		   });
 		this._init(options);
 		
+	    var parentDiv = this.myTree._parent;
+	    parentDiv.focus();
 		var keyListener = dojo.connect(parentDiv, "onkeydown", dojo.hitch(this, function (e) {
 			if(e.keyCode === dojo.keys.DOWN_ARROW){
 				return this.onUpArrow(e);
@@ -74,6 +74,14 @@
 			}
 		}));
 		this._listeners.push(keyListener);
+		var l1 = dojo.connect(parentDiv, "onblur", dojo.hitch(this, function (e) {
+			this.toggleCursor(null, false);
+		}));
+		var l2 = dojo.connect(parentDiv, "onfocus", dojo.hitch(this, function (e) {
+			this.toggleCursor(null, true);
+		}));
+		this._listeners.push(l1);
+		this._listeners.push(l2);
 	};
 	
 	ExplorerNavHandler.prototype = /** @lends orion.ExplorerNavHandler.ExplorerNavHandler.prototype */ {
@@ -114,7 +122,7 @@
 		},
 		
 		toggleCursor:  function(model, on){
-			var currentRow = this.getRowdDiv(model);
+			var currentRow = this.getRowDiv(model);
 			if(currentRow) {
 				dojo.toggleClass(currentRow, "treeIterationCursor", on);
 			}
@@ -140,7 +148,7 @@
 			this.toggleCursor(currentModel, true);
 		},
 		
-		getRowdDiv: function(model){
+		getRowDiv: function(model){
 			var rowModel = model ? model: this._modelIterator.cursor();
 			if(!rowModel){
 				return null;
@@ -157,13 +165,16 @@
 				if(selecting){
 					this._checkRow(this._modelIterator.prevCursor(), true);
 				}
-				//this.onHighlightSelection(next);
+				var currentRowDiv = this.getRowDiv();
+				if(currentRowDiv && !this._visible(currentRowDiv)) {
+					currentRowDiv.scrollIntoView(!forward);
+				}
 			}
 		},
 		
 		_checkRow: function(model, toggle) {
 			if(this.renderer._useCheckboxSelection){
-				var tableRow = this.getRowdDiv(model);
+				var tableRow = this.getRowDiv(model);
 				if(!tableRow){
 					return;
 				}
@@ -175,6 +186,33 @@
 			}
 		},
 		
+		_visible: function(rowDiv) {
+			if (rowDiv.offsetWidth === 0 || rowDiv.offsetHeight === 0) {
+				return false;
+			}
+		    var parentNode = this.myTree._parent;
+			var parentRect = parentNode.getClientRects()[0],
+			rects = rowDiv.getClientRects(),
+			on_top = function(r) {
+				var x = (r.left + r.right)/2, y = (r.top + r.bottom)/2;
+			    // document.elementFromPoint(x, y) === element; TODO: what is this ???
+			};
+			for (var i = 0, l = rects.length; i < l; i++) {
+				var r = rects[i];
+			    var in_viewport = (r.top >= parentRect.top && r.top <= parentRect.bottom && r.bottom >= parentRect.top && r.bottom <= parentRect.bottom);
+			    if (in_viewport ) {
+					return true;
+			    }
+			}
+			return false;
+		},
+			
+		onCollapse: function(model)	{
+			if(this._modelIterator.collapse(model)){
+				this.cursorOn();
+			}
+		},
+		
 		//Up arrow key iterates the current row backward. If control key is on, browser's scroll up behavior takes over.
 		//If shift key is on, it toggles the check box and iterates backward.
 		onUpArrow: function(e) {
@@ -232,6 +270,7 @@
 		//Space key toggles the check box on the current row if the renderer uses check box
 		onSpace: function(e) {
 			this._checkRow(null, true);
+			e.preventDefault();
 		},
 		
 		//Enter key simulates a href call if the current row has an href link rendered. The render has to provide the getRowActionElement function that returns the href DIV.
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/treeModelIterator.js b/bundles/org.eclipse.orion.client.core/web/orion/treeModelIterator.js
index 8546b77..b6df782 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/treeModelIterator.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/treeModelIterator.js
@@ -183,7 +183,7 @@
 		 */
 		collapse: function(collapsedModel) {
 			if(this._inParentChain(this._cursor, collapsedModel)){
-				this._cursor = collapsedModel;
+				this.setCursor(collapsedModel);
 				return this._cursor;
 			}
 			return null;