Index: chrome/browser/resources/bluetooth_internals/device.js |
diff --git a/chrome/browser/resources/bluetooth_internals/device.js b/chrome/browser/resources/bluetooth_internals/device.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f64ffcf3e634526b0d427158f85943ae4c1bef9f |
--- /dev/null |
+++ b/chrome/browser/resources/bluetooth_internals/device.js |
@@ -0,0 +1,189 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+/** |
+ * Javascript for Device-related features, served from |
+ * chrome://bluetooth-internals/. |
+ */ |
+ |
+cr.define('device', function() { |
ortuno
2016/10/26 03:26:11
Split the DeviceTable code into a separate file. W
mbrunson
2016/10/29 00:49:43
Done.
|
+ |
+ var REMOVED_CSS = 'removed'; |
+ |
+ /** |
+ * A table that lists the devices and responds to changes in the given |
+ * DeviceCollection. |
+ * @constructor |
+ * @extends {HTMLTableElement} |
+ */ |
+ var DeviceTable = cr.ui.define(function() { |
+ this.devices_ = null; |
+ |
+ return document.importNode($('table-template').content.children[0], |
+ true /* deep */); |
+ }); |
+ DeviceTable.prototype = { |
+ __proto__: HTMLTableElement.prototype, |
+ |
+ /** |
+ * Decorates an element as a UI element class. Caches references to the |
+ * table body and headers. |
+ */ |
+ decorate: function() { |
+ this.body_ = this.tBodies[0]; |
+ this.headers_ = this.tHead.rows[0].cells; |
+ }, |
+ |
+ /** |
+ * Sets the tables device collection. |
+ * @param {!DeviceCollection} deviceCollection |
+ */ |
+ setDevices: function(deviceCollection) { |
+ if (this.devices_) { |
+ this.devices_.removeEventListener('sorted', this.redraw_.bind(this)); |
+ this.devices_.removeEventListener('change', |
+ this.handleChange_.bind(this)); |
+ this.devices_.removeEventListener('splice', |
+ this.handleSplice_.bind(this)); |
+ } |
+ |
+ this.devices_ = deviceCollection; |
+ this.devices_.addEventListener('sorted', this.redraw_.bind(this)); |
+ this.devices_.addEventListener('change', this.handleChange_.bind(this)); |
+ this.devices_.addEventListener('splice', this.handleSplice_.bind(this)); |
+ |
+ this.redraw_(); |
+ }, |
+ |
+ /** |
+ * Updates table row on change event of the device collection. |
+ * @param {!Event} event |
+ */ |
+ handleChange_: function(event) { |
+ this.updateRow_(this.devices_.item(event.index), event.index); |
+ }, |
+ |
+ /** |
+ * Updates table row on splice event of the device collection. |
+ * @param {!Event} event |
+ */ |
+ handleSplice_: function(event) { |
+ event.removed.forEach(function() { |
+ this.removeRow(event.index); |
+ }, this); |
+ |
+ event.added.forEach(function(device, index) { |
+ this.newRowForDevice_(device, event.index + index); |
+ }, this); |
+ }, |
+ |
+ /** |
+ * Inserts a new row at |index| and updates it with info from |device|. |
+ * @param {!Device} device |
+ * @param {?number} index |
+ */ |
+ newRowForDevice_: function(device, index) { |
+ var row = this.body_.insertRow(index); |
+ row.id = device.info.address; |
+ |
+ for (var i = 0; i < this.headers_.length; i++) { |
+ row.insertCell(); |
+ } |
+ |
+ this.updateRow_(device, row.sectionRowIndex); |
+ }, |
+ |
+ /** |
+ * Deletes and recreates the table using the cached |devices_|. |
+ */ |
+ redraw_: function() { |
+ this.removeChild(this.body_); |
+ this.appendChild(document.createElement('tbody')); |
+ this.body_ = this.tBodies[0]; |
+ this.body_.classList.add('table-body'); |
+ |
+ for (var i = 0; i < this.devices_.length; i++) { |
+ this.newRowForDevice_(this.devices_.item(i)); |
+ } |
+ }, |
+ |
+ /** |
+ * Updates the row at |index| with the info from |device|. |
+ * @param {!Device} device |
+ * @param {!number} index |
+ */ |
+ updateRow_: function(device, index) { |
+ var row = this.body_.rows[index]; |
+ |
+ if (device.removed) { |
+ row.classList.add(REMOVED_CSS); |
+ } else { |
+ row.classList.remove(REMOVED_CSS); |
+ } |
+ |
+ // Update the properties based on the header field path. |
+ for (var i = 0; i < this.headers_.length; i++) { |
+ var header = this.headers_[i]; |
+ var propName = header.dataset.field; |
+ |
+ var parts = propName.split('.'); |
+ var obj = device.info; |
+ while (obj != null && parts.length > 0) { |
+ var part = parts.shift(); |
+ obj = obj[part]; |
+ } |
+ |
+ var cell = row.cells[i]; |
+ cell.textContent = obj || 'Unknown'; |
+ cell.dataset.label = header.innerText; |
+ } |
+ }, |
+ }; |
+ |
+ /* |
+ * Collection of devices with helper functions for searching and updating by |
+ * device address. |
+ * @constructor |
+ * @param {!Array} array the starting collection of devices. |
+ * @extends {cr.ui.ArrayDataModel} |
+ */ |
+ var DeviceCollection = function(array) { |
+ cr.ui.ArrayDataModel.call(this, array); |
+ }; |
+ DeviceCollection.prototype = { |
+ __proto__: cr.ui.ArrayDataModel.prototype, |
+ getByAddress: function(address) { |
+ for (var i = 0; i < this.length; i++) { |
+ var device = this.item(i); |
+ if (address == device.info.address) |
+ return device; |
+ } |
+ return null; |
+ }, |
+ update: function(device) { |
ortuno
2016/10/26 03:26:11
Would it make sense to move all of the device info
mbrunson
2016/10/29 00:49:43
Hmm...ok. A few other places could have better sep
|
+ var oldDevice = this.getByAddress(device.info.address); |
+ if (oldDevice) { |
+ this.replaceItem(oldDevice, device); |
+ } else { |
+ this.push(device); |
+ } |
+ } |
+ }; |
+ |
+ /* |
+ * Data model for a cached device. |
+ * @constructor |
+ * @param {!bluetoothDevice.DeviceInfo} info |
+ */ |
+ var Device = function(info) { |
+ this.info = info; |
+ this.removed = false; |
+ }; |
+ |
+ return { |
+ Device: Device, |
+ DeviceCollection, DeviceCollection, |
+ DeviceTable: DeviceTable, |
+ }; |
+}); |