UNPKG

grapesjs

Version:

Free and Open Source Web Builder Framework

147 lines (129 loc) 4.05 kB
import Backbone from 'backbone'; import { isUndefined } from 'underscore'; export default Backbone.View.extend({ initialize(o) { this.opts = o || {}; this.config = o.config || {}; const coll = this.collection; this.listenTo(coll, 'add', this.addTo); this.listenTo(coll, 'reset', this.resetChildren); this.listenTo(coll, 'remove', this.removeChildren); }, removeChildren(removed, coll, opts = {}) { const em = this.config.em; const view = removed.view; const tempComp = removed.opt.temporary; const tempRemove = opts.temporary; if (!view) return; view.remove.apply(view); const { childrenView, scriptContainer } = view; childrenView && childrenView.stopListening(); scriptContainer && scriptContainer.remove(); removed.components().forEach(it => this.removeChildren(it, coll, opts)); if (em && !tempRemove) { // Remove the component from the global list const id = removed.getId(); const domc = em.get('DomComponents'); delete domc.componentsById[id]; // Remove all related CSS rules const allRules = em.get('CssComposer').getAll(); allRules.remove( allRules.filter( rule => rule.getSelectors().getFullString() === `#${id}` ) ); if (!tempComp) { const cm = em.get('Commands'); const hasSign = removed.get('style-signature'); const optStyle = { target: removed }; hasSign && cm.run('core:component-style-clear', optStyle); removed.removed(); em.trigger('component:remove', removed); } } }, /** * Add to collection * @param {Model} model * @param {Collection} coll * @param {Object} opts * @private * */ addTo(model, coll = {}, opts = {}) { const em = this.config.em; const i = this.collection.indexOf(model); this.addToCollection(model, null, i); if (em && !opts.temporary) { const triggerAdd = model => { em.trigger('component:add', model); model.components().forEach(comp => triggerAdd(comp)); }; triggerAdd(model); } }, /** * Add new object to collection * @param {Object} Model * @param {Object} Fragment collection * @param {Integer} Index of append * * @return {Object} Object rendered * @private * */ addToCollection(model, fragmentEl, index) { if (!this.compView) this.compView = require('./ComponentView').default; const { config, opts } = this; const fragment = fragmentEl || null; const dt = opts.componentTypes; const type = model.get('type'); let viewObject = this.compView; for (let it = 0; it < dt.length; it++) { if (dt[it].id == type) { viewObject = dt[it].view; break; } } const view = new viewObject({ model, config, componentTypes: dt }); let rendered = view.render().el; if (fragment) { fragment.appendChild(rendered); } else { const parent = this.parentEl; const children = parent.childNodes; if (!isUndefined(index)) { const lastIndex = children.length == index; // If the added model is the last of collection // need to change the logic of append if (lastIndex) { index--; } // In case the added is new in the collection index will be -1 if (lastIndex || !children.length) { parent.appendChild(rendered); } else { parent.insertBefore(rendered, children[index]); } } else { parent.appendChild(rendered); } } return rendered; }, resetChildren() { this.parentEl.innerHTML = ''; this.collection.each(model => this.addToCollection(model)); }, render(parent) { const el = this.el; const frag = document.createDocumentFragment(); this.parentEl = parent || this.el; this.collection.each(model => this.addToCollection(model, frag)); el.innerHTML = ''; el.appendChild(frag); return this; } });