UNPKG

@print-one/grapesjs

Version:

Free and Open Source Web Builder Framework

211 lines (183 loc) 5.34 kB
import { isString, isObject, bindAll } from 'underscore'; import BlockManager from '..'; import { View } from '../../common'; import Component from '../../dom_components/model/Component'; import EditorModel from '../../editor/model/Editor'; import Block from '../model/Block'; import Categories from '../model/Categories'; import BlockView from './BlockView'; import CategoryView from './CategoryView'; export interface BlocksViewConfig { em: EditorModel; pStylePrefix?: string; ignoreCategories?: boolean; getSorter?: any; } export default class BlocksView extends View { em: EditorModel; config: BlocksViewConfig; categories: Categories; renderedCategories: Record<string, CategoryView>; ppfx: string; noCatClass: string; blockContClass: string; catsClass: string; catsEl?: HTMLElement; blocksEl?: HTMLElement; rendered?: boolean; sorter: any; constructor(opts: any, config: BlocksViewConfig) { super(opts); bindAll(this, 'getSorter', 'onDrag', 'onDrop', 'onMove'); this.config = config || {}; this.categories = opts.categories || ''; this.renderedCategories = {}; const ppfx = this.config.pStylePrefix || ''; this.ppfx = ppfx; this.noCatClass = `${ppfx}blocks-no-cat`; this.blockContClass = `${ppfx}blocks-c`; this.catsClass = `${ppfx}block-categories`; const coll = this.collection; this.listenTo(coll, 'add', this.addTo); this.listenTo(coll, 'reset', this.render); this.em = this.config.em; if (this.em) { this.config.getSorter = this.getSorter; } } __getModule(): BlockManager { return this.em.Blocks; } updateConfig(opts = {}) { this.config = { ...this.config, ...opts, }; } /** * Get sorter * @private */ getSorter() { const { em } = this; if (!em) return; if (!this.sorter) { const utils = em.Utils; const canvas = em.Canvas; this.sorter = new utils.Sorter({ // @ts-ignore container: canvas.getBody(), placer: canvas.getPlacerEl(), containerSel: '*', itemSel: '*', pfx: this.ppfx, onStart: this.onDrag, onEndMove: this.onDrop, onMove: this.onMove, document: canvas.getFrameEl().contentDocument, direction: 'a', wmargin: 1, nested: 1, em, canvasRelative: 1, }); } return this.sorter; } onDrag(ev: Event) { this.em.stopDefault(); this.__getModule().__startDrag(this.sorter.__currentBlock, ev); } onMove(ev: Event) { this.__getModule().__drag(ev); this.em.trigger('block:drag:move', ev); // old event } onDrop(component?: Component) { this.em.runDefault(); this.__getModule().__endDrag({ component }); delete this.sorter.__currentBlock; } /** * Add new model to the collection * @param {Model} model * @private * */ addTo(model: Block) { this.add(model); } /** * Render new model inside the view * @param {Model} model * @param {Object} fragment Fragment collection * @private * */ add(model: Block, fragment?: DocumentFragment) { const { config } = this; const view = new BlockView( { model, attributes: model.get('attributes'), }, config ); const rendered = view.render().el; let category = model.get('category'); // Check for categories if (category && this.categories && !config.ignoreCategories) { if (isString(category)) { category = { id: category, label: category }; } else if (isObject(category) && !category.id) { category.id = category.label; } const catModel = this.categories.add(category); const catId = catModel.get('id')!; const categories = this.getCategoriesEl(); let catView = this.renderedCategories[catId]; // @ts-ignore model.set('category', catModel, { silent: true }); if (!catView && categories) { catView = new CategoryView({ model: catModel }, config).render(); this.renderedCategories[catId] = catView; categories.appendChild(catView.el); } catView && catView.append(rendered); return; } fragment ? fragment.appendChild(rendered) : this.append(rendered); } getCategoriesEl() { if (!this.catsEl) { this.catsEl = this.el.querySelector(`.${this.catsClass}`)!; } return this.catsEl; } getBlocksEl() { if (!this.blocksEl) { this.blocksEl = this.el.querySelector(`.${this.noCatClass} .${this.blockContClass}`)!; } return this.blocksEl; } append(el: HTMLElement | DocumentFragment) { let blocks = this.getBlocksEl(); blocks && blocks.appendChild(el); } render() { const ppfx = this.ppfx; const frag = document.createDocumentFragment(); delete this.catsEl; delete this.blocksEl; this.renderedCategories = {}; this.el.innerHTML = ` <div class="${this.catsClass}"></div> <div class="${this.noCatClass}"> <div class="${this.blockContClass}"></div> </div> `; this.collection.each(model => this.add(model, frag)); this.append(frag); const cls = `${this.blockContClass}s ${ppfx}one-bg ${ppfx}two-color`; this.$el.addClass(cls); this.rendered = true; return this; } }