Browse Source

Refactore canvas files to classes

pull/4234/head
Artur Arseniev 5 years ago
parent
commit
012b5a1c27
  1. 2
      src/canvas/index.js
  2. 4
      src/canvas/model/Canvas.js
  3. 4
      src/canvas/model/Frame.js
  4. 6
      src/canvas/model/Frames.js
  5. 116
      src/canvas/view/CanvasView.js
  6. 99
      src/canvas/view/FrameView.js
  7. 77
      src/canvas/view/FrameWrapView.js
  8. 2
      src/canvas/view/FramesView.js
  9. 3
      src/dom_components/view/ComponentsView.js

2
src/canvas/index.js

@ -48,7 +48,7 @@
*/
import { isUndefined } from 'underscore';
import { getElement, getViewEl } from 'utils/mixins';
import { getElement, getViewEl } from '../utils/mixins';
import defaults from './config/config';
import Canvas from './model/Canvas';
import canvasView from './view/CanvasView';

4
src/canvas/model/Canvas.js

@ -1,5 +1,5 @@
import { Model } from 'common';
import { evPageSelect } from 'pages';
import { Model } from '../../common';
import { evPageSelect } from '../../pages';
import Frames from './Frames';
export default class Canvas extends Model {

4
src/canvas/model/Frame.js

@ -1,6 +1,6 @@
import { Model } from 'common';
import { result, forEach, isEmpty, isString } from 'underscore';
import { isComponent, isObject } from 'utils/mixins';
import { Model } from '../../common';
import { isComponent, isObject } from '../../utils/mixins';
const keyAutoW = '__aw';
const keyAutoH = '__ah';

6
src/canvas/model/Frames.js

@ -1,6 +1,6 @@
import { bindAll } from 'underscore';
import { Collection } from 'common';
import model from './Frame';
import { Collection } from '../../common';
import Frame from './Frame';
export default class Frames extends Collection {
initialize(models, config = {}) {
@ -44,4 +44,4 @@ export default class Frames extends Collection {
}
}
Frames.prototype.model = model;
Frames.prototype.model = Frame;

116
src/canvas/view/CanvasView.js

@ -1,23 +1,17 @@
import Backbone from 'backbone';
import { bindAll } from 'underscore';
import {
on,
off,
getElement,
getKeyChar,
isTextNode,
getElRect,
getUiClass
} from 'utils/mixins';
import { View } from '../../common';
import { on, off, getElement, getKeyChar, isTextNode, getElRect, getUiClass } from '../../utils/mixins';
import { createEl } from '../../utils/dom';
import FramesView from './FramesView';
const $ = Backbone.$;
let timerZoom;
export default Backbone.View.extend({
events: {
wheel: 'onWheel'
},
export default class CanvasView extends View {
events() {
return {
wheel: 'onWheel',
};
}
template() {
const { pfx } = this;
@ -25,7 +19,7 @@ export default Backbone.View.extend({
<div class="${pfx}canvas__frames" data-frames></div>
<div id="${pfx}tools" class="${pfx}canvas__tools" data-tools></div>
`;
},
}
initialize(o) {
bindAll(this, 'clearOff', 'onKeyPress', 'onCanvasMove');
@ -42,12 +36,12 @@ export default Backbone.View.extend({
this.listenTo(model, 'change:zoom change:x change:y', this.updateFrames);
this.listenTo(model, 'change:frames', this._onFramesUpdate);
this.toggleListeners(1);
},
}
_onFramesUpdate() {
this._initFrames();
this._renderFrames();
},
}
_initFrames() {
const { frames, model, config, em } = this;
@ -59,10 +53,10 @@ export default Backbone.View.extend({
collection,
config: {
...config,
canvasView: this
}
canvasView: this,
},
});
},
}
checkSelected(component, opts = {}) {
const { scroll } = opts;
@ -72,28 +66,28 @@ export default Backbone.View.extend({
component.views.forEach(view => {
view._getFrame() === currFrame && view.scrollIntoView(scroll);
});
},
}
remove() {
this.frames.remove();
this.frames = {};
Backbone.View.prototype.remove.apply(this, arguments);
View.prototype.remove.apply(this, arguments);
this.toggleListeners();
},
}
preventDefault(ev) {
if (ev) {
ev.preventDefault();
ev._parentEvent && ev._parentEvent.preventDefault();
}
},
}
onCanvasMove(ev) {
// 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) {
const { el } = this;
@ -101,21 +95,17 @@ export default Backbone.View.extend({
fn(document, 'keypress', this.onKeyPress);
fn(window, 'scroll resize', this.clearOff);
// fn(el, 'mousemove dragover', this.onCanvasMove);
},
}
onKeyPress(ev) {
const { em } = this;
const key = getKeyChar(ev);
if (
key === ' ' &&
em.getZoomDecimal() !== 1 &&
!em.get('Canvas').isInputFocused()
) {
if (key === ' ' && em.getZoomDecimal() !== 1 && !em.get('Canvas').isInputFocused()) {
this.preventDefault(ev);
em.get('Editor').runCommand('core:canvas-move');
}
},
}
onWheel(ev) {
if ((ev.ctrlKey || ev.metaKey) && this.em.getConfig('multiFrames')) {
@ -125,7 +115,7 @@ export default Backbone.View.extend({
const zoom = model.get('zoom');
model.set('zoom', zoom + delta * 2);
}
},
}
updateFrames(ev) {
const { em, model } = this;
@ -133,18 +123,17 @@ export default Backbone.View.extend({
const zoom = this.getZoom();
const defOpts = { preserveSelected: 1 };
const mpl = zoom ? 1 / zoom : 1;
this.framesArea.style.transform = `scale(${zoom}) translate(${x *
mpl}px, ${y * mpl}px)`;
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);
},
}
getZoom() {
return this.em.getZoomDecimal();
},
}
/**
* Checks if the element is visible in the canvas's viewport
@ -157,13 +146,8 @@ export default Backbone.View.extend({
const frameRect = this.getFrameOffset(elem);
const rTop = rect.top;
const rLeft = rect.left;
return (
rTop >= 0 &&
rLeft >= 0 &&
rTop <= frameRect.height &&
rLeft <= frameRect.width
);
},
return rTop >= 0 && rLeft >= 0 && rTop <= frameRect.height && rLeft <= frameRect.width;
}
/**
* Get the offset of the element
@ -179,9 +163,9 @@ export default Backbone.View.extend({
top: rect.top + (noScroll ? 0 : docBody.scrollTop),
left: rect.left + (noScroll ? 0 : docBody.scrollLeft),
width: rect.width,
height: rect.height
height: rect.height,
};
},
}
/**
* Cleare cached offsets
@ -190,7 +174,7 @@ export default Backbone.View.extend({
clearOff() {
this.frmOff = null;
this.cvsOff = null;
},
}
/**
* Return frame offset
@ -205,7 +189,7 @@ export default Backbone.View.extend({
this.frmOff = this.offset(frEl || frame);
}
return this.frmOff;
},
}
/**
* Return canvas offset
@ -215,7 +199,7 @@ export default Backbone.View.extend({
getCanvasOffset() {
if (!this.cvsOff) this.cvsOff = this.offset(this.el);
return this.cvsOff;
},
}
/**
* Returns element's rect info
@ -239,7 +223,7 @@ export default Backbone.View.extend({
const width = eo.width * zoom;
return { top, left, height, width, zoom, rect: eo };
},
}
/**
* Returns element's offsets like margins and paddings
@ -259,13 +243,13 @@ export default Backbone.View.extend({
'paddingTop',
'paddingRight',
'paddingBottom',
'paddingLeft'
'paddingLeft',
].forEach(offset => {
result[offset] = parseFloat(styles[offset]) * this.getZoom();
});
return result;
},
}
/**
* Returns position data of the canvas element
@ -285,9 +269,9 @@ export default Backbone.View.extend({
top: fo.top + (noScroll ? 0 : bEl.scrollTop) * zoom - co.top,
left: fo.left + (noScroll ? 0 : bEl.scrollLeft) * zoom - co.left,
width: co.width,
height: co.height
height: co.height,
};
},
}
/**
* Update javascript of a specific component passed by its View
@ -299,19 +283,17 @@ export default Backbone.View.extend({
const id = model.getId();
if (!view.scriptContainer) {
view.scriptContainer = $(`<div data-id="${id}">`);
this.getJsContainer().appendChild(view.scriptContainer.get(0));
view.scriptContainer = createEl('div', { 'data-id': id });
this.getJsContainer().appendChild(view.scriptContainer);
}
view.el.id = id;
view.scriptContainer.html('');
view.scriptContainer.innerHTML = '';
// In editor, I make use of setTimeout as during the append process of elements
// those will not be available immediately, therefore 'item' variable
const script = document.createElement('script');
const scriptFn = model.getScriptString();
const scriptFnStr = model.get('script-props')
? scriptFn
: `function(){\n${scriptFn}\n;}`;
const scriptFnStr = model.get('script-props') ? scriptFn : `function(){\n${scriptFn}\n;}`;
const scriptProps = JSON.stringify(model.__getScriptProps());
script.innerHTML = `
setTimeout(function() {
@ -323,9 +305,9 @@ export default Backbone.View.extend({
// Adding setTimeout will make js components work on init of the editor
setTimeout(() => {
const scr = view.scriptContainer;
scr && scr.get(0).appendChild(script);
scr?.appendChild(script);
}, 0);
},
}
/**
* Get javascript container
@ -334,11 +316,11 @@ export default Backbone.View.extend({
getJsContainer(view) {
const frameView = this.getFrameView(view);
return frameView && frameView.getJsContainer();
},
}
getFrameView(view) {
return (view && view._getFrame()) || this.em.get('currentFrame');
},
}
_renderFrames() {
if (!this.ready) return;
@ -351,7 +333,7 @@ export default Backbone.View.extend({
em.setCurrentFrame(currFrame);
framesArea && framesArea.appendChild(frames.el);
this.frame = currFrame;
},
}
render() {
const { el, $el, ppfx, config, em } = this;
@ -394,4 +376,4 @@ export default Backbone.View.extend({
return this;
}
});
}

99
src/canvas/view/FrameView.js

@ -1,17 +1,21 @@
import Backbone from 'backbone';
import { bindAll, isString, debounce, isUndefined } from 'underscore';
import CssRulesView from 'css_composer/view/CssRulesView';
import Droppable from 'utils/Droppable';
import { appendVNodes, append, createEl, createCustomEvent, motionsEv } from 'utils/dom';
import { on, off, setViewEl, hasDnd, getPointerEvent } from 'utils/mixins';
export default Backbone.View.extend({
tagName: 'iframe',
attributes: {
allowfullscreen: 'allowfullscreen',
'data-frame-el': true,
},
import { appendVNodes, append, createEl, createCustomEvent, motionsEv } from '../../utils/dom';
import { on, off, setViewEl, hasDnd, getPointerEvent } from '../../utils/mixins';
import { View } from '../../common';
import CssRulesView from '../../css_composer/view/CssRulesView';
import Droppable from '../../utils/Droppable';
export default class FrameView extends View {
tagName() {
return 'iframe';
}
attributes() {
return {
allowfullscreen: 'allowfullscreen',
'data-frame-el': true,
};
}
initialize(o) {
bindAll(this, 'updateClientY', 'stopAutoscroll', 'autoscroll', '_emitUpdate');
@ -23,12 +27,13 @@ export default Backbone.View.extend({
};
this.ppfx = this.config.pStylePrefix || '';
this.em = this.config.em;
this.showGlobalTools = debounce(this.showGlobalTools.bind(this), 50);
const cvModel = this.getCanvasModel();
this.listenTo(model, 'change:head', this.updateHead);
this.listenTo(cvModel, 'change:styles', this.renderStyles);
model.view = this;
setViewEl(el, this);
},
}
/**
* Update `<head>` content of the frame
@ -59,35 +64,35 @@ export default Backbone.View.extend({
el && el.parentNode.removeChild(el);
});
appendVNodes(headEl, toAdd);
},
}
getEl() {
return this.el;
},
}
getCanvasModel() {
return this.em.get('Canvas').getModel();
},
}
getWindow() {
return this.getEl().contentWindow;
},
}
getDoc() {
return this.getEl().contentDocument;
},
}
getHead() {
return this.getDoc().querySelector('head');
},
}
getBody() {
return this.getDoc().querySelector('body');
},
}
getWrapper() {
return this.getBody().querySelector('[data-gjs-type=wrapper]');
},
}
getJsContainer() {
if (!this.jsContainer) {
@ -95,28 +100,28 @@ export default Backbone.View.extend({
}
return this.jsContainer;
},
}
getToolsEl() {
const { frameWrapView } = this.config;
return frameWrapView && frameWrapView.elTools;
},
}
getGlobalToolsEl() {
return this.em.get('Canvas').getGlobalToolsEl();
},
}
getHighlighter() {
return this._getTool('[data-hl]');
},
}
getBadgeEl() {
return this._getTool('[data-badge]');
},
}
getOffsetViewerEl() {
return this._getTool('[data-offset]');
},
}
getRect() {
if (!this.rect) {
@ -124,7 +129,7 @@ export default Backbone.View.extend({
}
return this.rect;
},
}
/**
* Get rect data, not affected by the canvas zoom
@ -145,7 +150,7 @@ export default Backbone.View.extend({
scrollBottom: scrollTop + height,
scrollRight: scrollLeft + width,
};
},
}
_getTool(name) {
const { tools } = this;
@ -156,15 +161,15 @@ export default Backbone.View.extend({
}
return tools[name];
},
}
remove() {
const wrp = this.wrapper;
this._toggleEffects();
this.tools = {};
wrp && wrp.remove();
Backbone.View.prototype.remove.apply(this, arguments);
},
View.prototype.remove.apply(this, arguments);
}
startAutoscroll() {
this.lastMaxHeight = this.getWrapper().offsetHeight - this.el.offsetHeight;
@ -175,7 +180,7 @@ export default Backbone.View.extend({
this._toggleAutoscrollFx(1);
requestAnimationFrame(this.autoscroll);
}, 0);
},
}
autoscroll() {
if (this.dragging) {
@ -211,20 +216,20 @@ export default Backbone.View.extend({
requestAnimationFrame(this.autoscroll);
}
},
}
updateClientY(ev) {
ev.preventDefault();
this.lastClientY = getPointerEvent(ev).clientY * this.em.getZoomDecimal();
},
}
showGlobalTools: debounce(function () {
showGlobalTools() {
this.getGlobalToolsEl().style.opacity = '';
}, 50),
}
stopAutoscroll() {
this.dragging && this._toggleAutoscrollFx();
},
}
_toggleAutoscrollFx(enable) {
this.dragging = enable;
@ -233,14 +238,14 @@ export default Backbone.View.extend({
const mt = { on, off };
mt[method](win, 'mousemove dragover', this.updateClientY);
mt[method](win, 'mouseup', this.stopAutoscroll);
},
}
render() {
const { $el, ppfx } = this;
$el.attr({ class: `${ppfx}frame` });
this.renderScripts();
return this;
},
}
renderScripts() {
const { el, model, em } = this;
@ -266,7 +271,7 @@ export default Backbone.View.extend({
em && em.trigger(`${evLoad}:before`, evOpts);
appendScript([...canvas.get('scripts')]);
};
},
}
renderStyles(opts = {}) {
const head = this.getHead();
@ -297,7 +302,7 @@ export default Backbone.View.extend({
el && el.parentNode.removeChild(el);
});
appendVNodes(head, toAdd);
},
}
renderBody() {
const { config, model, ppfx } = this;
@ -426,15 +431,15 @@ export default Backbone.View.extend({
this._toggleEffects(1);
this.droppable = hasDnd(em) && new Droppable(em, this.wrapper.el);
model.trigger('loaded');
},
}
_toggleEffects(enable) {
const method = enable ? on : off;
const win = this.getWindow();
win && method(win, `${motionsEv} resize`, this._emitUpdate);
},
}
_emitUpdate() {
this.model._emitUpdated();
},
});
}
}

77
src/canvas/view/FrameWrapView.js

@ -1,28 +1,23 @@
import Backbone from 'backbone';
import FrameView from './FrameView';
import { bindAll, isNumber, isNull, debounce } from 'underscore';
import { createEl, removeEl } from 'utils/dom';
import Dragger from 'utils/Dragger';
export default Backbone.View.extend({
events: {
'click [data-action-remove]': 'remove',
'mousedown [data-action-move]': 'startDrag'
},
import { View } from '../../common';
import FrameView from './FrameView';
import { createEl, removeEl } from '../../utils/dom';
import Dragger from '../../utils/Dragger';
export default class FrameWrapView extends View {
events() {
return {
'click [data-action-remove]': 'remove',
'mousedown [data-action-move]': 'startDrag',
};
}
initialize(opts = {}, conf = {}) {
bindAll(
this,
'onScroll',
'frameLoaded',
'updateOffset',
'remove',
'startDrag'
);
bindAll(this, 'onScroll', 'frameLoaded', 'updateOffset', 'remove', 'startDrag');
const { model } = this;
const config = {
...(opts.config || conf),
frameWrapView: this
frameWrapView: this,
};
const { canvasView, em } = config;
this.cv = canvasView;
@ -40,7 +35,7 @@ export default Backbone.View.extend({
this.listenTo(model, 'destroy remove', this.remove);
this.updatePos();
this.setupDragger();
},
}
setupDragger() {
const { canvas, model } = this;
@ -61,30 +56,28 @@ export default Backbone.View.extend({
setPosition: posOpts => {
model.set({
x: dragX + posOpts.x * zoom,
y: dragY + posOpts.y * zoom
y: dragY + posOpts.y * zoom,
});
}
},
});
},
}
startDrag(ev) {
ev && this.dragger.start(ev);
},
}
__clear(opts) {
const { frame } = this;
frame && frame.remove(opts);
removeEl(this.elTools);
},
}
remove(opts) {
this.__clear(opts);
Backbone.View.prototype.remove.apply(this, arguments);
['frame', 'dragger', 'cv', 'em', 'canvas', 'elTools'].forEach(
i => (this[i] = 0)
);
View.prototype.remove.apply(this, arguments);
['frame', 'dragger', 'cv', 'em', 'canvas', 'elTools'].forEach(i => (this[i] = 0));
return this;
},
}
updateOffset() {
const { em, $el, frame } = this;
@ -92,7 +85,7 @@ export default Backbone.View.extend({
em.runDefault({ preserveSelected: 1 });
$el.removeClass(this.classAnim);
frame.model._emitUpdated();
},
}
updatePos(md) {
const { model, el } = this;
@ -102,11 +95,11 @@ export default Backbone.View.extend({
style.left = isNaN(x) ? x : `${x}px`;
style.top = isNaN(y) ? y : `${y}px`;
md && this.updateOffset();
},
}
updateSize() {
this.updateDim();
},
}
/**
* Update dimensions of the frame
@ -124,7 +117,7 @@ export default Backbone.View.extend({
model.set(
{
...(!width ? { width: el.offsetWidth } : {}),
...(!height ? { height: el.offsetHeight } : {})
...(!height ? { height: el.offsetHeight } : {}),
},
{ silent: 1 }
);
@ -134,22 +127,22 @@ export default Backbone.View.extend({
// component hover during the animation
em.stopDefault({ preserveSelected: 1 });
noChanges ? this.updateOffset() : setTimeout(this.updateOffset, 350);
},
}
onScroll() {
const { frame, em } = this;
em.trigger('frame:scroll', {
frame,
body: frame.getBody(),
target: frame.getWindow()
target: frame.getWindow(),
});
},
}
frameLoaded() {
const { frame } = this;
frame.getWindow().onscroll = this.onScroll;
this.updateDim();
},
}
__handleSize() {
const un = 'px';
@ -164,7 +157,7 @@ export default Backbone.View.extend({
style.width = isNumber(newW) ? `${newW}${un}` : newW;
style.height = isNumber(newH) ? `${newH}${un}` : newH;
return { noChanges, width, height, newW, newH };
},
}
render() {
const { frame, $el, ppfx, cv, model, el } = this;
@ -197,7 +190,7 @@ export default Backbone.View.extend({
'div',
{
class: `${ppfx}tools`,
style: 'pointer-events:none; display: none'
style: 'pointer-events:none; display: none',
},
`
<div class="${ppfx}highlighter" data-hl></div>
@ -238,8 +231,8 @@ export default Backbone.View.extend({
frame: model,
frameWrapperView: this,
remove: this.remove,
startDrag: this.startDrag
startDrag: this.startDrag,
});
return this;
}
});
}

2
src/canvas/view/FramesView.js

@ -1,4 +1,4 @@
import DomainViews from 'domain_abstract/view/DomainViews';
import DomainViews from '../../domain_abstract/view/DomainViews';
import FrameWrapView from './FrameWrapView';
export default class FramesView extends DomainViews {

3
src/dom_components/view/ComponentsView.js

@ -1,5 +1,6 @@
import Backbone from 'backbone';
import { isUndefined } from 'underscore';
import { removeEl } from '../../utils/dom';
export default Backbone.View.extend({
initialize(o) {
@ -17,7 +18,7 @@ export default Backbone.View.extend({
if (!view) return;
const { childrenView, scriptContainer } = view;
childrenView && childrenView.stopListening();
scriptContainer && scriptContainer.remove();
removeEl(scriptContainer);
view.remove.apply(view);
});

Loading…
Cancel
Save