diff --git a/src/block_manager/index.js b/src/block_manager/index.js index b075c1d0e..deb81bd1d 100644 --- a/src/block_manager/index.js +++ b/src/block_manager/index.js @@ -2,7 +2,9 @@ * * [add](#add) * * [get](#get) * * [getAll](#getall) + * * [getAllVisible](#getallvisible) * * [getCategories](#getcategories) + * * [getContainer](#getcontainer) * * [render](#render) * * Block manager helps managing various, draggable, piece of contents that could be easily reused inside templates. @@ -32,7 +34,7 @@ module.exports = () => { Blocks = require('./model/Blocks'), BlockCategories = require('./model/Categories'), BlocksView = require('./view/BlocksView'); - var blocks, view; + var blocks, blocksVisible, blocksView; var categories = []; return { @@ -52,19 +54,58 @@ module.exports = () => { */ init(config) { c = config || {}; - for (var name in defaults) { - if (!(name in c)) + const em = c.em; + + for (let name in defaults) { + if (!(name in c)) { c[name] = defaults[name]; + } } - blocks = new Blocks(c.blocks); + + // Global blocks collection + blocks = new Blocks([]); + blocksVisible = new Blocks([]); categories = new BlockCategories(), - view = new BlocksView({ - collection: blocks, + blocksView = new BlocksView({ + // Visible collection + collection: blocksVisible, categories, }, c); + + // Setup the sync between the global and public collections + blocks.listenTo(blocks, 'add', model => { + blocksVisible.add(model); + em && em.trigger('block:add', model); + }); + + blocks.listenTo(blocks, 'remove', model => { + blocksVisible.remove(model); + em && em.trigger('block:remove', model); + }); + + blocks.listenTo(blocks, 'reset', coll => { + blocksVisible.reset(coll.models); + }); + return this; }, + /** + * Get configuration object + * @return {Object} + */ + getConfig() { + return c; + }, + + /** + * Loading blocks with `onLoad` allows to init starting collection + * from plugins + */ + onLoad() { + this.getAll().reset(c.blocks); + }, + /** * Add new block to the collection. * @param {string} id Block id @@ -98,7 +139,7 @@ module.exports = () => { * Return the block by id * @param {string} id Block id * @example - * var block = blockManager.get('h1-block'); + * const block = blockManager.get('h1-block'); * console.log(JSON.stringify(block)); * // {label: 'Heading', content: '

Put your ...', ...} */ @@ -110,7 +151,7 @@ module.exports = () => { * Return all blocks * @return {Collection} * @example - * var blocks = blockManager.getAll(); + * const blocks = blockManager.getAll(); * console.log(JSON.stringify(blocks)); * // [{label: 'Heading', content: '

Put your ...'}, ...] */ @@ -118,9 +159,26 @@ module.exports = () => { return blocks; }, + /** + * Return the visible collection, which containes blocks actually rendered + * @return {Collection} + */ + getAllVisible() { + return blocksVisible; + }, + + /** + * Remove a block by id + * @param {string} id Block id + * @return {Block} Removed block + */ + remove(id) { + return blocks.remove(id); + }, + /** * Get all available categories. - * Is possible to add categories only with blocks via 'add()' method + * It's possible to add categories only within blocks via 'add()' method * @return {Array|Collection} */ getCategories() { @@ -128,20 +186,43 @@ module.exports = () => { }, /** - * Render blocks + * Return the Blocks container element * @return {HTMLElement} */ - render() { - return view.render().el; + getContainer() { + return blocksView.el; }, /** - * Remove block by id - * @param {string} id Block id - * @return {Block} Removed block + * Render blocks + * @param {Array} blocks Blocks to render, without the argument will render + * all global blocks + * @example + * // Render all blocks (inside the global collection) + * blockManager.render(); + * + * // Render new set of blocks + * const blocks = blockManager.getAll(); + * blockManager.render(blocks.filter( + * block => block.get('category') == 'sections' + * )); + * // Or a new set from an array + * blockManager.render([ + * {label: 'Label text', content: '
Content
'} + * ]); + * + * // Back to blocks from the global collection + * blockManager.render(); */ - remove(id) { - return blocks.remove(id); + render(blocks) { + const toRender = blocks || this.getAll().models; + + if (!blocksView.rendered) { + blocksView.render(); + blocksView.rendered = 1; + } + + blocksView.collection.reset(toRender); }, }; diff --git a/src/block_manager/view/BlocksView.js b/src/block_manager/view/BlocksView.js index 33c0d81fb..75cfdf25c 100644 --- a/src/block_manager/view/BlocksView.js +++ b/src/block_manager/view/BlocksView.js @@ -14,7 +14,9 @@ module.exports = Backbone.View.extend({ this.noCatClass = `${ppfx}blocks-no-cat`; this.blockContClass = `${ppfx}blocks-c`; this.catsClass = `${ppfx}block-categories`; - this.listenTo(this.collection, 'add', this.addTo); + const coll = this.collection; + this.listenTo(coll, 'add', this.addTo); + this.listenTo(coll, 'reset', this.render); this.em = this.config.em; this.tac = 'test-tac'; this.grabbingCls = this.ppfx + 'grabbing'; @@ -167,8 +169,7 @@ module.exports = Backbone.View.extend({ }, render() { - var ppfx = this.ppfx; - var frag = document.createDocumentFragment(); + const frag = document.createDocumentFragment(); this.catsEl = null; this.blocksEl = null; this.renderedCategories = []; @@ -179,10 +180,7 @@ module.exports = Backbone.View.extend({ `; - this.collection.each(function(model){ - this.add(model, frag); - }, this); - + this.collection.each(model => this.add(model, frag)); this.append(frag); this.$el.addClass(this.blockContClass + 's') return this; diff --git a/src/commands/view/OpenBlocks.js b/src/commands/view/OpenBlocks.js index 6691db2d6..8abb5d871 100644 --- a/src/commands/view/OpenBlocks.js +++ b/src/commands/view/OpenBlocks.js @@ -1,28 +1,24 @@ -const $ = Backbone.$; - module.exports = { run(editor, sender) { - var config = editor.Config; - var pfx = config.stylePrefix; - var bm = editor.BlockManager; - var panelC; - if(!this.blocks){ - this.blocks = $('
').get(0); - this.blocks.appendChild(bm.render()); - var panels = editor.Panels; - if(!panels.getPanel('views-container')) - panelC = panels.addPanel({id: 'views-container'}); - else - panelC = panels.getPanel('views-container'); - panelC.set('appendContent', this.blocks).trigger('change:appendContent'); + const bm = editor.BlockManager; + const pn = editor.Panels; + + if (!this.blocks) { + bm.render(); + const id = 'views-container'; + const blocks = document.createElement('div'); + const panels = pn.getPanel(id) || pn.addPanel({id}); + blocks.appendChild(bm.getContainer()); + panels.set('appendContent', blocks).trigger('change:appendContent'); + this.blocks = blocks; } this.blocks.style.display = 'block'; }, stop() { - if(this.blocks) - this.blocks.style.display = 'none'; + const blocks = this.blocks; + blocks && (blocks.style.display = 'none'); } }; diff --git a/src/editor/index.js b/src/editor/index.js index d41b4346c..cd70bbae9 100644 --- a/src/editor/index.js +++ b/src/editor/index.js @@ -38,6 +38,8 @@ * * `component:styleUpdate` - Triggered when the style of the component is updated * * `component:styleUpdate:{propertyName}` - Listen for a specific style property change * * `component:selected` - New component selected + * * `block:add` - New block added + * * `block:remove` - Block removed * * `asset:add` - New asset added * * `asset:remove` - Asset removed * * `asset:upload:start` - Before the upload is started diff --git a/test/specs/block_manager/index.js b/test/specs/block_manager/index.js index 6ab43db55..877f083c8 100644 --- a/test/specs/block_manager/index.js +++ b/test/specs/block_manager/index.js @@ -65,7 +65,8 @@ describe('BlockManager', () => { }); it('Render blocks', () => { - expect(obj.render()).toExist(); + obj.render(); + expect(obj.getContainer()).toExist(); }); });