|  | // Copyright 2018 the V8 project authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | 'use strict'; | 
|  |  | 
|  | const details_selection_template = | 
|  | document.currentScript.ownerDocument.querySelector( | 
|  | '#details-selection-template'); | 
|  |  | 
|  | class DetailsSelection extends HTMLElement { | 
|  | constructor() { | 
|  | super(); | 
|  | const shadowRoot = this.attachShadow({mode: 'open'}); | 
|  | shadowRoot.appendChild(details_selection_template.content.cloneNode(true)); | 
|  | this.isolateSelect.addEventListener( | 
|  | 'change', e => this.handleIsolateChange(e)); | 
|  | this.datasetSelect.addEventListener( | 
|  | 'change', e => this.notifySelectionChanged(e)); | 
|  | this.$('#merge-categories') | 
|  | .addEventListener('change', e => this.notifySelectionChanged(e)); | 
|  | } | 
|  |  | 
|  | connectedCallback() { | 
|  | for (let category of CATEGORIES.keys()) { | 
|  | this.$('#categories').appendChild(this.buildCategory(category)); | 
|  | } | 
|  | } | 
|  |  | 
|  | set data(value) { | 
|  | this._data = value; | 
|  | this.dataChanged(); | 
|  | } | 
|  |  | 
|  | get data() { | 
|  | return this._data; | 
|  | } | 
|  |  | 
|  | buildCategory(name) { | 
|  | const div = document.createElement('div'); | 
|  | div.id = name; | 
|  | div.classList.add('box'); | 
|  | const span = document.createElement('span'); | 
|  | div.appendChild(span); | 
|  | span.innerHTML = CATEGORY_NAMES.get(name) + ' '; | 
|  | const all_button = document.createElement('button'); | 
|  | span.appendChild(all_button); | 
|  | all_button.innerHTML = 'All'; | 
|  | all_button.addEventListener('click', e => this.selectCategory(name)); | 
|  | const none_button = document.createElement('button'); | 
|  | span.appendChild(none_button); | 
|  | none_button.innerHTML = 'None'; | 
|  | none_button.addEventListener('click', e => this.unselectCategory(name)); | 
|  | const innerDiv = document.createElement('div'); | 
|  | div.appendChild(innerDiv); | 
|  | innerDiv.id = name + 'Content'; | 
|  | return div; | 
|  | } | 
|  |  | 
|  | $(id) { | 
|  | return this.shadowRoot.querySelector(id); | 
|  | } | 
|  |  | 
|  | get datasetSelect() { | 
|  | return this.$('#dataset-select'); | 
|  | } | 
|  |  | 
|  | get isolateSelect() { | 
|  | return this.$('#isolate-select'); | 
|  | } | 
|  |  | 
|  | dataChanged() { | 
|  | this.clearUI(); | 
|  | this.populateSelect('#isolate-select', Object.keys(this.data)); | 
|  | this.handleIsolateChange(); | 
|  | } | 
|  |  | 
|  | clearUI() { | 
|  | this.selection = {categories: {}}; | 
|  | removeAllChildren(this.isolateSelect); | 
|  | removeAllChildren(this.datasetSelect); | 
|  | this.clearCategories(); | 
|  | } | 
|  |  | 
|  | handleIsolateChange(e) { | 
|  | this.selection.isolate = this.isolateSelect.value; | 
|  | if (this.selection.isolate.length === 0) { | 
|  | this.selection.isolate = null; | 
|  | return; | 
|  | } | 
|  |  | 
|  | this.populateSelect( | 
|  | '#dataset-select', this.data[this.selection.isolate].data_sets, 'live'); | 
|  | this.populateCategories(); | 
|  | this.notifySelectionChanged(); | 
|  | } | 
|  |  | 
|  | notifySelectionChanged(e) { | 
|  | if (!this.selection.isolate) return; | 
|  |  | 
|  | this.selection.categories = {}; | 
|  | for (let category of CATEGORIES.keys()) { | 
|  | const selected = this.selectedInCategory(category); | 
|  | if (selected.length > 0) this.selection.categories[category] = selected; | 
|  | } | 
|  | this.selection.category_names = CATEGORY_NAMES; | 
|  | this.selection.data_set = this.datasetSelect.value; | 
|  | this.selection.merge_categories = this.$('#merge-categories').checked; | 
|  | this.dispatchEvent(new CustomEvent( | 
|  | 'change', {bubbles: true, composed: true, detail: this.selection})); | 
|  | } | 
|  |  | 
|  | selectedInCategory(category) { | 
|  | const selected = this.shadowRoot.querySelectorAll( | 
|  | 'input[name=' + category + 'Checkbox]:checked'); | 
|  | var tmp = []; | 
|  | for (var val of selected.values()) tmp.push(val.value); | 
|  | return tmp; | 
|  | } | 
|  |  | 
|  | categoryForType(instance_type) { | 
|  | for (let [key, value] of CATEGORIES.entries()) { | 
|  | if (value.has(instance_type)) return key; | 
|  | } | 
|  | return 'unclassified'; | 
|  | } | 
|  |  | 
|  | createOption(text) { | 
|  | const option = document.createElement('option'); | 
|  | option.value = text; | 
|  | option.text = text; | 
|  | return option; | 
|  | } | 
|  |  | 
|  | populateSelect(id, iterable, autoselect = null) { | 
|  | for (let option_value of iterable) { | 
|  | const option = this.createOption(option_value); | 
|  | if (autoselect === option_value) { | 
|  | option.selected = 'selected'; | 
|  | } | 
|  | this.$(id).appendChild(option); | 
|  | } | 
|  | } | 
|  |  | 
|  | clearCategories() { | 
|  | for (const category of CATEGORIES.keys()) { | 
|  | let f = this.$('#' + category + 'Content'); | 
|  | while (f.firstChild) { | 
|  | f.removeChild(f.firstChild); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | populateCategories() { | 
|  | this.clearCategories(); | 
|  | const categories = {}; | 
|  | for (let cat of CATEGORIES.keys()) { | 
|  | categories[cat] = []; | 
|  | } | 
|  |  | 
|  | for (let instance_type of this.data[this.selection.isolate] | 
|  | .non_empty_instance_types) { | 
|  | if (IGNORED_INSTANCE_TYPES.has(instance_type)) continue; | 
|  | const category = this.categoryForType(instance_type); | 
|  | categories[category].push(instance_type); | 
|  | } | 
|  | for (let category of Object.keys(categories)) { | 
|  | categories[category].sort(); | 
|  | for (let instance_type of categories[category]) { | 
|  | this.$('#' + category + 'Content') | 
|  | .appendChild(this.createCheckBox(instance_type, category)); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | unselectCategory(category) { | 
|  | for (let checkbox of this.shadowRoot.querySelectorAll( | 
|  | 'input[name=' + category + 'Checkbox]')) { | 
|  | checkbox.checked = false; | 
|  | } | 
|  | this.notifySelectionChanged(); | 
|  | } | 
|  |  | 
|  | selectCategory(category) { | 
|  | for (let checkbox of this.shadowRoot.querySelectorAll( | 
|  | 'input[name=' + category + 'Checkbox]')) { | 
|  | checkbox.checked = true; | 
|  | } | 
|  | this.notifySelectionChanged(); | 
|  | } | 
|  |  | 
|  | createCheckBox(instance_type, category) { | 
|  | const div = document.createElement('div'); | 
|  | div.classList.add('boxDiv'); | 
|  | const input = document.createElement('input'); | 
|  | div.appendChild(input); | 
|  | input.type = 'checkbox'; | 
|  | input.name = category + 'Checkbox'; | 
|  | input.checked = 'checked'; | 
|  | input.id = instance_type + 'Checkbox'; | 
|  | input.value = instance_type; | 
|  | input.addEventListener('change', e => this.notifySelectionChanged(e)); | 
|  | const label = document.createElement('label'); | 
|  | div.appendChild(label); | 
|  | label.innerText = instance_type; | 
|  | label.htmlFor = instance_type + 'Checkbox'; | 
|  | return div; | 
|  | } | 
|  | } | 
|  |  | 
|  | customElements.define('details-selection', DetailsSelection); |