UNPKG

@paperbits/core

Version:
158 lines (136 loc) 6.42 kB
import * as ko from "knockout"; import { View } from "@paperbits/common/ui"; import "@paperbits/common/extensions"; import { ISettingsProvider } from "@paperbits/common/configuration"; import { PositioningOptions } from "@paperbits/common/ui/positioningOptions"; interface EditorSettings { width: number; height: number; left: number; top: number; } export class SurfaceBindingHandler { constructor(private readonly localSettings: ISettingsProvider) { const initialize = this.initialize.bind(this); ko.bindingHandlers["surface"] = { init(element: HTMLElement, valueAccessor?: () => View): void { initialize(element, valueAccessor); } }; } private async initialize(element: HTMLElement, valueAccessor?: () => View): Promise<void> { const view = valueAccessor(); const editorSettings = await this.localSettings.getSetting<EditorSettings>(view.name); if (editorSettings) { if (Number.isInteger(editorSettings.width)) { element.style.width = editorSettings.width + "px"; } if (Number.isInteger(editorSettings.height)) { element.style.height = editorSettings.height + "px"; element.classList.add("resized-vertically"); } if (Number.isInteger(editorSettings.left)) { if (editorSettings.left + editorSettings.width > document.body.clientWidth) { editorSettings.left = document.body.clientWidth - editorSettings.width; } element.style.left = editorSettings.left + "px"; } if (Number.isInteger(editorSettings.top)) { if (editorSettings.top + editorSettings.height > document.body.clientHeight) { editorSettings.top = 10; } element.style.top = editorSettings.top + "px"; } } else { if (view.positioning) { let positioning: PositioningOptions; const defaultOffset = 20; const rect = element.getBoundingClientRect(); if (typeof view.positioning === "string") { switch (view.positioning) { case "left": positioning = { left: defaultOffset, top: (document.body.clientHeight / 2) - (rect.height / 2) }; break; case "right": positioning = { right: defaultOffset, top: (document.body.clientHeight / 2) - (rect.height / 2) }; break; case "top": positioning = { top: defaultOffset, left: (document.body.clientWidth / 2) - (rect.width / 2) }; break; case "bottom": positioning = { bottom: defaultOffset, left: (document.body.clientWidth / 2) - (rect.width / 2) }; break; case "center": positioning = { left: (document.body.clientWidth / 2) - (rect.width / 2), top: (document.body.clientHeight / 2) - (rect.height / 2) }; } } else { positioning = view.positioning as PositioningOptions; } element.style.left = (document.body.clientWidth / 2) - (rect.width / 2) + "px"; element.style.top = document.body.clientHeight / 2 - rect.height / 2 + "px"; element.style.left = positioning.left ? positioning.left + "px" : null; element.style.top = positioning.top ? positioning.top + "px" : null; element.style.right = positioning.right ? positioning.right + "px" : null; element.style.bottom = positioning.bottom ? positioning.bottom + "px" : null; } } ko.applyBindingsToNode(element, { dragsource: { sticky: false, sourceData: "surface", inertia: true, preventDragging: (clickedElement: HTMLElement) => { return clickedElement.closest("a, .form, .btn, .toolbox-btn, .toolbox-dropdown .cropbox") !== null; }, ondragend: async (): Promise<void> => { if (!view?.name) { return; } const rect = element.getBoundingClientRect(); await this.localSettings.setSetting(`${view.name}/top`, Math.floor(rect.top)); await this.localSettings.setSetting(`${view.name}/left`, Math.floor(rect.left)); } } }, null); let resizeDirections; if (typeof view.resizing === "string") { resizeDirections = view.resizing; } else { resizeDirections = view.resizing.directions; } ko.applyBindingsToNode(element, { resizable: { directions: resizeDirections, onresize: async (): Promise<void> => { if (!view?.name) { return; } if (resizeDirections.includes("horizontally")) { await this.localSettings.setSetting(`${view.name}/width`, element.clientWidth); } if (resizeDirections.includes("vertically")) { await this.localSettings.setSetting(`${view.name}/height`, element.clientHeight); } } } }, null); } }