From 94c056af269eb2f313856963e79157cfe9e079f9 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Mon, 2 Sep 2019 22:57:28 +0200 Subject: [PATCH] Update renderBody in FrameView --- src/canvas/model/Frame.js | 2 +- src/canvas/view/CanvasView.js | 2 +- src/canvas/view/FrameView.js | 105 ++++++++++++++++++++-------------- src/utils/dom.js | 38 +++++++++++- 4 files changed, 101 insertions(+), 46 deletions(-) diff --git a/src/canvas/model/Frame.js b/src/canvas/model/Frame.js index f0380b85d..d8ec7e664 100644 --- a/src/canvas/model/Frame.js +++ b/src/canvas/model/Frame.js @@ -18,7 +18,7 @@ export default Backbone.Model.extend({ initialize() { const { root, styles } = this.attributes; this.set('head', []); - !root && this.set('root', new Component()); + !root && this.set('root', new Component({ type: 'wrapper' })); !styles && this.set('styles', new CssRules()); }, diff --git a/src/canvas/view/CanvasView.js b/src/canvas/view/CanvasView.js index 949d84c1b..519df0802 100644 --- a/src/canvas/view/CanvasView.js +++ b/src/canvas/view/CanvasView.js @@ -495,7 +495,7 @@ export default Backbone.View.extend({ // Render all frames const frames = new FramesView({ collection: model.get('frames'), - config + config: { ...config, renderContent: 1 } }); frames.render(); $frames.append(frames.el); diff --git a/src/canvas/view/FrameView.js b/src/canvas/view/FrameView.js index 3f09bcf5f..4b1af0be1 100644 --- a/src/canvas/view/FrameView.js +++ b/src/canvas/view/FrameView.js @@ -2,7 +2,14 @@ import Backbone from 'backbone'; import { bindAll } from 'underscore'; import CssRulesView from 'css_composer/view/CssRulesView'; import ComponentView from 'dom_components/view/ComponentView'; -import { appendVNodes, empty, append } from 'utils/dom'; +import { + appendVNodes, + empty, + append, + createEl, + createCustomEvent +} from 'utils/dom'; +import { on, off } from 'utils/mixins'; const motionsEv = 'transitionend oTransitionEnd transitionend webkitTransitionEnd'; @@ -96,8 +103,20 @@ export default Backbone.View.extend({ return this.$el.contents().find('body > div'); }, + getJsContainer() { + if (!this.jsContainer) { + this.jsContainer = createEl('div', { class: `${this.ppfx}js-cont` }); + } + + return this.jsContainer; + }, + render() { - this.$el.attr({ class: this.ppfx + 'frame' }); + const { el, $el, ppfx, config } = this; + $el.attr({ class: ppfx + 'frame' }); + if (config.renderContent) { + el.onload = this.renderBody.bind(this); + } return this; }, @@ -106,9 +125,10 @@ export default Backbone.View.extend({ const root = model.get('root'); const styles = model.get('styles'); const { em } = config; + const win = this.getWindow(); + const doc = this.getDoc(); const body = this.getBody(); const conf = em.get('Config'); - const win = this.getWindow(); // Should be handled by `head` // config.styles.forEach(style => { @@ -129,7 +149,33 @@ export default Backbone.View.extend({ append( body, `` ); append(body, new ComponentView({ model: root }).render().el); - append(body, new CssRulesView({ collection: styles }).render().el); - body.append(this.getJsContainer()); - em.trigger('loaded'); - win.onscroll = this.onFrameScroll; - this.frame.updateOffset(); - - // Avoid the default link behaviour in the canvas - body.on( + append(body, new CssRulesView({ collection: styles, config }).render().el); + append(body, this.getJsContainer()); + // em.trigger('loaded'); // I need to manage only the first one maybe + // win.onscroll = this.onFrameScroll; // TODO + this.updateOffset(); // TOFIX (check if I need it) + + // Avoid some default behaviours + on( + body, 'click', ev => ev && ev.target.tagName == 'A' && ev.preventDefault() ); - // Avoid the default form behaviour - body.on('submit', ev => ev && ev.preventDefault()); + on(body, 'submit', ev => ev && ev.preventDefault()); // When the iframe is focused the event dispatcher is not the same so // I need to delegate all events to the parent document - const doc = document; - const fdoc = this.frame.el.contentDocument; - - // Unfortunately just creating `KeyboardEvent(e.type, e)` is not enough, - // the keyCode/which will be always `0`. Even if it's an old/deprecated - // property keymaster (and many others) still use it... using `defineProperty` - // hack seems the only way - const createCustomEvent = (e, cls) => { - let oEvent; - try { - oEvent = new window[cls](e.type, e); - } catch (e) { - oEvent = document.createEvent(cls); - oEvent.initEvent(e.type, true, true); - } - oEvent.keyCodeVal = e.keyCode; - oEvent._parentEvent = e; - ['keyCode', 'which'].forEach(prop => { - Object.defineProperty(oEvent, prop, { - get() { - return this.keyCodeVal; - } - }); - }); - return oEvent; - }; - [ { event: 'keydown keyup keypress', class: 'KeyboardEvent' }, { event: 'wheel', class: 'WheelEvent' } ].forEach(obj => obj.event.split(' ').forEach(event => { - fdoc.addEventListener(event, e => - this.el.dispatchEvent(createCustomEvent(e, obj.class)) + doc.addEventListener(event, ev => + this.el.dispatchEvent(createCustomEvent(ev, obj.class)) ); }) ); diff --git a/src/utils/dom.js b/src/utils/dom.js index 21bc1ad7d..14924686e 100644 --- a/src/utils/dom.js +++ b/src/utils/dom.js @@ -1,5 +1,5 @@ // DOM helpers -import { each, isUndefined } from 'underscore'; +import { each, isUndefined, isString } from 'underscore'; const KEY_TAG = 'tag'; const KEY_ATTR = 'attributes'; @@ -18,6 +18,12 @@ export const appendAtIndex = (parent, child, index) => { const total = childNodes.length; const at = isUndefined(index) ? total : index; + if (isString(child)) { + parent.insertAdjacentHTML('beforeEnd', child); + child = parent.lastChild; + parent.removeChild(child); + } + if (at >= total) { parent.appendChild(child); } else { @@ -27,6 +33,36 @@ export const appendAtIndex = (parent, child, index) => { export const append = (parent, child) => appendAtIndex(parent, child); +export const createEl = (tag, attrs = '') => { + const el = document.createElement(tag); + attrs && each(attrs, (value, key) => el.setAttribute(key, value)); + return el; +}; + +// Unfortunately just creating `KeyboardEvent(e.type, e)` is not enough, +// the keyCode/which will be always `0`. Even if it's an old/deprecated +// property keymaster (and many others) still use it... using `defineProperty` +// hack seems the only way +export const createCustomEvent = (e, cls) => { + let oEvent; + try { + oEvent = new window[cls](e.type, e); + } catch (e) { + oEvent = document.createEvent(cls); + oEvent.initEvent(e.type, true, true); + } + oEvent.keyCodeVal = e.keyCode; + oEvent._parentEvent = e; + ['keyCode', 'which'].forEach(prop => { + Object.defineProperty(oEvent, prop, { + get() { + return this.keyCodeVal; + } + }); + }); + return oEvent; +}; + /** * Append an array of vNodes to an element * @param {HTMLElement} node HTML element