Add event system
This commit is contained in:
parent
29e1546eb2
commit
5a87d2db71
15 changed files with 151 additions and 92 deletions
39
.idea/workspace.xml
generated
39
.idea/workspace.xml
generated
|
|
@ -2,33 +2,21 @@
|
|||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="8edc47ab-1265-4111-9771-536b24cc9310" name="Default Changelist" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/src/framework/page-event.ts" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/framework/page.ts" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/test.html" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/framework/element-factory.ts" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/framework/helper.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/framework/helper.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/framework/page-element.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/framework/page-element.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/about/about.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/background/background.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/background.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/content/content.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/content/content.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/footer/footer.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/index.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/about/about.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.html.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/about/about.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/about/about.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/content/content.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/content/content.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/content/content.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/content/content.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/footer/footer.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.html.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/footer/footer.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/footer/footer.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/image-viewer/image-viewer.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.html.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/image-viewer/image-viewer.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/image-viewer/image-viewer.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/main.html.ts" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/main.scss" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/main.ts" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/timeline/timeline-element/timeline-element.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.html.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/timeline/timeline-element/timeline-element.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/timeline/timeline-element/timeline-element.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/timeline/timeline.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline.html.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/timeline/timeline.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/main/timeline/timeline.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/static/favicon.ico" beforeDir="false" afterPath="$PROJECT_DIR$/src/static/no-change/favicon.ico" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/static/og-image.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/src/static/no-change/og-image.jpg" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/styles.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/styles.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/webpack.config.js" beforeDir="false" afterPath="$PROJECT_DIR$/webpack.config.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/page/timeline/timeline.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline.ts" afterDir="false" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
|
|
@ -115,6 +103,7 @@
|
|||
<workItem from="1577001408085" duration="15739000" />
|
||||
<workItem from="1577040021962" duration="1657000" />
|
||||
<workItem from="1577088438195" duration="19038000" />
|
||||
<workItem from="1577271824791" duration="6178000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
import { html } from "../model/misc";
|
||||
|
||||
export const createElement = (from: html): HTMLElement => {
|
||||
const element: HTMLElement = document.createElement("div");
|
||||
element.innerHTML = from;
|
||||
return element.firstElementChild as HTMLElement;
|
||||
};
|
||||
|
|
@ -1,31 +1,11 @@
|
|||
export const mixColorsToRGB = (
|
||||
hexColorA: string,
|
||||
hexColorB: string,
|
||||
qA: number
|
||||
): string => {
|
||||
const colorA = hexToRGB(hexColorA);
|
||||
const colorB = hexToRGB(hexColorB);
|
||||
const mixedColor: [number, number, number] = [
|
||||
colorA[0] * qA + colorB[0] * (1 - qA),
|
||||
colorA[1] * qA + colorB[1] * (1 - qA),
|
||||
colorA[2] * qA + colorB[2] * (1 - qA)
|
||||
];
|
||||
import { html } from "../model/misc";
|
||||
|
||||
return RGBToHex(mixedColor);
|
||||
export const createElement = (from: html): HTMLElement => {
|
||||
const element: HTMLElement = document.createElement("div");
|
||||
element.innerHTML = from;
|
||||
return element.firstElementChild as HTMLElement;
|
||||
};
|
||||
|
||||
const hexToRGB = (hex: string): [number, number, number] => {
|
||||
const [r1, r2, g1, g2, b1, b2] = hex;
|
||||
return [
|
||||
Number.parseInt(r1 + r2, 16),
|
||||
Number.parseInt(g1 + g2, 16),
|
||||
Number.parseInt(b1 + b2, 16)
|
||||
];
|
||||
};
|
||||
|
||||
const RGBToHex = (rgb: [number, number, number]): string =>
|
||||
rgb.map(n => Math.round(n).toString(16)).join("");
|
||||
|
||||
export const randomFactory = seed => () =>
|
||||
((2 ** 31 - 1) & (seed = Math.imul(48271, seed))) / 2 ** 31;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,32 @@
|
|||
import { PageEvent, PageEventType } from "./page-event";
|
||||
|
||||
export abstract class PageElement {
|
||||
private element: HTMLElement;
|
||||
|
||||
// Getter and setter accessors would have to agree in visibility
|
||||
public getElement(): HTMLElement {
|
||||
return this._element;
|
||||
return this.element;
|
||||
}
|
||||
private _element: HTMLElement;
|
||||
|
||||
protected setElement(value: HTMLElement) {
|
||||
this._element = value;
|
||||
this.element = value;
|
||||
}
|
||||
|
||||
protected eventGenerator: PageElement;
|
||||
|
||||
protected constructor(private children: Array<PageElement> = []) {}
|
||||
|
||||
public onAfterLoad(parent: HTMLElement) {
|
||||
this.children.forEach(c => c.onAfterLoad(this.getElement()));
|
||||
public giveEvent(event: PageEvent, parent: PageElement = null) {
|
||||
if (event.type === PageEventType.eventGeneratorChanged) {
|
||||
this.eventGenerator = event.data;
|
||||
}
|
||||
this.handleEvent(event, parent);
|
||||
this.children.forEach(c => c.giveEvent(event, this));
|
||||
}
|
||||
|
||||
protected query(query: string): HTMLElement | null {
|
||||
return this.getElement()?.querySelector(query);
|
||||
}
|
||||
|
||||
protected handleEvent(event: PageEvent, parent: PageElement) {}
|
||||
}
|
||||
|
|
|
|||
10
src/framework/page-event.ts
Normal file
10
src/framework/page-event.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export class PageEvent {
|
||||
type: PageEventType;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export enum PageEventType {
|
||||
onLoad,
|
||||
onBodyDimensionsChanged,
|
||||
eventGeneratorChanged
|
||||
}
|
||||
18
src/framework/page.ts
Normal file
18
src/framework/page.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { PageElement } from "./page-element";
|
||||
import { PageEventType } from "./page-event";
|
||||
|
||||
export class Page extends PageElement {
|
||||
public constructor(
|
||||
children: Array<PageElement>,
|
||||
private rootElement: HTMLElement
|
||||
) {
|
||||
super(children);
|
||||
this.setElement(rootElement);
|
||||
this.giveEvent(
|
||||
{ type: PageEventType.eventGeneratorChanged, data: this },
|
||||
this
|
||||
);
|
||||
rootElement.append(...children.map(e => e.getElement()));
|
||||
this.giveEvent({ type: PageEventType.onLoad }, this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { PageContent } from "../content/content";
|
||||
import { Header } from "../../model/portfolio";
|
||||
import { PageElement } from "../../framework/page-element";
|
||||
import { createElement } from "../../framework/element-factory";
|
||||
|
||||
import { generate } from "./about.html";
|
||||
import { createElement } from "../../framework/helper";
|
||||
|
||||
export class PageHeader extends PageElement {
|
||||
public constructor(header: Header, aPictureOf: string) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { PageElement } from "../../framework/page-element";
|
||||
import { createElement } from "../../framework/element-factory";
|
||||
import { generate } from "./background.html";
|
||||
import { createElement } from "../../framework/helper";
|
||||
import { PageEvent, PageEventType } from "../../framework/page-event";
|
||||
|
||||
export class PageBackground extends PageElement {
|
||||
public constructor(
|
||||
|
|
@ -16,4 +17,18 @@ export class PageBackground extends PageElement {
|
|||
createElement(generate(count, probability, width, color, translateZ))
|
||||
);
|
||||
}
|
||||
|
||||
protected handleEvent(event: PageEvent, parent: PageElement) {
|
||||
if (event.type === PageEventType.onLoad) {
|
||||
window.addEventListener("resize", this.resize.bind(this, parent));
|
||||
this.resize(parent);
|
||||
} else if (event.type === PageEventType.onBodyDimensionsChanged) {
|
||||
this.resize(parent);
|
||||
}
|
||||
}
|
||||
|
||||
private resize(parent: PageElement) {
|
||||
const width = parent.getElement().clientWidth;
|
||||
const height = parent.getElement().clientHeight;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Content, TypedContent } from "../../model/content";
|
||||
import "./content.scss";
|
||||
import { PageElement } from "../../framework/page-element";
|
||||
import { createElement } from "../../framework/element-factory";
|
||||
import { createElement } from "../../framework/helper";
|
||||
|
||||
export class PageContent extends PageElement {
|
||||
private static isTyped(content): content is TypedContent {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Footer } from "../../model/portfolio";
|
||||
import { PageElement } from "../../framework/page-element";
|
||||
import { createElement } from "../../framework/element-factory";
|
||||
|
||||
import { generate } from "./footer.html";
|
||||
import { createElement } from "../../framework/helper";
|
||||
|
||||
export class PageFooter extends PageElement {
|
||||
constructor(footer: Footer, cvName: string) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { createElement } from "../../framework/element-factory";
|
||||
import { PageElement } from "../../framework/page-element";
|
||||
|
||||
import { generate } from "./image-viewer.html";
|
||||
import { createElement } from "../../framework/helper";
|
||||
import { PageEvent, PageEventType } from "../../framework/page-event";
|
||||
|
||||
export class PageImageViewer extends PageElement {
|
||||
public constructor() {
|
||||
|
|
@ -12,12 +13,16 @@ export class PageImageViewer extends PageElement {
|
|||
this.setElement(root);
|
||||
}
|
||||
|
||||
public onAfterLoad(parent: HTMLElement) {
|
||||
super.onAfterLoad(parent);
|
||||
protected handleEvent(event: PageEvent, parent: PageElement) {
|
||||
if (event.type !== PageEventType.onLoad) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.body.addEventListener("keydown", this.handleKeydown.bind(this));
|
||||
|
||||
const images = Array.prototype.slice.call(parent.querySelectorAll("img"));
|
||||
const images = Array.prototype.slice.call(
|
||||
parent.getElement().querySelectorAll("img")
|
||||
);
|
||||
images
|
||||
.filter(
|
||||
(img: HTMLImageElement) => img.parentElement !== this.getElement()
|
||||
|
|
@ -28,7 +33,7 @@ export class PageImageViewer extends PageElement {
|
|||
}
|
||||
|
||||
private handleClick(event: Event) {
|
||||
(this.getElement().querySelector(
|
||||
(this.query(
|
||||
"#photo"
|
||||
) as HTMLImageElement).src = (event.target as HTMLImageElement).src;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +1,23 @@
|
|||
import { Portfolio } from "../model/portfolio";
|
||||
import { PageElement } from "../framework/page-element";
|
||||
import { PageBackground } from "./background/background";
|
||||
import { PageHeader } from "./about/about";
|
||||
import { PageTimeline } from "./timeline/timeline";
|
||||
import { PageFooter } from "./footer/footer";
|
||||
import { PageImageViewer } from "./image-viewer/image-viewer";
|
||||
import { Page } from "../framework/page";
|
||||
|
||||
export const create = ({ config, header, timeline, footer }: Portfolio) => {
|
||||
document.title = header.name;
|
||||
|
||||
const pageElements: Array<PageElement> = [
|
||||
new PageBackground(0.1, 200, 140, 0.4, "#fff9e0aa", -15),
|
||||
new PageBackground(0.15, 300, 80, 0.3, "#ffd6d6aa", -10),
|
||||
new PageHeader(header, config.aPictureOf),
|
||||
new PageTimeline(timeline, config.showMore, config.showLess),
|
||||
new PageFooter(footer, config.cvName),
|
||||
new PageImageViewer()
|
||||
];
|
||||
|
||||
const root = document.body.querySelector("main");
|
||||
root.append(...pageElements.map(e => e.getElement()));
|
||||
pageElements.forEach(e => e.onAfterLoad(root));
|
||||
new Page(
|
||||
[
|
||||
new PageBackground(0.1, 200, 140, 0.4, "#fff9e0aa", -15),
|
||||
new PageBackground(0.15, 300, 80, 0.3, "#ffd6d6aa", -10),
|
||||
new PageHeader(header, config.aPictureOf),
|
||||
new PageTimeline(timeline, config.showMore, config.showLess),
|
||||
new PageFooter(footer, config.cvName),
|
||||
new PageImageViewer()
|
||||
],
|
||||
document.body.querySelector("main")
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { TimelineElement } from "../../../model/portfolio";
|
||||
import { PageContent } from "../../content/content";
|
||||
import { PageElement } from "../../../framework/page-element";
|
||||
import { createElement } from "../../../framework/element-factory";
|
||||
import { generate } from "./timeline-element.html";
|
||||
import { createElement } from "../../../framework/helper";
|
||||
import { PageEventType } from "../../../framework/page-event";
|
||||
|
||||
export class PageTimelineElement extends PageElement {
|
||||
private isOpen;
|
||||
|
|
@ -30,12 +31,8 @@ export class PageTimelineElement extends PageElement {
|
|||
}
|
||||
|
||||
private toggleOpen() {
|
||||
const showMore = this.getElement().querySelector(
|
||||
"#show-more"
|
||||
) as HTMLElement;
|
||||
const showLess = this.getElement().querySelector(
|
||||
"#show-less"
|
||||
) as HTMLElement;
|
||||
const showMore = this.query("#show-more") as HTMLElement;
|
||||
const showLess = this.query("#show-less") as HTMLElement;
|
||||
if (this.isOpen) {
|
||||
this.more.style.height = "0";
|
||||
PageTimelineElement.show(showMore);
|
||||
|
|
@ -47,6 +44,9 @@ export class PageTimelineElement extends PageElement {
|
|||
}
|
||||
|
||||
this.isOpen = !this.isOpen;
|
||||
this.eventGenerator?.giveEvent({
|
||||
type: PageEventType.onBodyDimensionsChanged
|
||||
});
|
||||
}
|
||||
|
||||
private static hide(element: HTMLElement) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { TimelineElement } from "../../model/portfolio";
|
||||
import { PageElement } from "../../framework/page-element";
|
||||
import { createElement } from "../../framework/element-factory";
|
||||
import { PageTimelineElement } from "./timeline-element/timeline-element";
|
||||
import { generate } from "./timeline.html";
|
||||
import { createElement } from "../../framework/helper";
|
||||
|
||||
export class PageTimeline extends PageElement {
|
||||
public constructor(
|
||||
|
|
|
|||
34
src/test.html
Normal file
34
src/test.html
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>Portfolio</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
main {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.absolute {
|
||||
position: absolute;
|
||||
height: 200vh;
|
||||
width: 100%;
|
||||
z-index: -1;
|
||||
background: rebeccapurple;
|
||||
}
|
||||
.static {
|
||||
height: 150vh;
|
||||
background: rgba(255, 255, 0, 0.5);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="absolute"></div>
|
||||
<div class="static"></div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue