diff --git a/src/canvas/model/Frame.js b/src/canvas/model/Frame.js index 4943e3aaa..f0380b85d 100644 --- a/src/canvas/model/Frame.js +++ b/src/canvas/model/Frame.js @@ -1,4 +1,6 @@ import Backbone from 'backbone'; +import Component from 'dom_components/model/Component'; +import CssRules from 'css_composer/model/CssRules'; export default Backbone.Model.extend({ defaults: { @@ -8,11 +10,16 @@ export default Backbone.Model.extend({ head: '', x: 0, y: 0, + root: 0, + styles: 0, attributes: {} }, initialize() { + const { root, styles } = this.attributes; this.set('head', []); + !root && this.set('root', new Component()); + !styles && this.set('styles', new CssRules()); }, getHead() { diff --git a/src/canvas/view/FrameView.js b/src/canvas/view/FrameView.js index 7ae53ed6a..3f09bcf5f 100644 --- a/src/canvas/view/FrameView.js +++ b/src/canvas/view/FrameView.js @@ -1,6 +1,8 @@ import Backbone from 'backbone'; import { bindAll } from 'underscore'; -import { appendVNodes, empty } from 'utils/dom'; +import CssRulesView from 'css_composer/view/CssRulesView'; +import ComponentView from 'dom_components/view/ComponentView'; +import { appendVNodes, empty, append } from 'utils/dom'; const motionsEv = 'transitionend oTransitionEnd transitionend webkitTransitionEnd'; @@ -74,6 +76,10 @@ export default Backbone.View.extend({ this.$el.off(motionsEv, this.updateOffset); }, + getWindow() { + return this.$el.get(0).contentWindow; + }, + getDoc() { return this.$el.get(0).contentDocument; }, @@ -93,5 +99,149 @@ export default Backbone.View.extend({ render() { this.$el.attr({ class: this.ppfx + 'frame' }); return this; + }, + + renderBody() { + const { config, model, ppfx } = this; + const root = model.get('root'); + const styles = model.get('styles'); + const { em } = config; + const body = this.getBody(); + const conf = em.get('Config'); + const win = this.getWindow(); + + // Should be handled by `head` + // config.styles.forEach(style => { + // externalStyles += ``; + // }); + // externalStyles && head.append(externalStyles); + + const colorWarn = '#ffca6f'; + + // I need all this styles to make the editor work properly + // Remove `html { height: 100%;}` from the baseCss as it gives jumpings + // effects (on ENTER) with RTE like CKEditor (maybe some bug there?!?) + // With `body {height: auto;}` jumps in CKEditor are removed but in + // Firefox is impossible to drag stuff in empty canvas, so bring back + // `body {height: 100%;}`. + // For the moment I give the priority to Firefox as it might be + // CKEditor's issue + 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( + 'click', + ev => ev && ev.target.tagName == 'A' && ev.preventDefault() + ); + // Avoid the default form behaviour + body.on('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)) + ); + }) + ); } }); diff --git a/src/utils/dom.js b/src/utils/dom.js index 805007dd7..21bc1ad7d 100644 --- a/src/utils/dom.js +++ b/src/utils/dom.js @@ -25,6 +25,8 @@ export const appendAtIndex = (parent, child, index) => { } }; +export const append = (parent, child) => appendAtIndex(parent, child); + /** * Append an array of vNodes to an element * @param {HTMLElement} node HTML element