Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2512)

Unified Diff: chrome/browser/resources/downloads/downloads.js

Issue 807593005: Make downloads list keyboard shortcuts more consistent. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nit Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/downloads/downloads.js
diff --git a/chrome/browser/resources/downloads/downloads.js b/chrome/browser/resources/downloads/downloads.js
index fd7ccc9e6dee71dd48d02317fc2fb38d95c60fa6..a925ae3ec2b9a96c3b757e5cb1426fec1eec0ae2 100644
--- a/chrome/browser/resources/downloads/downloads.js
+++ b/chrome/browser/resources/downloads/downloads.js
@@ -77,6 +77,122 @@ function createButton(onclick, value) {
}
///////////////////////////////////////////////////////////////////////////////
+// DownloadFocusRow:
+
+/**
+ * Provides an implementation for a single column grid.
+ * @constructor
+ * @param {Download} download The Download representing this row.
+ * @param {Node} boundary Focus events are ignored outside of this node.
+ * @extends {cr.ui.FocusRow}
+ */
+DownloadFocusRow = function(download, boundary) {
+ var self = download.node;
+ self.__proto__ = DownloadFocusRow.prototype;
+ self.download_ = download;
+ self.decorate(boundary);
+ return self;
Dan Beam 2015/01/24 02:37:07 what's the point to this pattern of returning some
hcarmona 2015/01/27 18:30:39 I had seen this in the code when a constructor wou
+};
+
+DownloadFocusRow.prototype = {
+ __proto__: cr.ui.FocusRow.prototype,
+
+ /** @override */
+ decorate: function(boundary, opt_delegate) {
+ cr.ui.FocusRow.prototype.decorate.apply(this, arguments);
+
+ // Add all clickable elements as a row into the grid.
+ this.addFocusRow_(this.download_.nodeFileLink_, 'name');
Dan Beam 2015/01/24 02:37:08 i understand @private is file-level in closure, bu
hcarmona 2015/01/27 18:30:39 Done.
+ this.addFocusRow_(this.download_.nodeURL_, 'url');
+ this.addFocusRow_(this.download_.controlShow_, 'show');
+ this.addFocusRow_(this.download_.controlRetry_, 'retry');
+ this.addFocusRow_(this.download_.controlPause_, 'pause');
+ this.addFocusRow_(this.download_.controlResume_, 'resume');
+ this.addFocusRow_(this.download_.controlRemove_, 'remove');
+ this.addFocusRow_(this.download_.controlCancel_, 'cancel');
+
+ // Only one set of these two buttons will be added to a download row at a
+ // time. They have the same type so that focus is handled well in case
+ // there is a dangerous download right next to a malicious download.
+ this.addFocusRow_(this.download_.malwareSave_, 'save');
+ this.addFocusRow_(this.download_.malwareDiscard_, 'discard');
+ this.addFocusRow_(this.download_.dangerSave_, 'save');
+ this.addFocusRow_(this.download_.dangerDiscard_, 'discard');
+
+ this.addFocusRow_(this.download_.controlByExtensionLink_, 'extension');
+ },
+
+ /** @override */
+ getEquivalentElement: function(element) {
+ if (this.contains(element))
+ return element;
+
+ // All elements default to another element with the same type.
+ var query = '[column-type="' + element.getAttribute('column-type') + '"]';
+ var ret = this.querySelector(query);
+
+ // The following element types are at the same UI level.
+ if (!ret) {
+ switch (element.getAttribute('column-type')) {
Dan Beam 2015/01/24 02:37:08 what is this entire switch trying to accomplish?
hcarmona 2015/01/27 18:30:39 Got rid of switch to make it more clear what's hap
+ case ('show'):
Dan Beam 2015/01/24 02:37:07 no parens case 'show':
hcarmona 2015/01/27 18:30:39 Done.
+ case ('retry'):
+ case ('pause'):
+ case ('resume'):
+ case ('remove'):
+ case ('cancel'):
+ ret = this.querySelector('[column-type="show"]') ||
+ this.querySelector('[column-type="retry"]') ||
+ this.querySelector('[column-type="pause"]') ||
+ this.querySelector('[column-type="resume"]') ||
+ this.querySelector('[column-type="remove"]') ||
+ this.querySelector('[column-type="cancel"]');
Dan Beam 2015/01/24 02:37:07 querySelector('[column-type=show], [column-type=re
hcarmona 2015/01/27 18:30:39 Done.
+ break;
+ }
+ }
+
+ // Any other miss should return the first focusable element.
+ return ret || this.focusableElements[0];
+ },
+
+ /**
+ * Add an element if it exists in this FocusRow and is focusable.
+ * @param {Element} element The element that should be added.
+ * @param {string} type The type to use for the element.
+ * @private
+ */
+ addFocusRow_: function(element, type) {
+ if (this.shouldFocus_(element)) {
+ this.addFocusableElement(element);
+ element.setAttribute('column-type', type);
+ }
+ },
+
+ /**
+ * Determines if element should be focusable.
+ * @param {!Element} element
+ * @return {boolean}
+ * @private
+ */
+ shouldFocus_: function(element) {
+ if (!element)
+ return false;
+
+ // Hidden elements are not focusable.
+ var style = window.getComputedStyle(element);
+ if (style.visibility == 'hidden' || style.display == 'none')
+ return false;
+
+ // Verify that all ancestors are focusable. This is necessary because of the
+ // case where a node has display set to something other than 'none', but it
+ // has an ancestor with display == 'none'.
+ if (element.parentElement)
+ return this.shouldFocus_(element.parentElement);
+
+ return true;
+ },
+};
+
+///////////////////////////////////////////////////////////////////////////////
// Downloads
/**
* Class to hold all the information about the visible downloads.
@@ -91,6 +207,7 @@ function Downloads() {
this.node_ = $('downloads-display');
this.summary_ = $('downloads-summary-text');
this.searchText_ = '';
+ this.focusGrid_ = new cr.ui.FocusGrid();
// Keep track of the dates of the newest and oldest downloads so that we
// know where to insert them.
@@ -176,6 +293,23 @@ Downloads.prototype.updateResults = function() {
if (loadTimeData.getBoolean('allow_deleting_history'))
$('clear-all').hidden = !hasDownloads || this.searchText_.length > 0;
+
+ this.rebuildFocusGrid_();
+};
+
+/**
+ * Rebuild the focusGrid_ using the elements that each download will have.
+ * @private
+ */
+Downloads.prototype.rebuildFocusGrid_ = function() {
+ this.focusGrid_.destroy();
+
+ // Keys for downloads are in the reverse order of what is displayed.
+ var keys = Object.keys(this.downloads_);
+ for (var i = keys.length - 1; i >= 0; --i) {
+ this.focusGrid_.addRow(new DownloadFocusRow(this.downloads_[keys[i]],
+ this.node_));
+ }
};
/**

Powered by Google App Engine
This is Rietveld 408576698