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

Unified Diff: remoting/webapp/me2mom/host_list.js

Issue 8587050: Implement rename and delete. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleaned up CSS. Created 9 years, 1 month 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: remoting/webapp/me2mom/host_list.js
diff --git a/remoting/webapp/me2mom/host_list.js b/remoting/webapp/me2mom/host_list.js
index d84d73edf7d8119dc0348e45707d700abea0e109..715471a5dabfe889317a6166cfe9d9c9fc2d89b3 100644
--- a/remoting/webapp/me2mom/host_list.js
+++ b/remoting/webapp/me2mom/host_list.js
@@ -13,6 +13,9 @@
var remoting = remoting || {};
/**
+ * The deserialized form of the chromoting host as returned by Apiary.
+ * Note that the object has more fields than are detailed below--these
+ * are just the ones that we refer to directly.
* @constructor
*/
remoting.Host = function() {
@@ -26,8 +29,20 @@ remoting.Host = function() {
this.jabberId = '';
/** @type {string} */
this.publicKey = '';
-}
+};
+/**
+ * An entry in the host table.
+ * @constructor
+ */
+remoting.HostTableEntry = function() {
+ /** @type {remoting.Host} */
+ this.host = null;
+ /** @type {Element} */
+ this.tableRow = null;
+ /** @type {Element} */
+ this.hostNameCell = null;
+};
Jamie 2011/11/17 21:42:09 I separated out the raw object (Host) we get back
simonmorris 2011/11/17 23:59:48 Maybe HostModel and HostView would be more familia
Jamie 2011/11/18 22:54:57 It's not really MVC pattern though. I'd prefer to
/**
* @constructor
@@ -37,9 +52,26 @@ remoting.Host = function() {
remoting.HostList = function(table, errorDiv) {
this.table = table;
this.errorDiv = errorDiv;
- /** @type {Array.<remoting.Host>} */
- this.hosts = null;
-}
+ /**
+ * @type {Array.<remoting.HostTableEntry>}
+ * @private
+ */
+ this.hostTableEntries = null;
+};
+
+/**
+ * Search the host list for a host with the specified id.
+ * @param {string} hostId The unique id of the host.
+ * @return {remoting.HostTableEntry?} The host table entry, if any.
+ */
+remoting.HostList.prototype.getHostForId = function(hostId) {
+ for (var i = 0; i < this.hostTableEntries.length; ++i) {
+ if (this.hostTableEntries[i].host.hostId == hostId) {
+ return this.hostTableEntries[i];
+ }
+ }
+ return null;
+};
/**
* Refresh the host list with up-to-date details.
@@ -49,28 +81,38 @@ remoting.HostList = function(table, errorDiv) {
remoting.HostList.prototype.update = function(hosts) {
this.table.innerHTML = '';
this.showError(null);
- this.hosts = hosts;
+ this.hostTableEntries = [];
for (var i = 0; i < hosts.length; ++i) {
var host = hosts[i];
+ // Validate the entry to make sure it has all the fields we expect.
if (!host.hostName || !host.hostId || !host.status || !host.jabberId ||
!host.publicKey)
continue;
- var hostEntry = document.createElement('tr');
- addClass(hostEntry, 'host-list-row');
+ var hostTableEntry = new remoting.HostTableEntry();
+ hostTableEntry.host = host;
+
+ hostTableEntry.tableRow = document.createElement('tr');
+ addClass(hostTableEntry.tableRow, 'host-list-row');
var hostIcon = document.createElement('td');
+ addClass(hostIcon, 'host-list-row-start');
var hostIconImage = document.createElement('img');
hostIconImage.src = 'icon_host.png';
- hostIcon.className = 'host-list-row-start';
+ addClass(hostIconImage, 'host-list-main-icon');
hostIcon.appendChild(hostIconImage);
- hostEntry.appendChild(hostIcon);
+ hostTableEntry.tableRow.appendChild(hostIcon);
- var hostName = document.createElement('td');
- hostName.setAttribute('class', 'mode-select-label');
- hostName.appendChild(document.createTextNode(host.hostName));
- hostEntry.appendChild(hostName);
+ hostTableEntry.hostNameCell = document.createElement('td');
+ hostTableEntry.hostNameCell.setAttribute('class', 'mode-select-label');
+ hostTableEntry.hostNameCell.appendChild(
+ document.createTextNode(host.hostName));
+ hostTableEntry.hostNameCell.setAttribute(
+ 'ondblclick',
+ 'remoting.hostList.beginRenameHost("' +
+ host.hostId + '"); return false;');
+ hostTableEntry.tableRow.appendChild(hostTableEntry.hostNameCell);
var hostStatus = document.createElement('td');
if (host.status == 'ONLINE') {
@@ -78,22 +120,45 @@ remoting.HostList.prototype.update = function(hosts) {
connectButton.setAttribute('class', 'mode-select-button');
connectButton.setAttribute('type', 'button');
connectButton.setAttribute('onclick',
- 'remoting.connectHost("'+host.hostId+'")');
+ 'remoting.connectHost("' + host.hostId + '")');
connectButton.innerHTML =
chrome.i18n.getMessage(/*i18n-content*/'CONNECT_BUTTON');
hostStatus.appendChild(connectButton);
} else {
- addClass(hostEntry, 'host-offline');
+ addClass(hostTableEntry.tableRow, 'host-offline');
hostStatus.innerHTML = chrome.i18n.getMessage(/*i18n-content*/'OFFLINE');
}
hostStatus.className = 'host-list-row-end';
- hostEntry.appendChild(hostStatus);
+ hostTableEntry.tableRow.appendChild(hostStatus);
- this.table.appendChild(hostEntry);
+ var editButton = document.createElement('td');
+ editButton.setAttribute('onclick', 'remoting.hostList.beginRenameHost("' +
+ host.hostId + '")');
+ addClass(editButton, 'clickable');
+ addClass(editButton, 'host-list-edit');
+ var penImage = document.createElement('img');
+ penImage.src = 'icon_pencil.png';
+ addClass(penImage, 'host-list-rename-icon');
+ editButton.appendChild(penImage);
+ hostTableEntry.tableRow.appendChild(editButton);
+
+ var removeButton = document.createElement('td');
+ removeButton.setAttribute('onclick', 'remoting.hostList.removeHost("' +
+ host.hostId + '")');
+ addClass(removeButton, 'clickable');
+ addClass(removeButton, 'host-list-edit');
+ var crossImage = document.createElement('img');
+ crossImage.src = 'icon_cross.png';
+ addClass(crossImage, 'host-list-remove-icon');
+ removeButton.appendChild(crossImage);
+ hostTableEntry.tableRow.appendChild(removeButton);
simonmorris 2011/11/17 23:59:48 Clearer to make this new code a method of HostTabl
Jamie 2011/11/18 22:54:57 Good point, thanks for spotting this. I've refacto
+
+ this.hostTableEntries[i] = hostTableEntry;
+ this.table.appendChild(hostTableEntry.tableRow);
}
- this.showOrHide_(this.hosts.length != 0);
-}
+ this.showOrHide_(this.hostTableEntries.length != 0);
+};
/**
* Display a localized error message.
@@ -110,7 +175,7 @@ remoting.HostList.prototype.showError = function(errorTag) {
} else {
this.errorDiv.innerText = '';
}
-}
+};
/**
* Show or hide the host-list UI.
@@ -127,7 +192,142 @@ remoting.HostList.prototype.showOrHide_ = function(show) {
} else {
addClass(parent, remoting.HostList.COLLAPSED_);
}
-}
+};
+
+/**
+ * Remove a host from the list, and deregister it.
simonmorris 2011/11/17 23:59:48 Won't the user expect this to have some effect on
Jamie 2011/11/18 22:54:57 I think the long-term plan is to have hosts shut d
+ * @param {string} hostId The id of the host to be removed.
+ * @return {void} Nothing.
+ */
+remoting.HostList.prototype.removeHost = function(hostId) {
+ /** @type {remoting.HostTableEntry} */
+ var hostTableEntry = this.getHostForId(hostId);
+ if (!hostTableEntry) {
+ console.error('No host registered for id ' + hostId);
+ return;
+ }
+ hostTableEntry.tableRow.parentElement.removeChild(hostTableEntry.tableRow);
+ var index = this.hostTableEntries.indexOf(hostTableEntry);
+ if (index != -1) { // Since we've just found it, index must be >= 0
+ this.hostTableEntries.splice(index, 1);
+ }
+
+ /** @param {string} token */
+ var deleteHost = function(token) {
+ var headers = { 'Authorization': 'OAuth ' + token };
+ remoting.xhr.remove(
+ 'https://www.googleapis.com/chromoting/v1/@me/hosts/' + hostId,
+ function() {}, '', headers);
Wez 2011/11/17 22:58:58 Why not refresh the host list when the XHR complet
Jamie 2011/11/18 22:54:57 I'm not sure about that. It's only going to make a
+ }
+ remoting.oauth2.callWithToken(deleteHost);
+
+ this.showOrHide_(this.hostTableEntries.length != 0);
+};
+
+/**
+ * Prepare a host for renaming by replacing its name with an edit box.
+ * @param {string} hostId The id of the host to be renamed.
+ * @return {void} Nothing.
+ */
+remoting.HostList.prototype.beginRenameHost = function(hostId) {
+ /** @type {remoting.HostTableEntry} */
+ var hostTableEntry = this.getHostForId(hostId);
+ if (!hostTableEntry) {
+ console.error('No host registered for id ' + hostId);
+ return;
+ }
+ var editBox = /** @type {HTMLInputElement} */ document.createElement('input');
+ editBox.type = 'text';
+ editBox.value = hostTableEntry.host.hostName;
+ editBox.setAttribute('onblur',
+ 'remoting.hostList.commitRenameHost("' + hostId + '");');
+ /** @type {remoting.HostList} */
+ var that = this;
+ /** @param {Event} event */
+ var onKeydown = function(event) {
+ that.onKeydown(event, hostId);
+ }
+ editBox.onkeydown = onKeydown;
+ hostTableEntry.hostNameCell.innerHTML = '';
+ hostTableEntry.hostNameCell.appendChild(editBox);
+ editBox.select();
simonmorris 2011/11/17 23:59:48 This could be a method of HostView.
Jamie 2011/11/18 22:54:57 My refactoring addresses this.
+};
+
+/**
+ * Remove the edit box corresponding to the specified host, and reset its name.
+ * @param {remoting.HostTableEntry} hostTableEntry The host being renamed.
+ * @return {void} Nothing.
+ */
+remoting.HostList.prototype.removeEditBox = function(hostTableEntry) {
+ var editBox = hostTableEntry.hostNameCell.querySelector('input');
+ if (editBox) {
+ // onblur will fire when the edit box is removed, so remove the hook.
+ editBox.onblur = null;
+ }
+ hostTableEntry.hostNameCell.innerHTML = '';
+ hostTableEntry.hostNameCell.appendChild(
+ document.createTextNode(hostTableEntry.host.hostName));
+};
+
+/**
+ * Accept the host name entered by the user.
+ * @param {string} hostId The id of the host to be renamed.
+ * @return {void} Nothing.
+ */
+remoting.HostList.prototype.commitRenameHost = function(hostId) {
+ /** @type {remoting.HostTableEntry} */
+ var hostTableEntry = this.getHostForId(hostId);
+ if (hostTableEntry) {
+ var editBox = hostTableEntry.hostNameCell.querySelector('input');
+ if (editBox) {
+ if (hostTableEntry.host.hostName != editBox.value) {
+ hostTableEntry.host.hostName = editBox.value;
+ hostTableEntry.host.status = 'OFFLINE';
simonmorris 2011/11/17 23:59:48 Why is the status set here?
Jamie 2011/11/18 22:54:57 Left-over debugging code. Removed.
+ /** @param {string} token */
+ var renameHost = function(token) {
+ var headers = {
+ 'Authorization': 'OAuth ' + token,
+ 'content-type' : 'application/json; charset=UTF-8'
Wez 2011/11/17 22:58:58 nit: content-type capitalization.
Jamie 2011/11/18 22:54:57 Done.
+ };
+ var newHostDetails = { data: hostTableEntry.host };
+ remoting.xhr.put(
+ 'https://www.googleapis.com/chromoting/v1/@me/hosts/' + hostId,
+ function(xhr) {},
Wez 2011/11/17 22:58:58 Why not refresh when the XHR returns?
Jamie 2011/11/18 22:54:57 Same argument as above.
+ JSON.stringify(newHostDetails),
+ headers);
+ }
+ remoting.oauth2.callWithToken(renameHost);
+ }
+ }
+ }
+ this.removeEditBox(hostTableEntry);
+};
+
+/**
+ * Revert the host name, ignoring changes made by the user.
+ * @param {string} hostId The id of the host to be renamed.
+ * @return {void} Nothing.
+ */
+remoting.HostList.prototype.cancelRenameHost = function(hostId) {
+ var host = this.getHostForId(hostId);
Wez 2011/11/17 22:58:58 How can the user have cancelled editing if the hos
Jamie 2011/11/18 22:54:57 It's just a sanity check. I'd make it a DCHECK if
+ if (host) {
+ this.removeEditBox(host);
+ }
+};
+
+/**
+ * Handle a key event while the user is typing a host name
+ * @param {Event} event The keyboard event.
+ * @param {string} hostId The id of the host being renamed.
+ * @return {void} Nothing.
+ */
+remoting.HostList.prototype.onKeydown = function(event, hostId) {
+ if (event.which == 27) { // Escape
+ this.cancelRenameHost(hostId);
+ } else if (event.which == 13) { // Enter
+ this.commitRenameHost(hostId);
+ }
+};
/**
* Class name for the host list when it is collapsed.
@@ -136,4 +336,4 @@ remoting.HostList.prototype.showOrHide_ = function(show) {
remoting.HostList.COLLAPSED_ = 'collapsed';
/** @type {remoting.HostList} */
-remoting.hostList = null;
+remoting.hostList = null;
Wez 2011/11/17 22:58:58 Newline change?
Jamie 2011/11/18 22:54:57 Yep. The original was missing a newline.

Powered by Google App Engine
This is Rietveld 408576698