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();
});
});