| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import {createElementWithClassName} from 'chrome://resources/ash/common/util.js'; |
| |
| import {MENU_TEXT_COLOR_DARK, MENU_TEXT_COLOR_LIGHT} from './constants.js'; |
| import {DataSeries} from './data_series.js'; |
| |
| /** |
| * Create by |LineChart|. |
| * A menu to show and to control the visibility of the data series in current |
| * line chart. |
| * @const |
| */ |
| export class Menu { |
| constructor(/** function(): undefined */ callback) { |
| /** |
| * Handle the menu status changed event, include clicking button, hiding or |
| * showing the menu. |
| * @const {function(): undefined} |
| */ |
| this.callback_ = callback; |
| |
| /** @const {Element} - Root of the menu. */ |
| this.rootDiv_ = createElementWithClassName('div', 'line-chart-menu'); |
| |
| /** @const {Element} - Container of buttons. */ |
| this.buttonOuterDiv_ = |
| createElementWithClassName('div', 'line-chart-menu-button-outer'); |
| this.rootDiv_.appendChild(this.buttonOuterDiv_); |
| |
| /** @const {Element} - Handle to control the visibility of menu. */ |
| this.handleDiv_ = |
| createElementWithClassName('div', 'line-chart-menu-handle'); |
| this.rootDiv_.appendChild(this.handleDiv_); |
| this.handleDiv_.addEventListener('click', this.handleOnClick_.bind(this)); |
| |
| /** @type {Array<DataSeries>} */ |
| this.dataSeries_ = []; |
| |
| /** @type {Array<Element>} - Buttons of data series. */ |
| this.buttons_ = []; |
| } |
| |
| /** |
| * Handle menu showing and hiding. |
| * @this {Menu} |
| */ |
| handleOnClick_() { |
| const /** string|null */ hiddenAttr = |
| this.buttonOuterDiv_.getAttribute('hidden'); |
| if (hiddenAttr == null) { |
| this.buttonOuterDiv_.setAttribute('hidden', ''); |
| } else { |
| this.buttonOuterDiv_.removeAttribute('hidden'); |
| } |
| this.callback_(); |
| } |
| |
| /** @return {Element} */ |
| getRootDiv() { |
| return this.rootDiv_; |
| } |
| |
| /** @return {number} */ |
| getWidth() { |
| return this.rootDiv_.offsetWidth; |
| } |
| |
| /** |
| * Add a data series to the menu. |
| * @param {DataSeries} dataSeries |
| */ |
| addDataSeries(dataSeries) { |
| const /** number */ idx = this.dataSeries_.indexOf(dataSeries); |
| if (idx != -1) { |
| return; |
| } |
| const /** Element */ button = this.createButton_(dataSeries); |
| this.buttons_.push(button); |
| this.buttonOuterDiv_.appendChild(button); |
| this.dataSeries_.push(dataSeries); |
| |
| /* Width may change. */ |
| this.callback_(); |
| } |
| |
| /** |
| * Create a button to control the data series. |
| * @param {DataSeries} dataSeries |
| * @return {Element} |
| */ |
| createButton_(dataSeries) { |
| const /** Element */ buttonInner = |
| createElementWithClassName('span', 'line-chart-menu-button-inner-span'); |
| buttonInner.innerText = dataSeries.getTitle(); |
| const /** Element */ button = |
| createElementWithClassName('div', 'line-chart-menu-button'); |
| button.appendChild(buttonInner); |
| this.setupButtonOnClickHandler_(button, dataSeries); |
| |
| const /** boolean */ visible = dataSeries.isVisible(); |
| this.updateButtonStyle_(button, dataSeries, visible); |
| return button; |
| } |
| |
| /** |
| * Add a onclick handler to the button. |
| * @param {Element} button |
| * @param {DataSeries} dataSeries |
| */ |
| setupButtonOnClickHandler_(button, dataSeries) { |
| const /** function(Event): undefined */ handler = function(event) { |
| const /** boolean */ visible = !dataSeries.isVisible(); |
| dataSeries.setVisible(visible); |
| this.updateButtonStyle_(button, dataSeries, visible); |
| this.callback_(); |
| }.bind(this); |
| button.addEventListener('click', handler); |
| } |
| |
| /** |
| * Update the button style with the visibility of data series. |
| * @param {Element} button |
| * @param {DataSeries} dataSeries |
| * @param {boolean} visible |
| */ |
| updateButtonStyle_(button, dataSeries, visible) { |
| if (visible) { |
| button.style.backgroundColor = dataSeries.getColor(); |
| const /** string */ color = dataSeries.isMenuTextBlack() ? |
| MENU_TEXT_COLOR_DARK : |
| MENU_TEXT_COLOR_LIGHT; |
| button.style.color = color; |
| } else { |
| button.style.backgroundColor = MENU_TEXT_COLOR_LIGHT; |
| button.style.color = MENU_TEXT_COLOR_DARK; |
| } |
| } |
| |
| /** |
| * Remove a data series from the menu. |
| * @param {DataSeries} dataSeries |
| */ |
| removeDataSeries(dataSeries) { |
| const /** number */ idx = this.dataSeries_.indexOf(dataSeries); |
| if (idx == -1) { |
| return; |
| } |
| this.dataSeries_.splice(idx, 1); |
| const /** Element */ button = this.buttons_.splice(idx, 1)[0]; |
| this.buttonOuterDiv_.removeChild(button); |
| /* Width may change. */ |
| this.callback_(); |
| } |
| } |