mirror of https://github.com/artf/grapesjs.git
20 changed files with 446 additions and 4 deletions
@ -0,0 +1,7 @@ |
|||
define(function () { |
|||
return { |
|||
|
|||
'blocks': [], |
|||
|
|||
}; |
|||
}); |
|||
@ -0,0 +1,105 @@ |
|||
/** |
|||
* * [add](#add) |
|||
* * [get](#get) |
|||
* * [getAll](#getall) |
|||
* * [render](#render) |
|||
* |
|||
* Block manager helps managing various, draggable, pieces of content that could be reused inside templates. |
|||
* |
|||
* Before using methods you should get first the module from the editor instance, in this way: |
|||
* |
|||
* ```js
|
|||
* var blockManager = editor.BlockManager; |
|||
* ``` |
|||
* |
|||
* @module BlockManager |
|||
* @param {Object} config Configurations |
|||
* @param {Array<Object>} [config.blocks=[]] Default blocks |
|||
* @example |
|||
* ... |
|||
* blockManager: { |
|||
* blocks: [ |
|||
* {id:'h1-block' label: 'Heading', content:'<h1>...</h1>'}, |
|||
* ... |
|||
* ], |
|||
* } |
|||
* ... |
|||
*/ |
|||
define(function(require) { |
|||
|
|||
return function(config) { |
|||
var c = config || {}, |
|||
defaults = require('./config/config'), |
|||
Blocks = require('./model/Blocks'), |
|||
BlocksView = require('./view/BlocksView'); |
|||
|
|||
for (var name in defaults) { |
|||
if (!(name in c)) |
|||
c[name] = defaults[name]; |
|||
} |
|||
|
|||
var blocks = new Blocks(c.blocks); |
|||
var view = new BlocksView({ collection: blocks }, c); |
|||
|
|||
return { |
|||
|
|||
/** |
|||
* Add new block to the collection. |
|||
* @param {string} id Block id |
|||
* @param {Object} opts Options |
|||
* @param {string} opts.label Name of the block |
|||
* @param {string} opts.content HTML content |
|||
* @param {Object} [opts.attributes={}] Block attributes |
|||
* @return {Block} Added block |
|||
* @example |
|||
* blockManager.add('h1-block', { |
|||
* label: 'Heading', |
|||
* content: '<h1>Put your title here</h1>', |
|||
* attributes: { |
|||
* title: 'Insert h1 block' |
|||
* } |
|||
* }); |
|||
*/ |
|||
add: function(id, opts){ |
|||
var obj = opts || {}; |
|||
obj.id = id; |
|||
return blocks.add(obj); |
|||
}, |
|||
|
|||
/** |
|||
* Return block by id |
|||
* @param {string} id Block id |
|||
* @example |
|||
* var block = blockManager.get('h1-block'); |
|||
* console.log(JSON.stringify(block)); |
|||
* // {label: 'Heading', content: '<h1>Put your ...', ...}
|
|||
*/ |
|||
get: function(id){ |
|||
return blocks.get(id); |
|||
}, |
|||
|
|||
/** |
|||
* Return all blocks |
|||
* @return {Collection} |
|||
* @example |
|||
* var blocks = blockManager.getAll(); |
|||
* console.log(JSON.stringify(blocks)); |
|||
* // [{label: 'Heading', content: '<h1>Put your ...'}, ...]
|
|||
*/ |
|||
getAll: function(){ |
|||
return blocks; |
|||
}, |
|||
|
|||
/** |
|||
* Render blocks |
|||
* @return {HTMLElement} |
|||
*/ |
|||
render: function(){ |
|||
return view.render().el; |
|||
}, |
|||
|
|||
}; |
|||
|
|||
}; |
|||
|
|||
}); |
|||
@ -0,0 +1,13 @@ |
|||
define(['backbone'], |
|||
function(Backbone){ |
|||
|
|||
return Backbone.Model.extend({ |
|||
|
|||
defaults :{ |
|||
label: '', |
|||
content: '', |
|||
attributes: {}, |
|||
}, |
|||
|
|||
}); |
|||
}); |
|||
@ -0,0 +1,9 @@ |
|||
define(['backbone','./Block'], |
|||
function (Backbone, Block) { |
|||
|
|||
return Backbone.Collection.extend({ |
|||
|
|||
model: Block, |
|||
|
|||
}); |
|||
}); |
|||
@ -0,0 +1,17 @@ |
|||
define(['backbone'], |
|||
function(Backbone) { |
|||
|
|||
return Backbone.View.extend({ |
|||
|
|||
initialize: function(o) { |
|||
this.config = o.config || {}; |
|||
this.listenTo(this.model, 'destroy', this.remove); |
|||
}, |
|||
|
|||
render: function() { |
|||
this.el.innerHTML = this.model.get('label'); |
|||
return this; |
|||
}, |
|||
|
|||
}); |
|||
}); |
|||
@ -0,0 +1,56 @@ |
|||
define(['backbone', './BlockView'], |
|||
function(Backbone, BlockView) { |
|||
|
|||
return Backbone.View.extend({ |
|||
|
|||
initialize: function(opts, config) { |
|||
this.config = config || {}; |
|||
this.ppfx = this.config.pStylePrefix || ''; |
|||
this.listenTo(this.collection, 'add', this.addTo); |
|||
}, |
|||
|
|||
/** |
|||
* Add new model to the collection |
|||
* @param {Model} model |
|||
* @private |
|||
* */ |
|||
addTo: function(model){ |
|||
this.add(model); |
|||
}, |
|||
|
|||
/** |
|||
* Render new model inside the view |
|||
* @param {Model} model |
|||
* @param {Object} fragment Fragment collection |
|||
* */ |
|||
add: function(model, fragment){ |
|||
var frag = fragment || null; |
|||
var view = new BlockView({ |
|||
model: model, |
|||
attributes: model.get('attributes'), |
|||
}, this.config); |
|||
var rendered = view.render().el; |
|||
|
|||
if(frag) |
|||
frag.appendChild(rendered); |
|||
else |
|||
this.$el.append(rendered); |
|||
}, |
|||
|
|||
|
|||
|
|||
render: function() { |
|||
var frag = document.createDocumentFragment(); |
|||
this.$el.empty(); |
|||
|
|||
this.collection.each(function(model){ |
|||
this.add(model, frag); |
|||
}, this); |
|||
|
|||
this.$el.append(frag); |
|||
this.$el.addClass(this.ppfx + 'blocks-c'); |
|||
return this; |
|||
}, |
|||
|
|||
}); |
|||
}); |
|||
@ -0,0 +1,27 @@ |
|||
define(function() { |
|||
|
|||
return { |
|||
|
|||
run: function(editor, sender) { |
|||
var config = editor.Config; |
|||
var pfx = config.stylePrefix; |
|||
var bm = editor.BlockManager; |
|||
if(!this.blocks){ |
|||
this.blocks = 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'); |
|||
} |
|||
|
|||
this.blocks.style.display = 'block'; |
|||
}, |
|||
|
|||
stop: function() { |
|||
if(this.blocks) |
|||
this.blocks.style.display = 'none'; |
|||
} |
|||
}; |
|||
}); |
|||
@ -0,0 +1,76 @@ |
|||
var modulePath = './../../../test/specs/block_manager'; |
|||
|
|||
define([ 'BlockManager', |
|||
modulePath + '/view/BlocksView', |
|||
], |
|||
function(BlockManager, BlocksView) { |
|||
|
|||
describe('BlockManager', function() { |
|||
|
|||
describe('Main', function() { |
|||
|
|||
var obj; |
|||
var idTest; |
|||
var optsTest; |
|||
|
|||
beforeEach(function () { |
|||
idTest = 'h1-block'; |
|||
optsTest = { |
|||
label: 'Heading', |
|||
content: '<h1>Test</h1>' |
|||
}; |
|||
obj = new BlockManager(); |
|||
}); |
|||
|
|||
afterEach(function () { |
|||
delete obj; |
|||
}); |
|||
|
|||
it('Object exists', function() { |
|||
obj.should.be.exist; |
|||
}); |
|||
|
|||
it('No blocks inside', function() { |
|||
var coll = obj.getAll(); |
|||
coll.length.should.equal(0); |
|||
}); |
|||
|
|||
it('Add new block', function() { |
|||
var model = obj.add(idTest, optsTest); |
|||
obj.getAll().length.should.equal(1); |
|||
}); |
|||
|
|||
it('Added block has correct data', function() { |
|||
var model = obj.add(idTest, optsTest); |
|||
model.get('label').should.equal(optsTest.label); |
|||
model.get('content').should.equal(optsTest.content); |
|||
}); |
|||
|
|||
it('Add block with attributes', function() { |
|||
optsTest.attributes = {'class':'test'}; |
|||
var model = obj.add(idTest, optsTest); |
|||
model.get('attributes').class.should.equal('test'); |
|||
}); |
|||
|
|||
it('The id of the block is unique', function() { |
|||
var model = obj.add(idTest, optsTest); |
|||
var model2 = obj.add(idTest, {other: 'test'}); |
|||
model.should.deep.equal(model2); |
|||
}); |
|||
|
|||
it('Get block by id', function() { |
|||
var model = obj.add(idTest, optsTest); |
|||
var model2 = obj.get(idTest); |
|||
model.should.deep.equal(model2); |
|||
}); |
|||
|
|||
it('Render blocks', function() { |
|||
obj.render().should.be.ok; |
|||
}); |
|||
|
|||
}); |
|||
|
|||
BlocksView.run(); |
|||
|
|||
}); |
|||
}); |
|||
@ -0,0 +1,90 @@ |
|||
var path = 'BlockManager/view/'; |
|||
define([path + 'BlocksView', 'BlockManager/model/Blocks'], |
|||
function(BlocksView, Blocks) { |
|||
|
|||
return { |
|||
run : function(){ |
|||
describe('BlocksView', function() { |
|||
|
|||
var $fixtures; |
|||
var $fixture; |
|||
var model; |
|||
var view; |
|||
var editorModel; |
|||
var ppfx; |
|||
|
|||
before(function () { |
|||
$fixtures = $("#fixtures"); |
|||
$fixture = $('<div class="devices-fixture"></div>'); |
|||
}); |
|||
|
|||
beforeEach(function () { |
|||
model = new Blocks([]); |
|||
view = new BlocksView({ collection: model }); |
|||
$fixture.empty().appendTo($fixtures); |
|||
$fixture.html(view.render().el); |
|||
}); |
|||
|
|||
afterEach(function () { |
|||
view.collection.reset(); |
|||
}); |
|||
|
|||
after(function () { |
|||
$fixture.remove(); |
|||
}); |
|||
|
|||
it("The container is not empty", function (){ |
|||
view.el.outerHTML.should.be.not.empty; |
|||
}); |
|||
|
|||
it("No children inside", function (){ |
|||
view.el.children.length.should.equal(0); |
|||
}); |
|||
|
|||
it("Render children on add", function (){ |
|||
model.add({}); |
|||
view.el.children.length.should.equal(1); |
|||
model.add([{},{}]); |
|||
view.el.children.length.should.equal(3); |
|||
}); |
|||
|
|||
it("Destroy children on remove", function (){ |
|||
model.add([{},{}]); |
|||
view.el.children.length.should.equal(2); |
|||
model.at(0).destroy(); |
|||
view.el.children.length.should.equal(1); |
|||
}); |
|||
|
|||
describe('With configs', function() { |
|||
|
|||
beforeEach(function () { |
|||
ppfx = 'pfx-t-'; |
|||
editorModel = new Backbone.Model(); |
|||
model = new Blocks([ |
|||
{name:'test1'}, |
|||
{name:'test2'} |
|||
]); |
|||
view = new BlocksView({ |
|||
collection: model, |
|||
},{ |
|||
pStylePrefix: ppfx |
|||
}); |
|||
$fixture.empty().appendTo($fixtures); |
|||
$fixture.html(view.render().el); |
|||
}); |
|||
|
|||
it("Render children", function (){ |
|||
view.el.children.length.should.equal(2); |
|||
}); |
|||
|
|||
it("Render children", function (){ |
|||
view.el.getAttribute('class').should.equal(ppfx + 'blocks-c'); |
|||
}); |
|||
|
|||
}); |
|||
|
|||
}); |
|||
} |
|||
}; |
|||
|
|||
}); |
|||
Loading…
Reference in new issue