12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @fileoverview The section of the history page that shows tabs from sessions 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on other devices. 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Globals: 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** @const */ var MAX_NUM_COLUMNS = 3; 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** @const */ var NB_ENTRIES_FIRST_ROW_COLUMN = 6; 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** @const */ var NB_ENTRIES_OTHER_ROWS_COLUMN = 0; 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Histogram buckets for UMA tracking of menu usage. 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Using the same values as the Other Devices button in the NTP. 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** @const */ var HISTOGRAM_EVENT = { 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) INITIALIZED: 0, 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SHOW_MENU: 1, 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LINK_CLICKED: 2, 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LINK_RIGHT_CLICKED: 3, 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SESSION_NAME_RIGHT_CLICKED: 4, 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SHOW_SESSION_MENU: 5, 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) COLLAPSE_SESSION: 6, 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPAND_SESSION: 7, 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OPEN_ALL: 8, 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LIMIT: 9 // Should always be the last one. 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Record an event in the UMA histogram. 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {number} eventId The id of the event to be recorded. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)function recordUmaEvent_(eventId) { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome.send('metricsHandler:recordInHistogram', 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ['HistoryPage.OtherDevicesMenu', eventId, HISTOGRAM_EVENT.LIMIT]); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DeviceContextMenuController: 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Controller for the context menu for device names in the list of sessions. 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This class is designed to be used as a singleton. Also copied from existing 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * other devices button in NTP. 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * TODO(mad): Should we extract/reuse/share with ntp4/other_sessions.js? 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @constructor 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)function DeviceContextMenuController() { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.__proto__ = DeviceContextMenuController.prototype; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.initialize(); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)cr.addSingletonGetter(DeviceContextMenuController); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DeviceContextMenuController, Public: --------------------------------------- 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Initialize the context menu for device names in the list of sessions. 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceContextMenuController.prototype.initialize = function() { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var menu = new cr.ui.Menu; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cr.ui.decorate(menu, cr.ui.Menu); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.menu = menu; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.collapseItem_ = this.appendMenuItem_('collapseSessionMenuItemText'); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.collapseItem_.addEventListener('activate', 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.onCollapseOrExpand_.bind(this)); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.expandItem_ = this.appendMenuItem_('expandSessionMenuItemText'); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.expandItem_.addEventListener('activate', 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.onCollapseOrExpand_.bind(this)); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.openAllItem_ = this.appendMenuItem_('restoreSessionMenuItemText'); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.openAllItem_.addEventListener('activate', 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.onOpenAll_.bind(this)); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Set the session data for the session the context menu was invoked on. 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This should never be called when the menu is visible. 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object} session The model object for the session. 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceContextMenuController.prototype.setSession = function(session) { 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.session_ = session; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.updateMenuItems_(); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DeviceContextMenuController, Private: -------------------------------------- 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Appends a menu item to |this.menu|. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {string} textId The ID for the localized string that acts as 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * the item's label. 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {Element} The button used for a given menu option. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceContextMenuController.prototype.appendMenuItem_ = function(textId) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var button = document.createElement('button'); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.menu.appendChild(button); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cr.ui.decorate(button, cr.ui.MenuItem); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button.textContent = loadTimeData.getString(textId); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return button; 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Handler for the 'Collapse' and 'Expand' menu items. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Event} e The activation event. 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceContextMenuController.prototype.onCollapseOrExpand_ = function(e) { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.session_.collapsed = !this.session_.collapsed; 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.updateMenuItems_(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome.send('setForeignSessionCollapsed', 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [this.session_.tag, this.session_.collapsed]); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome.send('getForeignSessions'); // Refresh the list. 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var eventId = this.session_.collapsed ? 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HISTOGRAM_EVENT.COLLAPSE_SESSION : HISTOGRAM_EVENT.EXPAND_SESSION; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recordUmaEvent_(eventId); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Handler for the 'Open all' menu item. 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Event} e The activation event. 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceContextMenuController.prototype.onOpenAll_ = function(e) { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome.send('openForeignSession', [this.session_.tag]); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recordUmaEvent_(HISTOGRAM_EVENT.OPEN_ALL); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Set the visibility of the Expand/Collapse menu items based on the state 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * of the session that this menu is currently associated with. 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceContextMenuController.prototype.updateMenuItems_ = function() { 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.collapseItem_.hidden = this.session_.collapsed; 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.expandItem_.hidden = !this.session_.collapsed; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Device: 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Class to hold all the information about a device entry and generate a DOM 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * node for it. 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object} session An object containing the device's session data. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {DevicesView} view The view object this entry belongs to. 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @constructor 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)function Device(session, view) { 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.view_ = view; 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.session_ = session; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.searchText_ = view.getSearchText(); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Device, Public: ------------------------------------------------------------ 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Get the DOM node to display this device. 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {int} maxNumTabs The maximum number of tabs to display. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {int} row The row in which this device is displayed. 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {Object} A DOM node to draw the device. 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Device.prototype.getDOMNode = function(maxNumTabs, row) { 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var deviceDiv = createElementWithClassName('div', 'device'); 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.row_ = row; 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!this.session_) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return deviceDiv; 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Name heading 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var heading = document.createElement('h3'); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heading.textContent = this.session_.name; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heading.sessionData_ = this.session_; 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deviceDiv.appendChild(heading); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Keep track of the drop down that triggered the menu, so we know 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // which element to apply the command to. 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var session = this.session_; 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) function handleDropDownFocus(e) { 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeviceContextMenuController.getInstance().setSession(session); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heading.addEventListener('contextmenu', handleDropDownFocus); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var dropDownButton = new cr.ui.ContextMenuButton; 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dropDownButton.classList.add('drop-down'); 189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch dropDownButton.addEventListener('mousedown', function(event) { 190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch handleDropDownFocus(event); 191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Mousedown handling of cr.ui.MenuButton.handleEvent calls 192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // preventDefault, which prevents blur of the focused element. We need to 193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // do blur manually. 194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch document.activeElement.blur(); 195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dropDownButton.addEventListener('focus', handleDropDownFocus); 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heading.appendChild(dropDownButton); 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var timeSpan = createElementWithClassName('div', 'device-timestamp'); 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timeSpan.textContent = this.session_.modifiedTime; 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heading.appendChild(timeSpan); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cr.ui.contextMenuHandler.setContextMenu( 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heading, DeviceContextMenuController.getInstance().menu); 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!this.session_.collapsed) 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deviceDiv.appendChild(this.createSessionContents_(maxNumTabs)); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return deviceDiv; 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Marks tabs as hidden or not in our session based on the given searchText. 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {string} searchText The search text used to filter the content. 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Device.prototype.setSearchText = function(searchText) { 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.searchText_ = searchText.toLowerCase(); 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var i = 0; i < this.session_.windows.length; i++) { 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var win = this.session_.windows[i]; 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var foundMatch = false; 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var j = 0; j < win.tabs.length; j++) { 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var tab = win.tabs[j]; 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tab.title.toLowerCase().indexOf(this.searchText_) != -1) { 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) foundMatch = true; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab.hidden = false; 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab.hidden = true; 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) win.hidden = !foundMatch; 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Device, Private ------------------------------------------------------------ 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Create the DOM tree representing the tabs and windows of this device. 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {int} maxNumTabs The maximum number of tabs to display. 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {Element} A single div containing the list of tabs & windows. 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Device.prototype.createSessionContents_ = function(maxNumTabs) { 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var contents = createElementWithClassName('div', 'device-contents'); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var sessionTag = this.session_.tag; 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var numTabsShown = 0; 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var numTabsHidden = 0; 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var i = 0; i < this.session_.windows.length; i++) { 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var win = this.session_.windows[i]; 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (win.hidden) 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Show a separator between multiple windows in the same session. 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i > 0 && numTabsShown < maxNumTabs) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents.appendChild(document.createElement('hr')); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var j = 0; j < win.tabs.length; j++) { 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var tab = win.tabs[j]; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tab.hidden) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (numTabsShown < maxNumTabs) { 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) numTabsShown++; 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var a = createElementWithClassName('a', 'device-tab-entry'); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) a.href = tab.url; 265d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch a.style.backgroundImage = getFaviconImageSet(tab.url); 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.addHighlightedText_(a, tab.title); 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add a tooltip, since it might be ellipsized. The ones that are not 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // necessary will be removed once added to the document, so we can 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // compute sizes. 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) a.title = tab.title; 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We need to use this to not lose the ids as we go through other loop 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // turns. 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) function makeClickHandler(sessionTag, windowId, tabId) { 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return function(e) { 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) recordUmaEvent_(HISTOGRAM_EVENT.LINK_CLICKED); 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome.send('openForeignSession', [sessionTag, windowId, tabId, 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e.button, e.altKey, e.ctrlKey, e.metaKey, e.shiftKey]); 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e.preventDefault(); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) a.addEventListener('click', makeClickHandler(sessionTag, 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) String(win.sessionId), 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) String(tab.sessionId))); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents.appendChild(a); 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) numTabsHidden++; 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (numTabsHidden > 0) { 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) var moreLinkButton = createElementWithClassName('button', 294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 'device-show-more-tabs link-button'); 295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) moreLinkButton.addEventListener('click', this.view_.increaseRowHeight.bind( 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.view_, this.row_, numTabsHidden)); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var xMore = loadTimeData.getString('xMore'); 298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) moreLinkButton.appendChild( 299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) document.createTextNode(xMore.replace('$1', numTabsHidden))); 300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) contents.appendChild(moreLinkButton); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return contents; 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Add child text nodes to a node such that occurrences of this.searchText_ are 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * highlighted. 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Node} node The node under which new text nodes will be made as 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * children. 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {string} content Text to be added beneath |node| as one or more 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * text nodes. 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Device.prototype.addHighlightedText_ = function(node, content) { 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var endOfPreviousMatch = 0; 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.searchText_) { 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var lowerContent = content.toLowerCase(); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var searchTextLenght = this.searchText_.length; 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var newMatch = lowerContent.indexOf(this.searchText_, 0); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (newMatch != -1) { 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (newMatch > endOfPreviousMatch) { 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.appendChild(document.createTextNode( 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content.slice(endOfPreviousMatch, newMatch))); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) endOfPreviousMatch = newMatch + searchTextLenght; 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Mark the highlighted text in bold. 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var b = document.createElement('b'); 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) b.textContent = content.substring(newMatch, endOfPreviousMatch); 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.appendChild(b); 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) newMatch = lowerContent.indexOf(this.searchText_, endOfPreviousMatch); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (endOfPreviousMatch < content.length) { 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.appendChild(document.createTextNode( 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content.slice(endOfPreviousMatch))); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DevicesView: 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Functions and state for populating the page with HTML. 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @constructor 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)function DevicesView() { 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.devices_ = []; // List of individual devices. 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.resultDiv_ = $('other-devices'); 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.searchText_ = ''; 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.rowHeights_ = [NB_ENTRIES_FIRST_ROW_COLUMN]; 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.updateSignInState(loadTimeData.getBoolean('isUserSignedIn')); 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recordUmaEvent_(HISTOGRAM_EVENT.INITIALIZED); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DevicesView, public: ------------------------------------------------------- 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Updates our sign in state by clearing the view is not signed in or sending 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * a request to get the data to display otherwise. 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {boolean} signedIn Whether the user is signed in or not. 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevicesView.prototype.updateSignInState = function(signedIn) { 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (signedIn) 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome.send('getForeignSessions'); 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.clearDOM(); 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Resets the view sessions. 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object} sessionList The sessions to add. 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevicesView.prototype.setSessionList = function(sessionList) { 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.devices_ = []; 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var i = 0; i < sessionList.length; i++) 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.devices_.push(new Device(sessionList[i], this)); 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.displayResults_(); 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Sets the current search text. 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {string} searchText The text to search. 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevicesView.prototype.setSearchText = function(searchText) { 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.searchText_ != searchText) { 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.searchText_ = searchText; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var i = 0; i < this.devices_.length; i++) 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.devices_[i].setSearchText(searchText); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.displayResults_(); 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {string} The current search text. 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevicesView.prototype.getSearchText = function() { 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return this.searchText_; 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Clears the DOM content of the view. 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevicesView.prototype.clearDOM = function() { 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (this.resultDiv_.hasChildNodes()) { 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.resultDiv_.removeChild(this.resultDiv_.lastChild); 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Increase the height of a row by the given amount. 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {int} row The row number. 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {int} height The extra height to add to the givent row. 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevicesView.prototype.increaseRowHeight = function(row, height) { 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var i = this.rowHeights_.length; i <= row; i++) 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.rowHeights_.push(NB_ENTRIES_OTHER_ROWS_COLUMN); 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.rowHeights_[row] += height; 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.displayResults_(); 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DevicesView, Private ------------------------------------------------------- 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Update the page with results. 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevicesView.prototype.displayResults_ = function() { 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.clearDOM(); 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var resultsFragment = document.createDocumentFragment(); 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.devices_.length == 0) 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We'll increase to 0 as we create the first row. 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var rowIndex = -1; 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need to access the last row and device when we get out of the loop. 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var currentRowElement; 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is only set when changing rows, yet used on all device columns. 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var maxNumTabs; 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var i = 0; i < this.devices_.length; i++) { 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var device = this.devices_[i]; 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Should we start a new row? 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i % MAX_NUM_COLUMNS == 0) { 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (currentRowElement) 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resultsFragment.appendChild(currentRowElement); 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) currentRowElement = createElementWithClassName('div', 'devices-row'); 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rowIndex++; 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rowIndex < this.rowHeights_.length) 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) maxNumTabs = this.rowHeights_[rowIndex]; 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) maxNumTabs = 0; 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) currentRowElement.appendChild(device.getDOMNode(maxNumTabs, rowIndex)); 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (currentRowElement) 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resultsFragment.appendChild(currentRowElement); 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.resultDiv_.appendChild(resultsFragment); 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove the tootltip on all lines that don't need it. It's easier to 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // remove them here, after adding them all above, since we have the data 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // handy above, but we don't have the width yet. Whereas here, we have the 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // width, and the nodeValue could contain sub nodes for highlighting, which 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // makes it harder to extract the text data here. 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tabs = document.getElementsByClassName('device-tab-entry'); 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var i = 0; i < tabs.length; i++) { 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tabs[i].scrollWidth <= tabs[i].clientWidth) 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tabs[i].title = ''; 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.resultDiv_.appendChild( 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) createElementWithClassName('div', 'other-devices-bottom')); 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 476558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch/** 477558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * Sets the menu model data. An empty list means that either there are no 478558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * foreign sessions, or tab sync is disabled for this profile. 479558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * |isTabSyncEnabled| makes it possible to distinguish between the cases. 480558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * 481558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {Array} sessionList Array of objects describing the sessions 482558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * from other devices. 483558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {boolean} isTabSyncEnabled Is tab sync enabled for this profile? 484558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch */ 485558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochfunction setForeignSessions(sessionList, isTabSyncEnabled) { 486558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // The other devices is shown iff tab sync is enabled. 487558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (isTabSyncEnabled) 488558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch devicesView.setSessionList(sessionList); 489558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch else 490558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch devicesView.clearDOM(); 491558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 493558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch/** 494558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * Called when this element is initialized, and from the new tab page when 495558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * the user's signed in state changes, 496558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {string} header The first line of text (unused here). 497558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {string} subHeader The second line of text (unused here). 498558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {string} iconURL The url for the login status icon. If this is null 499558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch then the login status icon is hidden (unused here). 500558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * @param {boolean} isUserSignedIn Is the user currently signed in? 501558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch */ 502558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochfunction updateLogin(header, subHeader, iconURL, isUserSignedIn) { 503558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (devicesView) 504558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch devicesView.updateSignInState(isUserSignedIn); 505558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Document Functions: 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Window onload handler, sets up the other devices view. 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)function load() { 513558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!loadTimeData.getBoolean('isInstantExtendedApiEnabled')) 514558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return; 515558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 516558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // We must use this namespace to reuse the handler code for foreign session 517558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // and login. 518558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch cr.define('ntp', function() { 519558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return { 520558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch setForeignSessions: setForeignSessions, 521558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch updateLogin: updateLogin 522558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch }; 523558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch }); 524558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) devicesView = new DevicesView(); 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the context menu that appears when the user right clicks 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // on a device name or hit click on the button besides the device name 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) document.body.appendChild(DeviceContextMenuController.getInstance().menu); 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var doSearch = function(e) { 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) devicesView.setSearchText($('search-field').value); 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) $('search-field').addEventListener('search', doSearch); 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) $('search-button').addEventListener('click', doSearch); 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Add handlers to HTML elements. 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)document.addEventListener('DOMContentLoaded', load); 540