diff --git a/src/abstract/View.ts b/src/abstract/View.ts index f1aaa9170..a52d6ee93 100644 --- a/src/abstract/View.ts +++ b/src/abstract/View.ts @@ -1,19 +1,28 @@ -import Backbone from 'backbone'; -import Model from './Model'; +import Backbone from "backbone"; +import Model from "./Model"; +import Module, { IBaseModule } from "./Module"; export default class View< TModel extends Model = Model, TElement extends Element = HTMLElement > extends Backbone.View { protected get pfx() { - return (this.model.module.em.config as any).stylePrefix || ''; + return (this.model.em.config as any).stylePrefix || ""; } protected get ppfx() { - return this.pfx + this.model.module.config.stylePrefix || ''; + return this.pfx + this.config.stylePrefix || ""; + } + + protected get module(): TModel extends Model? M: unknown { + return this.model.module as any; } protected get em() { - return this.model.module.em; + return this.model.em; + } + + protected get config(): TModel extends Model ? (M extends IBaseModule ? C : unknown) : unknown{ + return this.module.config as any } } diff --git a/src/canvas/view/CanvasView.js b/src/canvas/view/CanvasView.ts similarity index 68% rename from src/canvas/view/CanvasView.js rename to src/canvas/view/CanvasView.ts index 0fe6aa4d7..7994e0404 100644 --- a/src/canvas/view/CanvasView.js +++ b/src/canvas/view/CanvasView.ts @@ -1,12 +1,26 @@ import { bindAll } from 'underscore'; -import { View } from '../../common'; +import { View } from '../../abstract'; import { on, off, getElement, getKeyChar, isTextNode, getElRect, getUiClass } from '../../utils/mixins'; import { createEl } from '../../utils/dom'; import FramesView from './FramesView'; - -let timerZoom; - -export default class CanvasView extends View { +import Canvas from '../model/Canvas'; +import Frame from '../model/Frame'; +import FrameView from './FrameView'; +import Components from '../../dom_components/model/Components'; +import ComponentView from '../../dom_components/view/ComponentView'; +import Component from '../../dom_components/model/Component'; + +interface MarginPaddingOffsets{ + marginTop?: number, + marginRight?: number, + marginBottom?: number, + marginLeft?: number, + paddingTop?: number, + paddingRight?: number, + paddingBottom?: number, + paddingLeft?: number, + } +export default class CanvasView extends View { events() { return { wheel: 'onWheel', @@ -20,23 +34,42 @@ export default class CanvasView extends View {
`; } - - constructor(o) { - super(o); + /*get className(){ + return this.pfx + 'canvas': + }*/ + hlEl?: HTMLElement; + badgeEl?: HTMLElement; + placerEl?: HTMLElement; + ghostEl?: HTMLElement; + toolbarEl?: HTMLElement; + resizerEl?: HTMLElement; + offsetEl?: HTMLElement; + fixedOffsetEl?: HTMLElement; + toolsGlobEl?: HTMLElement; + toolsEl?: HTMLElement; + framesArea?: HTMLElement; + toolsWrapper?: HTMLElement; + ready = false; + + frames!: FramesView; + frame?: FrameView; + + private timerZoom?: number + + private frmOff?: {top: number, left: number, width: number, height: number} + private cvsOff?: {top: number, left: number, width: number, height: number} + + constructor(model: Canvas) { + super({model}); bindAll(this, 'clearOff', 'onKeyPress', 'onCanvasMove'); - const { model } = this; - this.config = o.config || {}; - this.em = this.model.em || {}; - this.pfx = this.config.stylePrefix || ''; - this.ppfx = this.config.pStylePrefix || ''; - this.className = this.config.stylePrefix + 'canvas'; + this.className = this.pfx + 'canvas'; const { em } = this; this._initFrames(); this.listenTo(em, 'change:canvasOffset', this.clearOff); this.listenTo(em, 'component:selected', this.checkSelected); this.listenTo(model, 'change:zoom change:x change:y', this.updateFrames); this.listenTo(model, 'change:frames', this._onFramesUpdate); - this.toggleListeners(1); + this.toggleListeners(true); } _onFramesUpdate() { @@ -49,7 +82,7 @@ export default class CanvasView extends View { const collection = model.get('frames'); em.set('readyCanvas', 0); collection.once('loaded:all', () => em.set('readyCanvas', 1)); - frames && frames.remove(); + frames?.remove(); this.frames = new FramesView({ collection, config: { @@ -59,38 +92,40 @@ export default class CanvasView extends View { }); } - checkSelected(component, opts = {}) { + checkSelected(component: Component, opts: any = {}) { const { scroll } = opts; const currFrame = this.em.get('currentFrame'); - scroll && - component.views.forEach(view => { + scroll && component.views?.forEach(view => { view._getFrame() === currFrame && view.scrollIntoView(scroll); }); } - remove() { - this.frames.remove(); - this.frames = {}; - View.prototype.remove.apply(this, arguments); - this.toggleListeners(); + remove(...args: any) { + this.frames?.remove(); + //@ts-ignore + this.frames = undefined; + View.prototype.remove.apply(this, args); + this.toggleListeners(false); + return this } - preventDefault(ev) { + preventDefault(ev: Event) { if (ev) { ev.preventDefault(); - ev._parentEvent && ev._parentEvent.preventDefault(); + //@ts-ignore + ev._parentEvent?.preventDefault(); } } - onCanvasMove(ev) { + onCanvasMove(ev: Event) { // const data = { x: ev.clientX, y: ev.clientY }; // const data2 = this.em.get('Canvas').getMouseRelativeCanvas(ev); // const data3 = this.em.get('Canvas').getMouseRelativePos(ev); // this.em.trigger('canvas:over', data, data2, data3); } - toggleListeners(enable) { + toggleListeners(enable: boolean) { const { el } = this; const fn = enable ? on : off; fn(document, 'keypress', this.onKeyPress); @@ -98,7 +133,7 @@ export default class CanvasView extends View { // fn(el, 'mousemove dragover', this.onCanvasMove); } - onKeyPress(ev) { + onKeyPress(ev: Event) { const { em } = this; const key = getKeyChar(ev); @@ -108,28 +143,30 @@ export default class CanvasView extends View { } } - onWheel(ev) { + onWheel(ev: KeyboardEvent) { if ((ev.ctrlKey || ev.metaKey) && this.em.getConfig().multiFrames) { this.preventDefault(ev); const { model } = this; + //@ts-ignore this is potentially deprecated const delta = Math.max(-1, Math.min(1, ev.wheelDelta || -ev.detail)); const zoom = model.get('zoom'); model.set('zoom', zoom + delta * 2); } } - updateFrames(ev) { + updateFrames(ev: Event) { const { em, model } = this; const { x, y } = model.attributes; const zoom = this.getZoom(); const defOpts = { preserveSelected: 1 }; const mpl = zoom ? 1 / zoom : 1; + //@ts-ignore this.framesArea.style.transform = `scale(${zoom}) translate(${x * mpl}px, ${y * mpl}px)`; this.clearOff(); em.stopDefault(defOpts); em.trigger('canvas:update', ev); - timerZoom && clearTimeout(timerZoom); - timerZoom = setTimeout(() => em.runDefault(defOpts), 300); + this.timerZoom && clearTimeout(this.timerZoom); + this.timerZoom = setTimeout(() => em.runDefault(defOpts), 300) as any; } getZoom() { @@ -141,7 +178,7 @@ export default class CanvasView extends View { * @param {HTMLElement} el * @return {Boolean} */ - isElInViewport(el) { + isElInViewport(el: HTMLElement) { const elem = getElement(el); const rect = getElRect(elem); const frameRect = this.getFrameOffset(elem); @@ -155,14 +192,14 @@ export default class CanvasView extends View { * @param {HTMLElement} el * @return { {top: number, left: number, width: number, height: number} } */ - offset(el, opts = {}) { + offset(el?: HTMLElement, opts: any = {}) { const rect = getElRect(el); - const docBody = el.ownerDocument.body; + const docBody = el?.ownerDocument.body; const { noScroll } = opts; return { - top: rect.top + (noScroll ? 0 : docBody.scrollTop), - left: rect.left + (noScroll ? 0 : docBody.scrollLeft), + top: rect.top + (noScroll ? 0 : docBody?.scrollTop ?? 0), + left: rect.left + (noScroll ? 0 : docBody?.scrollLeft ?? 0), width: rect.width, height: rect.height, }; @@ -173,8 +210,8 @@ export default class CanvasView extends View { * @private */ clearOff() { - this.frmOff = null; - this.cvsOff = null; + this.frmOff = undefined; + this.cvsOff = undefined; } /** @@ -182,11 +219,11 @@ export default class CanvasView extends View { * @return { {top: number, left: number, width: number, height: number} } * @public */ - getFrameOffset(el) { + getFrameOffset(el?: HTMLElement) { if (!this.frmOff || el) { - const frame = this.frame.el; - const winEl = el && el.ownerDocument.defaultView; - const frEl = winEl ? winEl.frameElement : frame; + const frame = this.frame?.el; + const winEl = el?.ownerDocument.defaultView; + const frEl = winEl ? winEl.frameElement as HTMLElement : frame; this.frmOff = this.offset(frEl || frame); } return this.frmOff; @@ -208,7 +245,7 @@ export default class CanvasView extends View { * @return { {top: number, left: number, width: number, height: number, zoom: number, rect: any} } * @public */ - getElementPos(el, opts = {}) { + getElementPos(el: HTMLElement, opts: any = {}) { const zoom = this.getZoom(); const opt = opts || {}; const frameOffset = this.getFrameOffset(el); @@ -229,21 +266,14 @@ export default class CanvasView extends View { /** * Returns element's offsets like margins and paddings * @param {HTMLElement} el - * @return {{ marginTop: number, - * marginRight: number, - * marginBottom: number, - * marginLeft: number, - * paddingTop: number, - * paddingRight: number, - * paddingBottom: number, - * paddingLeft: number,}} + * @return { MarginPaddingOffsets } * @public */ - getElementOffsets(el) { + getElementOffsets(el: HTMLElement) { if (!el || isTextNode(el)) return {}; - const result = {}; + const result: MarginPaddingOffsets = {} ; const styles = window.getComputedStyle(el); - [ + const marginPaddingOffsets: (keyof MarginPaddingOffsets)[] =[ 'marginTop', 'marginRight', 'marginBottom', @@ -252,7 +282,8 @@ export default class CanvasView extends View { 'paddingRight', 'paddingBottom', 'paddingLeft', - ].forEach(offset => { + ] + marginPaddingOffsets.forEach(offset => { result[offset] = parseFloat(styles[offset]) * this.getZoom(); }); @@ -264,8 +295,9 @@ export default class CanvasView extends View { * @return { {top: number, left: number, width: number, height: number} } obj Position object * @public */ - getPosition(opts = {}) { - const doc = this.frame.el.contentDocument; + getPosition(opts: any = {}) { + + const doc = this.frame?.el.contentDocument; if (!doc) return; const bEl = doc.body; const zoom = this.getZoom(); @@ -286,7 +318,8 @@ export default class CanvasView extends View { * @param {View} view Component's View * @private */ - updateScript(view) { + //TODO change type after the ComponentView was updated to ts + updateScript(view: any) { const model = view.model; const id = model.getId(); @@ -321,25 +354,25 @@ export default class CanvasView extends View { * Get javascript container * @private */ - getJsContainer(view) { + getJsContainer(view?: ComponentView) { const frameView = this.getFrameView(view); return frameView && frameView.getJsContainer(); } - getFrameView(view) { - return (view && view._getFrame()) || this.em.get('currentFrame'); + getFrameView(view?: ComponentView) { + return view?._getFrame() || this.em.get('currentFrame'); } _renderFrames() { if (!this.ready) return; const { model, frames, em, framesArea } = this; - const frms = model.get('frames'); + const frms = model.frames; frms.listenToLoad(); frames.render(); const mainFrame = frms.at(0); - const currFrame = mainFrame && mainFrame.view; + const currFrame = mainFrame?.view; em.setCurrentFrame(currFrame); - framesArea && framesArea.appendChild(frames.el); + framesArea?.appendChild(frames.el); this.frame = currFrame; } @@ -368,18 +401,18 @@ export default class CanvasView extends View { `); const toolsEl = el.querySelector(`#${ppfx}tools`); - this.hlEl = el.querySelector(`.${ppfx}highlighter`); - this.badgeEl = el.querySelector(`.${ppfx}badge`); - this.placerEl = el.querySelector(`.${ppfx}placeholder`); - this.ghostEl = el.querySelector(`.${ppfx}ghost`); - this.toolbarEl = el.querySelector(`.${ppfx}toolbar`); - this.resizerEl = el.querySelector(`.${ppfx}resizer`); - this.offsetEl = el.querySelector(`.${ppfx}offset-v`); - this.fixedOffsetEl = el.querySelector(`.${ppfx}offset-fixed-v`); - this.toolsGlobEl = el.querySelector(`.${ppfx}tools-gl`); - this.toolsEl = toolsEl; + this.hlEl = el.querySelector(`.${ppfx}highlighter`) as HTMLElement; + this.badgeEl = el.querySelector(`.${ppfx}badge`) as HTMLElement; + this.placerEl = el.querySelector(`.${ppfx}placeholder`) as HTMLElement; + this.ghostEl = el.querySelector(`.${ppfx}ghost`) as HTMLElement; + this.toolbarEl = el.querySelector(`.${ppfx}toolbar`) as HTMLElement; + this.resizerEl = el.querySelector(`.${ppfx}resizer`) as HTMLElement; + this.offsetEl = el.querySelector(`.${ppfx}offset-v`) as HTMLElement; + this.fixedOffsetEl = el.querySelector(`.${ppfx}offset-fixed-v`) as HTMLElement; + this.toolsGlobEl = el.querySelector(`.${ppfx}tools-gl`) as HTMLElement; + this.toolsEl = toolsEl as HTMLElement; this.el.className = getUiClass(em, this.className); - this.ready = 1; + this.ready = true; this._renderFrames(); return this; diff --git a/src/editor/model/Editor.ts b/src/editor/model/Editor.ts index 30008da67..4c192ea0c 100644 --- a/src/editor/model/Editor.ts +++ b/src/editor/model/Editor.ts @@ -822,8 +822,8 @@ export default class EditorModel extends Model { return this.get('DomComponents').getWrapper(); } - setCurrentFrame(frameView: FrameView) { - return this.set('currentFrame', frameView); + setCurrentFrame(frameView?: FrameView) { + return this.set("currentFrame", frameView); } getCurrentFrame(): FrameView { diff --git a/src/utils/dom.js b/src/utils/dom.js index 01d718649..2e5b5f993 100644 --- a/src/utils/dom.js +++ b/src/utils/dom.js @@ -5,8 +5,7 @@ const KEY_TAG = 'tag'; const KEY_ATTR = 'attributes'; const KEY_CHILD = 'children'; -export const motionsEv = - 'transitionend oTransitionEnd transitionend webkitTransitionEnd'; +export const motionsEv = 'transitionend oTransitionEnd transitionend webkitTransitionEnd'; export const isDoc = el => el && el.nodeType === 9; @@ -18,14 +17,10 @@ export const removeEl = el => { export const find = (el, query) => el.querySelectorAll(query); export const attrUp = (el, attrs = {}) => - el && - el.setAttribute && - each(attrs, (value, key) => el.setAttribute(key, value)); + el && el.setAttribute && each(attrs, (value, key) => el.setAttribute(key, value)); export const isVisible = el => { - return ( - el && !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length) - ); + return el && !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length); }; export const empty = node => { @@ -56,7 +51,7 @@ export const appendAtIndex = (parent, child, index) => { export const append = (parent, child) => appendAtIndex(parent, child); -export const createEl = (tag, attrs = '', child) => { +export const createEl = (tag, attrs = {}, child) => { const el = document.createElement(tag); attrs && each(attrs, (value, key) => el.setAttribute(key, value)); @@ -90,7 +85,7 @@ export const createCustomEvent = (e, cls) => { Object.defineProperty(oEvent, prop, { get() { return this.keyCodeVal; - } + }, }); }); }