Javascript  |  204行  |  7.08 KB

// Copyright (c) 2012 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.

/**
 * @fileoverview
 * Class to track of connections to and from this computer and display them.
 */

'use strict';

/** @suppress {duplicate} */
var remoting = remoting || {};

/** @constructor */
remoting.ConnectionHistory = function() {
  /** @type {HTMLElement} @private */
  this.viewAll_ = document.getElementById('history-view-all');
  /** @type {HTMLElement} @private */
  this.viewOutgoing_ = document.getElementById('history-view-outgoing');
  /** @type {HTMLElement} @private */
  this.viewIncoming_ = document.getElementById('history-view-incoming');
  /** @type {HTMLElement} @private */
  this.clear_ = document.getElementById('clear-connection-history');
  /** @type {HTMLElement} @private */
  this.historyEntries_ = document.getElementById('connection-history-entries');
  /** @type {remoting.ConnectionHistory.Filter} @private */
  this.filter_ = remoting.ConnectionHistory.Filter.VIEW_ALL;

  /** @type {remoting.ConnectionHistory} */
  var that = this;
  var closeButton = document.getElementById('close-connection-history');
  closeButton.addEventListener('click', this.hide.bind(this), false);
  /** @param {Event} event Event identifying which button was clicked. */
  var setFilter = function(event) { that.setFilter_(event.target); };
  this.viewAll_.addEventListener('click', setFilter, false);
  this.viewOutgoing_.addEventListener('click', setFilter, false);
  this.viewIncoming_.addEventListener('click', setFilter, false);
  this.clear_.addEventListener('click', this.clearHistory_.bind(this), false);
};

/** @enum {string} */
remoting.ConnectionHistory.Filter = {
  VIEW_ALL: 'history-view-all',
  VIEW_OUTGOING: 'history-view-outgoing',
  VIEW_INCOMING: 'history-view-incoming'
};

/** Show the dialog and refresh its contents */
remoting.ConnectionHistory.prototype.show = function() {
  this.load();
  remoting.setMode(remoting.AppMode.HISTORY);
};

/** Hide the dialog */
remoting.ConnectionHistory.prototype.hide = function() {
  remoting.setMode(remoting.AppMode.HOME);
};

/**
 * A saved entry in the connection history.
 * @param {Object} object A Javascript object, which may or may not be of the
 *     correct type.
 * @constructor
 */
remoting.ConnectionHistory.Entry = function(object) {
  this.valid =
      'date' in object && typeof(object['date']) == 'number' &&
      'from' in object && typeof(object['from']) == 'string' &&
      'to' in object && typeof(object['to']) == 'string' &&
      'duration' in object && typeof(object['duration']) == 'number';
  if (this.valid) {
    /** @type {Date} */
    this.date = new Date(object['date']);
    /** @type {string} */
    this.from = object['from'];
    /** @type {string} */
    this.to = object['to'];
    /** @type {number} */
    this.duration = object['duration'];
  }
};

/**
 * @return {string} The connection duration, formatted as a string, or 'Not
 *     available' if there is no duration stored.
 * @private
 */
remoting.ConnectionHistory.Entry.prototype.durationString_ = function() {
  var secs = this.duration % 60;
  var mins = ((this.duration - secs) / 60) % 60;
  var hours = (this.duration - secs - 60 * mins) / 3600;
  if (secs < 10) {
    secs = '0' + secs;
  }
  var result = mins + ':' + secs;
  if (hours > 0) {
    if (mins < 10) {
      result = '0' + result;
    }
    result = hours + ':' + result;
  }
  return result;
};

/**
 * @return {{summary: Element, detail: Element}} Two table rows containing the
 *     summary and detail information, respectively, for the connection.
 */
remoting.ConnectionHistory.Entry.prototype.createTableRows = function() {
  var summary = /** @type {HTMLElement} */ document.createElement('tr');
  summary.classList.add('connection-history-summary');
  var zippy = /** @type {HTMLElement} */ document.createElement('td');
  zippy.classList.add('zippy');
  summary.appendChild(zippy);
  // TODO(jamiewalch): Find a way of combining date and time such both align
  // vertically without being considered separate columns, which puts too much
  // space between them.
  var date = document.createElement('td');
  // TODO(jamiewalch): Use a shorter localized version of the date.
  date.innerText = this.date.toLocaleDateString();
  summary.appendChild(date);
  var time = document.createElement('td');
  time.innerText = this.date.toLocaleTimeString();
  summary.appendChild(time);
  var from = document.createElement('td');
  from.innerText = this.from;
  summary.appendChild(from);
  var to = document.createElement('td');
  to.innerText = this.to;
  summary.appendChild(to);
  var duration = document.createElement('td');
  duration.innerText = this.durationString_();
  summary.appendChild(duration);
  // TODO(jamiewalch): Fill out the detail row correctly.
  var detail = /** @type {HTMLElement} */ document.createElement('tr');
  detail.classList.add('connection-history-detail');
  for (var i = 0; i < summary.childElementCount; ++i) {
    var td = document.createElement('td');
    if (i != 0) {
      // The inner div allows the details rows to be hidden without changing
      // the column widths.
      var div = document.createElement('div');
      div.innerText = 'Nothing to see here';
      td.appendChild(div);
    }
    detail.appendChild(td);
  }
  /** @param {HTMLElement} node The summary row. */
  var toggleDetail = function(node) {
    node.classList.toggle('expanded');
  };
  summary.addEventListener('click',
                           function() { toggleDetail(summary); },
                           false);
  detail.addEventListener('click',
                          function() { toggleDetail(summary); },
                          false);
  return { 'summary': summary, 'detail': detail };
};

/** Refresh the contents of the connection history table */
remoting.ConnectionHistory.prototype.load = function() {
  // TODO(jamiewalch): Load connection history data when it's available.
  var history = [];
  // Remove existing entries from the DOM and repopulate.
  // TODO(jamiewalch): Enforce the filter.
  this.historyEntries_.innerText = '';
  for (var i in history) {
    var connection = new remoting.ConnectionHistory.Entry(history[i]);
    if (connection.valid) {
      var rows = connection.createTableRows();
      this.historyEntries_.appendChild(rows.summary);
      this.historyEntries_.appendChild(rows.detail);
    }
  }
};

/**
 * @param {EventTarget} element The element that was clicked.
 * @private
 */
remoting.ConnectionHistory.prototype.setFilter_ = function(element) {
  for (var i in remoting.ConnectionHistory.Filter) {
    var link = document.getElementById(remoting.ConnectionHistory.Filter[i]);
    if (element == link) {
      link.classList.add('no-link');
      this.filter_ = /** @type {remoting.ConnectionHistory.Filter} */ (i);
    } else {
      link.classList.remove('no-link');
    }
  }
};

/**
 * @private
 */
remoting.ConnectionHistory.prototype.clearHistory_ = function() {
  // TODO(jamiewalch): Implement once we store users' connection histories.
};

/** @type {remoting.ConnectionHistory} */
remoting.ConnectionHistory.connectionHistory = null;