mirror of
https://github.com/golang/go
synced 2024-11-18 15:14:44 -07:00
08b1e0510c
This change also puts more structure into the viewer. Adds an enum for events that we'll issue and a few more elements to organize things. Change-Id: I39c7c53422779348ca05f051c6b0b07d22ad6a00 Reviewed-on: https://go-review.googlesource.com/26656 Reviewed-by: Alan Donovan <adonovan@google.com>
196 lines
5.5 KiB
TypeScript
196 lines
5.5 KiB
TypeScript
// Copyright 2016 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
/**
|
|
* An enum of types of actions that might be requested
|
|
* by the app.
|
|
*/
|
|
enum Action {
|
|
TOGGLE_SIDEBAR, // Toggle the sidebar.
|
|
NAVIGATE_ABOUT, // Go to the about page.
|
|
}
|
|
|
|
const TITLE = 'Go Heap Viewer';
|
|
|
|
/**
|
|
* A type of event that signals to the AppElement controller
|
|
* that something shoud be done. For the most part, the structure
|
|
* of the app will be that elements' state will mostly be controlled
|
|
* by parent elements. Elements will issue actions that the AppElement
|
|
* will handle, and the app will be re-rendered down the DOM
|
|
* hierarchy.
|
|
*/
|
|
class ActionEvent extends Event {
|
|
static readonly EVENT_TYPE = 'action-event'
|
|
constructor(public readonly action: Action) { super(ActionEvent.EVENT_TYPE); }
|
|
}
|
|
|
|
/**
|
|
* A hamburger menu element. Triggers a TOGGLE_SIDE action to toggle the
|
|
* sidebar.
|
|
*/
|
|
export class HamburgerElement extends HTMLElement {
|
|
static readonly NAME = 'heap-hamburger';
|
|
|
|
createdCallback() {
|
|
this.appendChild(document.createTextNode('☰'));
|
|
this.onclick =
|
|
() => { this.dispatchEvent(new ActionEvent(Action.TOGGLE_SIDEBAR)) };
|
|
}
|
|
}
|
|
document.registerElement(HamburgerElement.NAME, HamburgerElement);
|
|
|
|
/**
|
|
* A heading for the page with a hamburger menu and a title.
|
|
*/
|
|
export class HeadingElement extends HTMLElement {
|
|
static readonly NAME = 'heap-heading';
|
|
|
|
createdCallback() {
|
|
this.style.display = 'block';
|
|
this.style.backgroundColor = '#2196F3';
|
|
this.style.webkitUserSelect = 'none';
|
|
this.style.cursor = 'default';
|
|
this.style.color = '#FFFFFF';
|
|
this.style.padding = '10px';
|
|
|
|
const div = document.createElement('div');
|
|
div.style.margin = '0px';
|
|
div.style.fontSize = '2em';
|
|
div.appendChild(document.createElement(HamburgerElement.NAME));
|
|
div.appendChild(document.createTextNode(' ' + TITLE));
|
|
this.appendChild(div);
|
|
}
|
|
}
|
|
document.registerElement(HeadingElement.NAME, HeadingElement);
|
|
|
|
/**
|
|
* A sidebar that has navigation for the app.
|
|
*/
|
|
export class SidebarElement extends HTMLElement {
|
|
static readonly NAME = 'heap-sidebar';
|
|
|
|
createdCallback() {
|
|
this.style.display = 'none';
|
|
this.style.backgroundColor = '#9E9E9E';
|
|
this.style.width = '15em';
|
|
|
|
const aboutButton = document.createElement('button');
|
|
aboutButton.innerText = 'about';
|
|
aboutButton.onclick =
|
|
() => { this.dispatchEvent(new ActionEvent(Action.NAVIGATE_ABOUT)) };
|
|
this.appendChild(aboutButton);
|
|
}
|
|
|
|
toggle() {
|
|
this.style.display = this.style.display === 'none' ? 'block' : 'none';
|
|
}
|
|
}
|
|
document.registerElement(SidebarElement.NAME, SidebarElement);
|
|
|
|
/**
|
|
* A Container for the main content in the app.
|
|
* TODO(matloob): Implement main content.
|
|
*/
|
|
export class MainContentElement extends HTMLElement {
|
|
static readonly NAME = 'heap-container';
|
|
|
|
attachedCallback() {
|
|
this.style.backgroundColor = '#E0E0E0';
|
|
this.style.height = '100%';
|
|
this.style.flex = '1';
|
|
}
|
|
}
|
|
document.registerElement(MainContentElement.NAME, MainContentElement);
|
|
|
|
/**
|
|
* A container and controller for the whole app.
|
|
* Contains the heading, side drawer and main panel.
|
|
*/
|
|
class AppElement extends HTMLElement {
|
|
static readonly NAME = 'heap-app';
|
|
private sidebar: SidebarElement;
|
|
private mainContent: MainContentElement;
|
|
|
|
attachedCallback() {
|
|
document.title = TITLE;
|
|
|
|
this.addEventListener(
|
|
ActionEvent.EVENT_TYPE, e => this.handleAction(e as ActionEvent),
|
|
/* capture */ true);
|
|
|
|
this.render();
|
|
}
|
|
|
|
render() {
|
|
this.style.display = 'block';
|
|
this.style.height = '100vh';
|
|
this.style.width = '100vw';
|
|
this.appendChild(document.createElement(HeadingElement.NAME));
|
|
|
|
const bodyDiv = document.createElement('div');
|
|
bodyDiv.style.height = '100%';
|
|
bodyDiv.style.display = 'flex';
|
|
this.sidebar =
|
|
document.createElement(SidebarElement.NAME) as SidebarElement;
|
|
bodyDiv.appendChild(this.sidebar);
|
|
this.mainContent =
|
|
document.createElement(MainContentElement.NAME) as MainContentElement;
|
|
bodyDiv.appendChild(this.mainContent);
|
|
this.appendChild(bodyDiv);
|
|
|
|
this.renderRoute();
|
|
}
|
|
|
|
renderRoute() {
|
|
this.mainContent.innerHTML = ''
|
|
switch (window.location.pathname) {
|
|
case '/about':
|
|
this.mainContent.appendChild(
|
|
document.createElement(AboutPageElement.NAME));
|
|
break;
|
|
}
|
|
}
|
|
|
|
handleAction(event: ActionEvent) {
|
|
switch (event.action) {
|
|
case Action.TOGGLE_SIDEBAR:
|
|
this.sidebar.toggle();
|
|
break;
|
|
case Action.NAVIGATE_ABOUT:
|
|
window.history.pushState({}, '', '/about');
|
|
this.renderRoute();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
document.registerElement(AppElement.NAME, AppElement);
|
|
|
|
/**
|
|
* An about page.
|
|
*/
|
|
class AboutPageElement extends HTMLElement {
|
|
static readonly NAME = 'heap-about';
|
|
|
|
createdCallback() { this.textContent = TITLE; }
|
|
}
|
|
document.registerElement(AboutPageElement.NAME, AboutPageElement);
|
|
|
|
/**
|
|
* Resets body's margin and padding, and sets font.
|
|
*/
|
|
function clearStyle(document: Document) {
|
|
const styleElement = document.createElement('style') as HTMLStyleElement;
|
|
document.head.appendChild(styleElement);
|
|
const styleSheet = styleElement.sheet as CSSStyleSheet;
|
|
styleSheet.insertRule(
|
|
'* {font-family: Roboto,Helvetica; box-sizing: border-box}', 0);
|
|
styleSheet.insertRule('body {margin: 0px; padding:0px}', 0);
|
|
}
|
|
|
|
export function main() {
|
|
clearStyle(document);
|
|
document.body.appendChild(document.createElement(AppElement.NAME));
|
|
}
|