From 83170fce855561188e6c694e9b45a10ebbeea43b Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 25 May 2019 15:32:43 +0200 Subject: [PATCH] Make FrameView listen to head change --- src/canvas/model/Frame.js | 37 ++++++++++++++++++++++-------------- src/canvas/view/FrameView.js | 21 +++++++++++++++++++- src/utils/dom.js | 30 +++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 src/utils/dom.js diff --git a/src/canvas/model/Frame.js b/src/canvas/model/Frame.js index a7f35336f..751f4db78 100644 --- a/src/canvas/model/Frame.js +++ b/src/canvas/model/Frame.js @@ -14,7 +14,7 @@ module.exports = Backbone.Model.extend({ }, getHead() { - return this.get('head'); + return [...this.get('head')]; }, setHead(value) { @@ -27,14 +27,19 @@ module.exports = Backbone.Model.extend({ this.setHead(head); }, - removeHeadByAttr(attr, value, tag) { + getHeadByAttr(attr, value, tag) { const head = this.getHead(); - const item = head.filter( + return head.filter( item => item.attributes && item.attributes[attr] == value && (!tag || tag === item.tag) )[0]; + }, + + removeHeadByAttr(attr, value, tag) { + const head = this.getHead(); + const item = this.getHeadByAttr(attr, value, tag); const index = head.indexOf(item); if (index >= 0) { @@ -44,13 +49,15 @@ module.exports = Backbone.Model.extend({ }, addLink(href) { - this.addHeadItem({ - tag: 'link', - attributes: { - href, - rel: 'stylesheet' - } - }); + const tag = 'link'; + !this.getHeadByAttr('href', href, tag) && + this.addHeadItem({ + tag, + attributes: { + href, + rel: 'stylesheet' + } + }); }, removeLink(href) { @@ -58,10 +65,12 @@ module.exports = Backbone.Model.extend({ }, addScript(src) { - this.addHeadItem({ - tag: 'script', - attributes: { src } - }); + const tag = 'script'; + !this.getHeadByAttr('src', src, tag) && + this.addHeadItem({ + tag, + attributes: { src } + }); }, removeScript(src) { diff --git a/src/canvas/view/FrameView.js b/src/canvas/view/FrameView.js index 38b7d00f1..47f6fbf82 100644 --- a/src/canvas/view/FrameView.js +++ b/src/canvas/view/FrameView.js @@ -1,4 +1,5 @@ import { bindAll } from 'underscore'; +import { appendVNodes, empty } from 'utils/dom'; const motionsEv = 'transitionend oTransitionEnd transitionend webkitTransitionEnd'; @@ -15,9 +16,19 @@ module.exports = require('backbone').View.extend({ this.config = o.config || {}; this.ppfx = this.config.pStylePrefix || ''; this.em = this.config.em; + this.listenTo(this.model, 'change:head', this.updateHead); this.listenTo(this.em, 'change:device', this.updateDim); }, + /** + * Update `` content of the frame + */ + updateHead() { + const headEl = this.getHead(); + empty(headEl); + appendVNodes(headEl, this.model.getHead()); + }, + /** * Update dimensions of the frame * @private @@ -48,8 +59,16 @@ module.exports = require('backbone').View.extend({ this.$el.off(motionsEv, this.udpateOffset); }, + getDoc() { + return this.$el.get(0).contentDocument; + }, + + getHead() { + return this.getDoc().querySelector('head'); + }, + getBody() { - this.$el.contents().find('body'); + return this.getDoc().querySelector('body'); }, getWrapper() { diff --git a/src/utils/dom.js b/src/utils/dom.js new file mode 100644 index 000000000..e9c144e61 --- /dev/null +++ b/src/utils/dom.js @@ -0,0 +1,30 @@ +// DOM helpers +import { each } from 'underscore'; + +const KEY_TAG = 'tag'; +const KEY_ATTR = 'attributes'; +const KEY_CHILD = 'children'; + +export const empty = node => { + while (node.firstChild) node.removeChild(node.firstChild); +}; + +/** + * Append an array of vNodes to an element + * @param {HTMLElement} node HTML element + * @param {Array} vNodes Array of node objects + */ +export const appendVNodes = (node, vNodes = []) => { + const vNodesArr = Array.isArray(vNodes) ? vNodes : [vNodes]; + vNodesArr.forEach(vnode => { + const tag = vnode[KEY_TAG] || 'div'; + const attr = vnode[KEY_ATTR] || {}; + const el = document.createElement(tag); + + each(attr, (value, key) => { + el.setAttribute(key, value); + }); + + node.appendChild(el); + }); +};