diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 3c441b0..1b04fa9 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,33 +2,21 @@ + + + - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/src/framework/element-factory.ts b/src/framework/element-factory.ts deleted file mode 100644 index d2b13c1..0000000 --- a/src/framework/element-factory.ts +++ /dev/null @@ -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; -}; diff --git a/src/framework/helper.ts b/src/framework/helper.ts index b455e47..d50eb1a 100644 --- a/src/framework/helper.ts +++ b/src/framework/helper.ts @@ -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; diff --git a/src/framework/page-element.ts b/src/framework/page-element.ts index 9880ea7..421a8e4 100644 --- a/src/framework/page-element.ts +++ b/src/framework/page-element.ts @@ -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 = []) {} - 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) {} } diff --git a/src/framework/page-event.ts b/src/framework/page-event.ts new file mode 100644 index 0000000..d5fceb3 --- /dev/null +++ b/src/framework/page-event.ts @@ -0,0 +1,10 @@ +export class PageEvent { + type: PageEventType; + data?: any; +} + +export enum PageEventType { + onLoad, + onBodyDimensionsChanged, + eventGeneratorChanged +} diff --git a/src/framework/page.ts b/src/framework/page.ts new file mode 100644 index 0000000..433d426 --- /dev/null +++ b/src/framework/page.ts @@ -0,0 +1,18 @@ +import { PageElement } from "./page-element"; +import { PageEventType } from "./page-event"; + +export class Page extends PageElement { + public constructor( + children: Array, + 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); + } +} diff --git a/src/page/about/about.ts b/src/page/about/about.ts index f50c8fc..1d7c751 100644 --- a/src/page/about/about.ts +++ b/src/page/about/about.ts @@ -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) { diff --git a/src/page/background/background.ts b/src/page/background/background.ts index ba5229c..20628b1 100644 --- a/src/page/background/background.ts +++ b/src/page/background/background.ts @@ -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; + } } diff --git a/src/page/content/content.ts b/src/page/content/content.ts index c8e528a..779ec11 100644 --- a/src/page/content/content.ts +++ b/src/page/content/content.ts @@ -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 { diff --git a/src/page/footer/footer.ts b/src/page/footer/footer.ts index cebfbcb..1d2d578 100644 --- a/src/page/footer/footer.ts +++ b/src/page/footer/footer.ts @@ -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) { diff --git a/src/page/image-viewer/image-viewer.ts b/src/page/image-viewer/image-viewer.ts index 4963562..24f0f3a 100644 --- a/src/page/image-viewer/image-viewer.ts +++ b/src/page/image-viewer/image-viewer.ts @@ -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; diff --git a/src/page/index.ts b/src/page/index.ts index a95e876..1debb52 100644 --- a/src/page/index.ts +++ b/src/page/index.ts @@ -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 = [ - 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") + ); }; diff --git a/src/page/timeline/timeline-element/timeline-element.ts b/src/page/timeline/timeline-element/timeline-element.ts index 8de2c49..17def56 100644 --- a/src/page/timeline/timeline-element/timeline-element.ts +++ b/src/page/timeline/timeline-element/timeline-element.ts @@ -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) { diff --git a/src/page/timeline/timeline.ts b/src/page/timeline/timeline.ts index ff70ac5..82123b2 100644 --- a/src/page/timeline/timeline.ts +++ b/src/page/timeline/timeline.ts @@ -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( diff --git a/src/test.html b/src/test.html new file mode 100644 index 0000000..b60be97 --- /dev/null +++ b/src/test.html @@ -0,0 +1,34 @@ + + + + + + Portfolio + + + +
+
+
+
+ +