Browse Source

Merge branch 'dev'

pull/2/head v0.1.0-alpha
Artur Arseniev 10 years ago
parent
commit
eb8b7bb7e0
  1. 1
      .gitignore
  2. 3
      README.md
  3. 2
      bower.json
  4. 2
      dist/css/grapes.min.css
  5. 16
      dist/grapes.min.js
  6. 3
      package.json
  7. 34
      src/asset_manager/main.js
  8. 45
      src/code_manager/model/HtmlGenerator.js
  9. 22
      src/commands/config/config.js
  10. 7
      src/commands/main.js
  11. 23
      src/commands/view/CommandAbstract.js
  12. 96
      src/commands/view/DeleteComponent.js
  13. 17
      src/commands/view/ImageComponent.js
  14. 45
      src/commands/view/InsertCustom.js
  15. 24
      src/commands/view/MoveComponent.js
  16. 28
      src/commands/view/OpenLayers.js
  17. 53
      src/commands/view/OpenStyleManager.js
  18. 185
      src/commands/view/SelectComponent.js
  19. 288
      src/demo.js
  20. 26
      src/dom_components/config/config.js
  21. 24
      src/dom_components/main.js
  22. 31
      src/dom_components/model/Component.js
  23. 30
      src/dom_components/view/ComponentImageView.js
  24. 95
      src/dom_components/view/ComponentView.js
  25. 21
      src/editor/config/config.js
  26. 180
      src/editor/model/Editor.js
  27. 16
      src/navigator/main.js
  28. 34
      src/navigator/view/ItemView.js
  29. 36
      src/navigator/view/ItemsView.js
  30. 29
      src/style_manager/config/config.js
  31. 4
      src/style_manager/templates/sector.html
  32. 16
      src/style_manager/view/PropertyIntegerView.js
  33. 109
      src/style_manager/view/PropertyView.js
  34. 64
      src/style_manager/view/SectorView.js
  35. 22
      src/style_manager/view/SectorsView.js
  36. 76
      styles/css/main.css
  37. 2
      styles/css/main.css.map
  38. 71
      styles/scss/main.scss

1
.gitignore

@ -6,6 +6,7 @@ style/.sass-cache/
grapes.sublime-project
grapes.sublime-workspace
img/
private/
vendor/
node_modules/

3
README.md

@ -104,6 +104,9 @@ var config = {
// Where to render editor (eg. #myId)
container: '',
// Enable/Disable the possibility to copy (ctrl + c) and paste (ctrl + v) elements
copyPaste : true,
// Enable/Disable undo manager
undoManager: true,

2
bower.json

@ -1,7 +1,7 @@
{
"name": "grapesjs",
"description": "Open source Web Template Editor",
"version": "0.0.51",
"version": "0.1.0",
"author": "Artur Arseniev",
"homepage": "http://grapesjs.com",
"main": [

2
dist/css/grapes.min.css

File diff suppressed because one or more lines are too long

16
dist/grapes.min.js

File diff suppressed because one or more lines are too long

3
package.json

@ -1,10 +1,11 @@
{
"name": "grapesjs",
"description": "Open source Web Template Editor",
"version": "0.0.51",
"version": "0.1.0",
"author": "Artur Arseniev",
"license": "BSD-3-Clause",
"homepage": "http://grapesjs.com",
"main": "dist/grapes.min.js",
"repository": {
"type": "git",
"url": "https://github.com/artf/grapesjs.git"

34
src/asset_manager/main.js

@ -2,7 +2,7 @@ define(function(require) {
/**
* @class AssetManager
* @param {Object} Configurations
*
*
* @return {Object}
* */
var AssetManager = function(config)
@ -13,58 +13,62 @@ define(function(require) {
AssetsView = require('./view/AssetsView'),
FileUpload = require('./view/FileUploader');
for (var name in defaults) {
for (var name in defaults) {
if (!(name in c))
c[name] = defaults[name];
}
this.assets = new Assets(c.assets);
var obj = {
collection : this.assets,
config : c,
};
this.am = new AssetsView(obj);
this.fu = new FileUpload(obj);
};
AssetManager.prototype = {
/**
* Get collection of assets
*
*
* @return {Object}
* */
getAssets : function(){
return this.assets;
},
/**
* Set new target
* @param {Object} m Model
*
*
* @return void
* */
setTarget : function(m){
this.am.collection.target = m;
},
/**
* Set callback after asset was selected
* @param {Object} f Callback function
*
*
* @return void
* */
onSelect : function(f){
this.am.collection.onSelect = f;
},
render : function(){
if(!this.rendered)
/**
* Render
* @param {Boolean} f Force to render
*/
render : function(f){
if(!this.rendered || f)
this.rendered = this.am.render().$el.add(this.fu.render().$el);
return this.rendered;
},
};
return AssetManager;
});

45
src/code_manager/model/HtmlGenerator.js

@ -1,39 +1,50 @@
define(['backbone'],
define(['backbone'],
function (Backbone) {
/**
* @class HtmlGenerator
* */
return Backbone.Model.extend({
/** @inheritdoc */
getId : function(){
return 'html';
getId : function(){
return 'html';
},
/** @inheritdoc */
build: function(model){
var coll = model.get('components') || model,
code = '';
coll.each(function(m){
var tag = m.get('tagName'), // Tag name
attr = '', // Attributes string
cln = m.get('components'); // Children
var tag = m.get('tagName'), // Tag name
sTag = 0, // Single tag
attr = '', // Attributes string
cln = m.get('components'); // Children
_.each(m.get('attributes'),function(value, prop){
if(prop == 'onmousedown')
return;
attr += value && prop!='style' ? ' ' + prop + '="' + value + '" ' : '';
});
code += '<'+tag+' id="'+m.cid+'"' + attr + '>' + m.get('content');
if(m.get('type') == 'image'){
tag = 'img';
sTag = 1;
attr += 'src="' + m.get('src') + '"';
}
code += '<'+tag+' id="'+m.cid+'"' + attr + (sTag ? '/' : '') + '>' + m.get('content');
if(cln.length)
code += this.build(cln);
code += '</'+tag+'>';
if(!sTag)
code += '</'+tag+'>';
}, this);
return code;
},
});
});

22
src/commands/config/config.js

@ -1,25 +1,25 @@
define(function () {
return {
ESCAPE_KEY : 27,
stylePrefix : 'com-',
defaults : [],
// Editor model
em : null,
// If true center new first-level components
firstCentered : true,
// If true the new component will created with 'height', else 'min-height'
newFixedH : false,
newFixedH : false,
// Minimum height (in px) of new component
minComponentH : 50,
// Minimum width (in px) of component on creation
minComponentW : 50,
// Minimum width (in px) of component on creation
minComponentW : 50,
};
});

7
src/commands/main.js

@ -20,6 +20,13 @@ define(function(require) {
this.config = c;
this.Abstract = AbsCommands;
// Load commands passed by configuration
for( var k in c.defaults){
var obj = c.defaults[k];
if(obj.id)
this.add(obj.id, obj);
}
this.defaultCommands = {};
this.defaultCommands['select-comp'] = require('./view/SelectComponent');
this.defaultCommands['create-comp'] = require('./view/CreateComponent');

23
src/commands/view/CommandAbstract.js

@ -1,34 +1,35 @@
define(['backbone'],
function(Backbone) {
/**
/**
* @class CommandAbstract
* */
return Backbone.View.extend({
/**
* Initialize method that can't be removed
* @param {Object} o Options
* */
initialize: function(o) {
this.config = o;
this.editorModel = this.em = o.em || {};
this.canvasId = o.canvasId || '';
this.canvasId = o.canvasId || '';
this.wrapperId = o.wrapperId || 'wrapper';
this.pfx = o.stylePrefix;
this.pfx = o.stylePrefix;
this.hoverClass = this.pfx + 'hover';
this.badgeClass = this.pfx + 'badge';
this.plhClass = this.pfx + 'placeholder';
this.plhClass = this.pfx + 'placeholder';
this.setElement(this.editorModel.get('$editor').find('#'+this.canvasId));
this.$canvas = this.$el;
this.$wrapper = this.$canvas.find('#'+this.wrapperId);
this.$canvas = this.$el;
this.$wrapper = this.$canvas.find('#'+this.wrapperId);
this.init(o);
},
/**
* Callback triggered after initialize
* @param {Object} o Options
* */
init: function(o){},
/**
* Method that run command
* @param {Object} em Editor model
@ -37,7 +38,7 @@ define(['backbone'],
run: function(em, sender) {
console.warn("No run method found");
},
/**
* Method that stop command
* @param {Object} em Editor model
@ -46,6 +47,6 @@ define(['backbone'],
stop: function(em, sender) {
console.warn("No stop method found");
}
});
});

96
src/commands/view/DeleteComponent.js

@ -1,55 +1,83 @@
define(['backbone', './SelectComponent'],
function(Backbone, SelectComponent) {
/**
/**
* @class DeleteComponent
* */
return _.extend({},SelectComponent,{
init: function(o){
_.bindAll(this, 'startDelete', 'stopDelete', 'onDelete');
this.hoverClass = this.pfx + 'hover-delete';
this.badgeClass = this.pfx + 'badge-red';
},
enable: function(){
enable: function()
{
var that = this;
this.$el.find('*').mouseover(function (e){
e.stopPropagation();
if($(this).data('model').get('removable')){ //Show badge if possible
$(this).addClass(that.hoverClass);
that.attachBadge(this);
}
}).mouseout(function (e){ //hover out
e.stopPropagation();
$(this).removeClass(that.hoverClass);
if(that.badge) //Hide badge if possible
that.badge.css({ left: -1000, top:-1000 });
}).click(function(e){
that.onSelect(e,this); //Callback on select
});
this.$el.find('*')
.mouseover(this.startDelete)
.mouseout(this.stopDelete)
.click(this.onDelete);
},
/**
* Say what to do after the component was selected
* @param Event
* @param Object Selected element
* */
onSelect: function(e, el){
/**
* Start command
* @param {Object} e
*/
startDelete: function(e)
{
e.stopPropagation();
var $this = $(e.target);
// Show badge if possible
if($this.data('model').get('removable')){
$this.addClass(this.hoverClass);
this.attachBadge($this.get(0));
}
},
/**
* Stop command
* @param {Object} e
*/
stopDelete: function(e)
{
e.stopPropagation();
var $this = $(e.target);
$this.removeClass(this.hoverClass);
// Hide badge if possible
if(this.badge)
this.badge.css({ left: -1000, top:-1000 });
},
/**
* Delete command
* @param {Object} e
*/
onDelete: function(e)
{
e.stopPropagation();
var $selected = $(el);
if(!$selected.data('model').get('removable')) //Do nothing in case can't remove
var $this = $(e.target);
// Do nothing in case can't remove
if(!$this.data('model').get('removable'))
return;
$selected.data('model').destroy();
$this.data('model').destroy();
this.removeBadge();
this.clean();
},
/**
/**
* Updates badge label
* @param Object Model
* @return void
* @param {Object} model
* */
updateBadgeLabel: function (model){
this.badge.html( 'Remove '+model.getName() );
updateBadgeLabel: function (model)
{
this.badge.html( 'Remove ' + model.getName() );
},
});
});

17
src/commands/view/ImageComponent.js

@ -1,37 +1,40 @@
define(['backbone', './InsertCustom'],
function(Backbone, InsertCustom) {
/**
/**
* @class ImageComponent
* */
return _.extend({}, InsertCustom, {
/**
* Trigger before insert
* @param {Object} object
*
*
* */
beforeInsert: function(object){
object.type = 'image';
object.style = {};
object.attributes = {};
if (!this.nearToFloat()) {
object.style.display = 'block';
}
// This allow to avoid 'ghosts' on drag
object.attributes.onmousedown = 'return false';
if (this.config.firstCentered && (this.$wp.get(0) == this.posTargetEl.get(0)) ) {
object.style.margin = '0 auto';
}
},
/**
* Trigger after insert
* @param {Object} model Model created after insert
*
*
* */
afterInsert: function(model){
model.trigger('dblclick');
if(this.sender)
this.sender.set('active', false);
},
});
});

45
src/commands/view/InsertCustom.js

@ -1,30 +1,31 @@
define(['backbone', './SelectPosition'],
function(Backbone, SelectPosition) {
/**
/**
* @class InsertCustom
* */
return _.extend({}, SelectPosition, {
/**
* Run method
/**
* Run method
* */
run: function(em, sender){
this.enable();
this.em = em;
this.sender = sender;
this.opt = sender.get('options') || {};
this.opt = sender.get('options') || {};
this.content = this.opt.content;
},
enable: function(){
SelectPosition.enable.apply(this, arguments);
_.bindAll(this,'insertComponent');
this.$wp = this.$wrapper;
this.$wp.on('click', this.insertComponent);
},
/**
/**
* Start insert event
*
*
* @return void
* */
insertComponent: function(){
@ -32,41 +33,45 @@ define(['backbone', './SelectPosition'],
this.stopSelectPosition();
this.removePositionPlaceholder();
var object = this.buildContent();
this.beforeInsert(object);
var model = this.posTargetCollection.add(object, { at: this.posIndex, silent:false });
this.beforeInsert(object);
var model = this.posTargetCollection.add(object, { at: this.posIndex, silent:false });
if(this.opt.terminateAfterInsert && this.sender)
this.sender.set('active',false);
else
this.enable();
if(this.em)
this.em.initChildrenComp(model);
this.afterInsert(model, this);
},
/**
* Trigger before insert
* @param {Object} obj
*
*
* @return void
* */
beforeInsert: function(obj){},
/**
* Trigger after insert
* @param {Object} model Model created after insert
*
*
* @return void
* */
afterInsert: function(model){},
/**
/**
* Create different object, based on content, to insert inside canvas
*
*
* @return {Object}
* */
buildContent: function(){
var result = {};
if(typeof this.content === 'string'){
result = {
content : this.content,
result = {
content : this.content,
tagName : 'span',
};
}else if(typeof this.content === 'object'){

24
src/commands/view/MoveComponent.js

@ -6,7 +6,8 @@ define(['backbone', './SelectComponent','./SelectPosition'],
return _.extend({},SelectComponent, SelectPosition,{
init: function(o){
_.bindAll(this,'startMove','onMove','endMove','rollback','selectingPosition','itemLeft');//to mantein 'this' context
SelectComponent.init.apply(this, arguments);
_.bindAll(this,'startMove','onMove','endMove','rollback','selectingPosition','itemLeft');
this.opt = o;
this.hoverClass = this.pfx + 'hover-move';
this.badgeClass = this.pfx + 'badge-yellow';
@ -19,20 +20,23 @@ define(['backbone', './SelectComponent','./SelectPosition'],
this.$el.css('cursor','move');
this.$el.on('mousedown', this.startMove);
this.startSelectComponent();
//Avoid strange moving behavior
this.$el.addClass(this.noSelClass);
},
/** Highlight component when pointer is over it
* @param Event
* @param Object Component
* @return void
* */
highlightComponent: function(e, el){
/**
* Hover command
* @param {Object} e
*/
onHover: function(e)
{
e.stopPropagation();
if($(el).data('model').get('movable')){ //Show badge if possible
$(el).addClass(this.hoverClass);
this.attachBadge(el);
var $this = $(e.target);
if($this.data('model').get('movable')){ //Show badge if possible
$this.addClass(this.hoverClass);
this.attachBadge(e.target);
}
},

28
src/commands/view/OpenLayers.js

@ -1,31 +1,33 @@
define(['Navigator'], function(Layers) {
/**
/**
* @class OpenStyleManager
* */
return {
run: function(em, sender)
{
if(!this.$layers){
var collection = em.get('Components').getComponent().get('components'),
config = em.get('Config'),
panels = em.get('Panels'),
lyStylePfx = config.layers.stylePrefix || 'nv-';
config = em.get('Config'),
panels = em.get('Panels'),
lyStylePfx = config.layers.stylePrefix || 'nv-';
config.layers.stylePrefix = config.stylePrefix + lyStylePfx;
var layers = new Layers(collection, config.layers);
this.$layers = layers.render();
config.layers.em = em;
var layers = new Layers(collection, config.layers);
this.$layers = layers.render();
// Check if panel exists otherwise crate it
if(!panels.getPanel('views-container'))
this.panel = panels.addPanel({ id: 'views-container'});
this.panel = panels.addPanel({ id: 'views-container'});
else
this.panel = panels.getPanel('views-container');
this.panel = panels.getPanel('views-container');
this.panel.set('appendContent', this.$layers).trigger('change:appendContent');
}
this.$layers.show();
},
stop: function()
{
if(this.$layers)

53
src/commands/view/OpenStyleManager.js

@ -1,36 +1,65 @@
define(['StyleManager'], function(StyleManager) {
/**
/**
* @class OpenStyleManager
* */
return {
run: function(em, sender)
{
this.sender = sender;
if(!this.$sm){
var config = em.get('Config'),
panels = em.get('Panels'),
smStylePfx = config.styleManager.stylePrefix || 'sm-';
config.styleManager.stylePrefix = config.stylePrefix + smStylePfx;
panels = em.get('Panels'),
pfx = config.styleManager.stylePrefix || 'sm-';
config.styleManager.stylePrefix = config.stylePrefix + pfx;
config.styleManager.target = em;
var sm = new StyleManager(config.styleManager);
this.$sm = sm.render();
if(!panels.getPanel('views-container'))
this.panel = panels.addPanel({ id: 'views-container'});
else
this.panel = panels.getPanel('views-container');
this.panel.set('appendContent', this.$sm).trigger('change:appendContent');
// Create header
this.$header = $('<div>', {
class : config.styleManager.stylePrefix + 'header',
text : config.styleManager.textNoElement,
});
// Add all to the panel
this.panel.set('appendContent', this.$sm.add(this.$header) ).trigger('change:appendContent');
this.target = em;
this.listenTo( this.target ,'change:selectedComponent', this.toggleSm);
}
this.$sm.show();
this.toggleSm();
},
/**
* Toggle Style Manager visibility
*/
toggleSm: function()
{
if(!this.sender.get('active'))
return;
if(this.target.get('selectedComponent')){
this.$sm.show();
this.$header.hide();
}else{
this.$sm.hide();
this.$header.show();
}
},
stop: function()
{
if(this.$sm)
this.$sm.hide();
if(this.$header)
this.$header.hide();
}
};
});

185
src/commands/view/SelectComponent.js

@ -1,24 +1,96 @@
define(function() {
/**
/**
* @class SelectComponent
* */
return {
enable: function(){
init: function(o){
_.bindAll(this, 'onHover', 'onOut', 'onClick');
},
enable: function()
{
_.bindAll(this,'copyComp','pasteComp');
var confMain = this.config.em.get('Config');
this.startSelectComponent();
if(confMain.copyPaste){
key('⌘+c, ctrl+c', this.copyComp);
key('⌘+v, ctrl+v', this.pasteComp);
}
},
/**
* Copy component to clipboard
*/
copyComp: function()
{
var sel = this.editorModel.get('selectedComponent');
if(sel && sel.get('copyable'))
this.editorModel.set('clipboard', sel);
},
/**
* Paste component from clipboard
*/
pasteComp: function()
{
var clp = this.editorModel.get('clipboard'),
sel = this.editorModel.get('selectedComponent');
if(clp && sel && sel.collection){
var index = sel.collection.indexOf(sel),
clone = clp.clone();
sel.collection.add(clone, { at: index + 1 });
}
},
/** Start select component event
* @return void
* */
startSelectComponent: function(){
var that = this;
this.$el.find('*').on('mouseover',function(e){ that.highlightComponent(e,this); })
.on('mouseout' ,function(e){ that.removeHighlightComponent(e,this); })
.on('click' ,function(e){ that.selectComponent(e,this); });
this.$el.find('*')
.on('mouseover',this.onHover)
.on('mouseout', this.onOut)
.on('click', this.onClick);
this.selEl = this.$el.find('*');
},
/**
* Hover command
* @param {Object} e
*/
onHover: function(e)
{
e.stopPropagation();
$(e.target).addClass(this.hoverClass);
this.attachBadge(e.target);
},
/**
* Out command
* @param {Object} e
*/
onOut: function(e)
{
e.stopPropagation();
$(e.target).removeClass(this.hoverClass);
if(this.badge)
this.badge.css({ left: -10000, top:-10000 });
},
/**
* Hover command
* @param {Object} e
*/
onClick: function(e)
{
var s = $(e.target).data('model').get('stylable');
if(!(s instanceof Array) && !s)
return;
this.onSelect(e, e.target);
},
/** Stop select component event
* @param Event
* @return void
@ -28,64 +100,32 @@ define(function() {
this.selEl.trigger('mouseout').off('mouseover mouseout click');
this.selEl = null;
},
/** Highlight component when pointer is over it
* @param Event
* @param Object Component
* @return void
* */
highlightComponent: function(e, el){
e.stopPropagation();
$(el).addClass(this.hoverClass);
this.attachBadge(el);
},
/** Remove highlight from component
* @param Event
* @param Object Component
* @return void
* */
removeHighlightComponent: function(e, el){
e.stopPropagation();
$(el).removeClass(this.hoverClass);
if(this.badge) //Hide badge if possible
this.badge.css({ left: -10000, top:-10000 }); //TODO HIDE
},
/** Select highlighted component
* @param Event
* @param Object Component
* @return void
* */
selectComponent: function(e, el){
var s = $(el).data('model').get('stylable');
if(!(s instanceof Array) && !s)
return;
this.onSelect(e,el); //Callback on select
},
/** Say what to do after the component was selected
* @param Event
* @param Object Selected element
/**
* Say what to do after the component was selected
* @param {Object} e
* @param {Object} el
* */
onSelect: function(e, el){
onSelect: function(e, el)
{
e.stopPropagation();
if(this.$selected) //Check if already selected before
this.$selected.removeClass('selected-component');
this.$selected = $(el).addClass('selected-component');
if(this.$selected.data('model')){
// Generates too much recursions with JsonGenerator
//this.$selected.data('model').set('previousModel',this.editorModel.get('selectedComponent'));
this.editorModel.set('selectedComponent',this.$selected.data('model')); //Update selected component
this.$selected.data('model').set('status','selected');
var md = this.editorModel.get('selectedComponent');
if(md)
md.set('status','');
var nMd = $(el).data('model');
if(nMd){
this.editorModel.set('selectedComponent', nMd);
nMd.set('status','selected');
}
},
/** Removes all highlighting effects on components
* @return void
* */
clean: function(){
this.$el.find('*').removeClass(this.hoverClass);
},
/** Attach badge to component
* @param Object Component
* @return void
@ -111,24 +151,24 @@ define(function() {
relativeT -= badgeH;
this.badge.css({ left: relativeL, top:relativeT });
},
/** Create badge for the component
* @return void
* */
createBadge: function (){
this.badge = $('<div>', {class: this.badgeClass + " no-dots"}).appendTo(this.$wrapper);
},
/** Remove badge
* @return void
* */
removeBadge: function (){
if(this.badge){
if(this.badge){
this.badge.remove();
delete this.badge;
}
},
/** Updates badge label
* @param Object Model
* @return void
@ -137,28 +177,29 @@ define(function() {
if(model)
this.badge.html( model.getName() );
},
/** Run method
/**
* Run method
* */
run: function(){
run: function(em, sender){
this.enable();
this.render();
this.active = true;
},
/** Stop method
/**
* Stop method
* */
stop: function(){
if(this.editorModel.get('selectedComponent'))
this.editorModel.get('selectedComponent').set('status','');
var sel = this.editorModel.get('selectedComponent');
if(sel)
sel.set('status','');
this.$el.unbind(); //removes all attached events
if(this.$selected) //check if already selected before
this.$selected.removeClass('selected-component');
this.removeBadge();
this.removeBadge();
this.clean();
this.$el.find('*').unbind('mouseover').unbind('mouseout').unbind('click');
this.editorModel.set('selectedComponent',null);
this.active = false;
key.unbind('⌘+c, ctrl+c');
key.unbind('⌘+v, ctrl+v');
}
};
});

288
src/demo.js

@ -1,7 +1,9 @@
require(['src/config/require-config.js'], function() {
require(['editor/main'],function (Grapes){
var grapes = new Grapes({
var grapes = new Grapes(
{
container : '#wte-app',
@ -13,6 +15,184 @@ require(['src/config/require-config.js'], function() {
paramsStore : { type:'homeTemplate',},
paramsLoad : { type:'homeTemplate',},
},
components: {
defaults : [
{
style: {'width':'100%', 'min-height':'550px', 'background':'url("./img/bg-gr-v.png") repeat left top scroll, url("http://www.freewhd.com/wp-content/uploads/2014/01/work-desk-14949.jpg") no-repeat center center scroll'},
components: [
{
style: {'width':'90%', 'max-width':'1100px', 'min-height':'75px', 'padding':'7px 7px 7px 7px', 'margin':'0 auto'},
components: [
{
style: {'width':'100%','padding':'25px 7px 7px 7px'},
components: [
{
style: {'width':'50%','min-height':'75px','padding':'7px 7px 7px 7px','float':'left'},
components:[
{ type: 'text', content: 'GrapesJS', style:{'padding':'10px 10px 10px 10px', 'width':'130px', 'min-height':'50px', 'background-color':'#ffffff', 'border-radius':'5px', 'color':'#4d114f', 'font-size':'23px', 'text-align':'center', 'line-height':'30px'}}
]
},
{
style: {'width':'50%','min-height':'75px','padding':'7px 7px 7px 7px','float':'left'},
components: [
{
style: {'float':'right', 'padding':'7px 7px 7px 7px'},
components: [
{ type: 'text', content: 'WEB', style:{'padding': '10px 10px 10px 10px', 'width': '130px', 'min-height': '50px', 'float': 'left', 'color': '#ffffff', 'text-align': 'center', 'font-size': '15px', 'line-height':'30px'} },
{ type: 'text', content: 'TEMPLATE', style:{'padding': '10px 10px 10px 10px', 'width': '130px', 'min-height': '50px', 'float': 'left', 'color': '#ffffff', 'text-align': 'center', 'font-size': '15px', 'line-height':'30px'} },
{ type: 'text', content: 'EDITOR', style:{'padding': '10px 10px 10px 10px', 'width': '130px', 'min-height': '50px', 'float': 'left', 'color': '#ffffff', 'text-align': 'center', 'font-size': '15px', 'line-height':'30px'} },
]
},
]
},
{style: {'clear':'both'}}
]
},
{
type: 'text',
content: 'Build your templates without coding',
style: { 'padding': '7px 7px 7px 7px', 'width':'670px', 'min-height':'57px', 'font-size':'40px', 'color':'#ffffff', 'font-family':'Helvetica, serif', 'font-weight':100, 'margin':'100px 0px 0px 0px'}
},
{
type: 'text',
content: 'All text blocks could be edited easily with double clicking on it. You can create new text blocks with the command from the left panel',
style: { 'padding':'10px 10px 10px 10px', 'width':'599px', 'min-height':'80px', 'color':'#c6c6c6', 'font-family':'Helvetica, serif', 'font-weight':100, 'line-height':'26px'}
},
{
type: 'text',
content: 'Try it now',
style: {'padding':'10px 10px 10px 10px', 'width':'190px', 'min-height':'50px', 'font-weight':100, 'color':'#ffffff', 'font-size':'20px', 'text-align':'center', 'letter-spacing':'3px', 'line-height':'30px', 'background-color':'#d983a6', 'border-radius':'5px', 'margin':'15px 0px 0px 0px'}
}
]
},
]
},
{
style: {'min-height': '200px', 'background-color':'#ffffff'},
components:[
{
style: {'width':'90%', 'max-width':'1100px', 'min-height':'75px', 'padding':'100px 7px 7px 7px', 'margin':'0 auto'},
components: [
{ type: 'image', src: './img/phone-app.png', attributes: {'onmousedown': 'return false'}, style: { 'float': 'left'}},
{
style: { 'float': 'left', 'margin':'150px 0px 0px 100px', 'padding':'7px 7px 7px 7px' },
components: [
{
type: 'text', content: 'ASSET MANAGER',
style: {'padding':'7px 7px 7px 7px', 'min-height':'35px', 'color':'#b1b1b1', 'font-size':'15px'}
},
{
type: 'text', content: 'Manage your images with Asset Manager',
style: {'padding':'7px 7px 7px 7px', 'min-height':'35px', 'color':'#444444', 'font-size':'25px'}
},
{
type: 'text', content: 'You can create image blocks with the command from the left panel and edit them with double click',
style: {'padding':'7px 7px 7px 7px', 'min-height':'35px', 'color':'#444444', 'font-size':'17px', 'line-height':'25px','font-weight':100, 'width':'450px'}
},
{
type: 'text', content: 'At the moment uploading of new images is not allowed in demo, so there is only some random images.',
style: {'padding':'7px 7px 7px 7px', 'min-height':'35px', 'color':'#444444', 'font-size':'13px', 'line-height':'20px','font-weight':100, 'width':'450px'}
}
]
},
{style: {'clear':'both'}}
]
}
]
},
{
style: {'min-height': '500px', 'background-color':'#222222'},
components: [
{
style: {'width':'90%', 'max-width':'1100px', 'min-height':'75px', 'padding':'70px 7px 70px 7px', 'margin':'0 auto'},
components: [
{
type: 'text', content: 'Blocks',
style: {'padding':'7px 7px 7px 7px', 'min-height':'35px', 'color':'#fff', 'font-size':'25px','text-align':'center'}
},
{
type: 'text', content: 'Each element of the HTML page could be seen as a block. On the left panel you could find different kind of blocks that you can create, move and style',
style: {'padding':'7px 7px 7px 7px', 'min-height':'35px', 'color':'#b1b1b1', 'font-size':'15px', 'text-align':'center', 'width':'700px', 'margin':'0 auto', 'font-weight':100 }
},
{
style: {'margin':'70px 0 0 0','padding':'7px 7px 7px 7px'},
components: [
{
style: {'width':'33.333%','min-height':'75px','padding':'7px 7px 7px 7px','float':'left'},
components:[
{
style: {'margin': '0 auto', 'width':'300px', 'min-height':'350px','padding':'0 20px 0 20px','background-color':'#d983a6','border-radius':'5px'},
components: [
{ type: 'text', content:'Small', style:{ 'font-weight':100, 'color':'#ffffff', 'letter-spacing':'3px', 'text-align':'center', 'font-size':'25px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.1)','padding':'20px 20px 20px 20px'}},
{ type: 'text', content:'Some random list', style:{ 'font-weight':100, 'color':'#ffffff', 'letter-spacing':'3px', 'text-align':'center', 'font-size':'15px', 'margin':'0 -20px 0 -20px','padding':'50px 20px 50px 20px'}},
{ type: 'text', content:'+ Small feature 1', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.1)','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'+ Small feature 2', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'+ Small feature 3', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.1)','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'+ Small feature 4', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'Price 1', style:{ 'font-weight':100, 'color':'#ffffff', 'text-align':'center', 'font-size':'30px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.2)','padding':'40px 20px 40px 20px'}},
]
}
]
},
{
style: {'width':'33.333%','min-height':'75px','padding':'7px 7px 7px 7px','float':'left'},
components:[
{
style: {'margin': '0 auto', 'width':'300px', 'min-height':'350px','padding':'0 20px 0 20px','background-color':'#da78a0','border-radius':'5px'},
components: [
{ type: 'text', content:'Medium', style:{ 'font-weight':100, 'color':'#ffffff', 'letter-spacing':'3px', 'text-align':'center', 'font-size':'25px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.1)','padding':'20px 20px 20px 20px'}},
{ type: 'text', content:'Some random list', style:{ 'font-weight':100, 'color':'#ffffff', 'letter-spacing':'3px', 'text-align':'center', 'font-size':'15px', 'margin':'0 -20px 0 -20px','padding':'50px 20px 50px 20px'}},
{ type: 'text', content:'+ Medium feature 1', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.1)','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'+ Medium feature 2', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'+ Medium feature 3', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.1)','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'+ Medium feature 4', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'Price 2', style:{ 'font-weight':100, 'color':'#ffffff', 'text-align':'center', 'font-size':'30px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.2)','padding':'40px 20px 40px 20px'}},
]
}
]
},
{
style: {'width':'33.333%','min-height':'75px','padding':'7px 7px 7px 7px','float':'left'},
components:[
{
style: {'margin': '0 auto', 'width':'300px', 'min-height':'350px','padding':'0 20px 0 20px','background-color':'#d66a96','border-radius':'5px'},
components: [
{ type: 'text', content:'Large', style:{ 'font-weight':100, 'color':'#ffffff', 'letter-spacing':'3px', 'text-align':'center', 'font-size':'25px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.1)','padding':'20px 20px 20px 20px'}},
{ type: 'text', content:'Some random list', style:{ 'font-weight':100, 'color':'#ffffff', 'letter-spacing':'3px', 'text-align':'center', 'font-size':'15px', 'margin':'0 -20px 0 -20px','padding':'50px 20px 50px 20px'}},
{ type: 'text', content:'+ Large feature 1', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.1)','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'+ Large feature 2', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'+ Large feature 3', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.1)','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'+ Large feature 4', style:{ 'font-weight':100, 'color':'rgba(255,255,255,0.5)', 'letter-spacing':'2px', 'font-size':'15px', 'margin':'0 -20px 0 -20px','padding':'10px 20px 10px 20px'}},
{ type: 'text', content:'Price 3', style:{ 'font-weight':100, 'color':'#ffffff', 'text-align':'center', 'font-size':'30px', 'margin':'0 -20px 0 -20px', 'background-color': 'rgba(0, 0, 0, 0.2)','padding':'40px 20px 40px 20px'}},
]
}
]
},//#d8779e #d86895
{style: {'clear':'both'}}
]
},
]
}
]
}
],
},
commands: {
defaults : [{
id: 'open-github',
run: function(em, sender){
sender.set('active',false);
window.open('https://github.com/artf/grapesjs','_blank');
},
stop: function(){}
}],
},
assetManager: {
storageType : '',
storeOnChange : true,
@ -25,6 +205,9 @@ require(['src/config/require-config.js'], function() {
{ type: 'image', src : 'http://placehold.it/350x250/f28c33/fff/image5.jpg', date: '2015-02-01',height:350, width:250},
{ type: 'image', src : 'http://placehold.it/350x250/e868a2/fff/image6.jpg', date: '2015-02-01',height:350, width:250},
{ type: 'image', src : 'http://placehold.it/350x250/cc4360/fff/image7.jpg', date: '2015-02-01',height:350, width:250},
{ type: 'image', src : 'http://www.freewhd.com/wp-content/uploads/2014/01/work-desk-14949.jpg', date: '2015-02-01',height:1080, width:1728},
{ type: 'image', src : './img/phone-app.png', date: '2015-02-01',height:650, width:320},
{ type: 'image', src : './img/bg-gr-v.png', date: '2015-02-01',height:1, width:1728},
]
},
@ -35,36 +218,61 @@ require(['src/config/require-config.js'], function() {
id : 'select',
className : 'fa fa-mouse-pointer',
command : 'select-comp',
attributes : { title : 'Select' }
attributes : { title : 'Select element' }
},{
id : 'create',
className : 'fa fa-plus-square-o',
id : 'create',
className : 'fa fa-plus-square-o icon-add-comp',
command : 'create-comp',
attributes : { title : 'Create' },
buttons : [
{ id: 'create2', className: 'fa fa-plus-square-o', command: 'create-comp', attributes: { title: 'Create' },},
{ id: 'box100', className: 'fa fa-square-o', command: 'insert-custom',
attributes : { title : 'Create all-width box' },
attributes : { title : 'Create element' },
buttons : [
{ id: 'create2', className: 'fa fa-plus-square-o icon-add-comp', command: 'create-comp', attributes: { title: 'Create element' },},
{ id: 'comp100', className: 'fa fa-square-o icon-comp100', command: 'insert-custom',
attributes : { title : 'Create all-width element' },
options: {
content : { style: { width: '100%', 'min-height': '75px', 'padding': '7px'}},
terminateAfterInsert : false,
},
},{ id: 'comp50', className: 'fa fa-square-o icon-comp50', command: 'insert-custom',
attributes : { title : 'Create 2 columns element' },
options: {
content : { style: { width: '100%', 'min-height': '75px'}},
terminateAfterInsert : false,
},},
]
content : { style: { width: '100%', 'padding': '7px'},//, 'display': 'table'
components: [
{style: {width: '50%', 'min-height': '75px', 'padding': '7px', 'float':'left' }},
{style: {width: '50%', 'min-height': '75px', 'padding': '7px', 'float':'left' }},
{style: {clear:'both'}},
]
},
},
},{ id: 'comp30', className: 'fa fa-square-o icon-comp30', command: 'insert-custom',
attributes : { title : 'Create 3 columns element' },
options: {
content : { style: { width: '100%', 'padding': '7px'},//, 'display': 'table'
components: [
{style: {width: '33.333%', 'min-height': '75px', 'padding': '7px', 'float':'left' }},
{style: {width: '33.333%', 'min-height': '75px', 'padding': '7px', 'float':'left' }},
{style: {width: '33.333%', 'min-height': '75px', 'padding': '7px', 'float':'left' }},
{style: {clear:'both'}},
]
},
},
},
]
},
{ id: 'remove', className: 'fa fa-trash-o', command: 'delete-comp', attributes : { title: 'Remove' }, },
{ id: 'move', className: 'fa fa-arrows', command: 'move-comp', attributes : { title: 'Move' }, },
{ id: 'remove', className: 'fa fa-trash-o icon-rm', command: 'delete-comp', attributes : { title: 'Remove element' }, },
{ id: 'move', className: 'fa fa-arrows', command: 'move-comp', attributes : { title: 'Move elements' }, },
//{ id: 'resize', className: 'fa fa-arrows-alt', command: 'resize-comp', attributes : { title: 'Resize' }, },
{ id: 'text', className: 'fa fa-font' , command: 'text-comp', attributes : { title: 'Text' }, },
{ id: 'image', className: 'fa fa-picture-o', command: 'image-comp', attributes : { title: 'Image' }, },
{ id: 'var', className: 'fa fa-hashtag', command: 'insert-custom',attributes : { title: 'Some variable' },
options: { content: '{{ VAR11 }}', terminateAfterInsert: true, },
},
{ id: 'text', className: 'fa fa-font' , command: 'text-comp', attributes : { title: 'Create text element' }, },
{ id: 'image', className: 'fa fa-picture-o', command: 'image-comp', attributes : { title: 'Create image element' }, },
/*{ id: 'var', className: 'fa fa-hashtag', command: 'insert-custom',attributes : { title: 'Some variable' },
options: { content: '{{ VAR11 }}', terminateAfterInsert: true, },
},*/
],
},{
id : 'options',
buttons : [
{ id: 'visibility', className: 'fa fa-eye', command: 'sw-visibility', active: true, context: 'sw-visibility', attributes: { title: 'View components' }, },
{ id: 'export', className: 'fa fa-code', command: 'export-template', attributes: { title: 'View code' }, },
{ id: 'view-github', className: 'fa fa-github', command: 'open-github', attributes: { title: 'View on Github' }, },
],
},{
id : 'views',
@ -158,6 +366,7 @@ require(['src/config/require-config.js'], function() {
}],
},{
name: 'Dimension',
open: false,
properties:[{
name : 'Width',
property : 'width',
@ -263,6 +472,7 @@ require(['src/config/require-config.js'], function() {
},],
},{
name: 'Typography',
open: false,
properties:[{
name : 'Font',
property : 'font-family',
@ -271,61 +481,61 @@ require(['src/config/require-config.js'], function() {
list : [{
value : 'Arial, Helvetica, sans-serif',
name : 'Arial',
style : 'font-family: Arial, Helvetica, sans-serif',
style : 'font-family: Arial, Helvetica, sans-serif; font-size:15px;',
},{
value : '"Arial Black", Gadget, sans-serif',
style : 'font-family: "Arial Black", Gadget, sans-serif',
style : 'font-family: "Arial Black", Gadget, sans-serif; font-size:15px;',
name : 'Arial Black',
},{
value : '"Brush Script MT", sans-serif',
style : 'font-family: "Brush Script MT", sans-serif',
style : 'font-family: "Brush Script MT", sans-serif; font-size:15px;',
name : 'Brush Script MT',
},{
value : '"Comic Sans MS", cursive, sans-serif',
style : 'font-family: "Comic Sans MS", cursive, sans-serif',
style : 'font-family: "Comic Sans MS", cursive, sans-serif; font-size:15px;',
name : 'Comica Sans',
},{
value : '"Courier New", Courier, monospace',
style : 'font-family: "Courier New", Courier, monospace',
style : 'font-family: "Courier New", Courier, monospace; font-size:15px;',
name : 'Courier New',
},{
value : 'Georgia, serif',
style : 'font-family: Georgia, serif',
style : 'font-family: Georgia, serif; font-size:15px;',
name : 'Georgia',
},{
value : 'Helvetica, serif',
style : 'font-family: Helvetica, serif',
style : 'font-family: Helvetica, serif; font-size:15px;',
name : 'Helvetica',
},{
value : 'Impact, Charcoal, sans-serif',
style : 'font-family: Impact, Charcoal, sans-serif',
style : 'font-family: Impact, Charcoal, sans-serif; font-size:15px;',
name : 'Impact',
},{
value : '"Lucida Sans Unicode", "Lucida Grande", sans-serif',
style : 'font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif',
style : 'font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; font-size:15px;',
name : 'Lucida Sans',
},{
value : 'Tahoma, Geneva, sans-serif',
style : 'font-family: Tahoma, Geneva, sans-serif',
style : 'font-family: Tahoma, Geneva, sans-serif; font-size:15px;',
name : 'Tahoma',
},{
value : '"Times New Roman", Times, serif',
style : 'font-family: "Times New Roman", Times, serif',
style : 'font-family: "Times New Roman", Times, serif; font-size:15px;',
name : 'Times New Roman',
},{
value : '"Trebuchet MS", Helvetica, sans-serif',
style : 'font-family: "Trebuchet MS", Helvetica, sans-serif',
style : 'font-family: "Trebuchet MS", Helvetica, sans-serif; font-size:15px;',
name : 'Trebuchet',
},{
value : 'Verdana, Geneva, sans-serif',
style : 'font-family: Verdana, Geneva, sans-serif',
style : 'font-family: Verdana, Geneva, sans-serif; font-size:15px;',
name : 'Verdana',
}],
},{
name : 'Font size',
property : 'font-size',
type : 'integer',
units : ['px','em'],
units : ['px','em', 'rem', '%'],
defaults : '12',
min : 0,
},{
@ -346,7 +556,7 @@ require(['src/config/require-config.js'], function() {
name : 'Letter spacing',
property : 'letter-spacing',
type : 'integer',
units : ['px'],
units : ['px','em','%'],
defaults : 'normal',
},{
name: 'Font color',
@ -357,7 +567,7 @@ require(['src/config/require-config.js'], function() {
name : 'Line height',
property : 'line-height',
type : 'integer',
units : ['px'],
units : ['px','em','%'],
defaults : 'normal',
},{
name : 'Text align',
@ -371,6 +581,7 @@ require(['src/config/require-config.js'], function() {
}],
},{
name: 'Decorations',
open: false,
properties: [{
name : 'Border radius',
property : 'border-radius',
@ -534,6 +745,7 @@ require(['src/config/require-config.js'], function() {
},],
},{
name: 'Extra',
open: false,
properties: [{
name: 'Transition',
property: 'transition',
@ -603,7 +815,9 @@ require(['src/config/require-config.js'], function() {
],
},
});
}
);
grapes.render();

26
src/dom_components/config/config.js

@ -1,27 +1,29 @@
define(function () {
return {
stylePrefix : 'comp-',
wrapperId : 'wrapper',
wrapperId : 'wrapper',
// Default wrapper configuration
wrapper : {
removable : false,
removable : false,
copyable : false,
stylable : ['background','background-color','background-image', 'background-repeat','background-attachment','background-position'],
movable : false,
badgable : false,
components: [],
},
// Could be used for default components
components : {},
rte : {},
em : {},
defaults : [],
rte : {},
em : {},
// Class for new image component
imageCompClass : 'fa fa-picture-o',
// Open assets manager on create of image component
oAssetsOnCreate : true,
};

24
src/dom_components/main.js

@ -2,7 +2,7 @@ define(function(require) {
/**
* @class Components
* @param {Object} Configurations
*
*
* @return {Object}
* */
function Components(config)
@ -21,34 +21,40 @@ define(function(require) {
if (!(name in c))
c[name] = defaults[name];
}
if(!c.wrapper.attributes)
c.wrapper.attributes = {};
c.wrapper.attributes.id = 'wrapper';
// If there is no components try to append defaults
if(!c.wrapper.components.length && c.defaults.length){
console.log('Set defaults');
c.wrapper.components = c.defaults;
}
if(!c.wrapper.style)
c.wrapper.style = {};
c.wrapper.style.position = 'relative';
this.component = new Component(c.wrapper);
var obj = {
model : this.component,
config : c,
};
this.ComponentView = new ComponentView(obj);
}
Components.prototype = {
render : function(){
return this.ComponentView.render().$el;
},
getComponent : function(){
return this.component;
},
};
return Components;
});

31
src/dom_components/model/Component.js

@ -1,10 +1,10 @@
define(['backbone','./Components'],
define(['backbone','./Components'],
function (Backbone, Components) {
/**
* @class Component
* */
return Backbone.Model.extend({
return Backbone.Model.extend({
defaults: {
tagName : 'div',
type : '',
@ -14,22 +14,39 @@ define(['backbone','./Components'],
droppable : true,
badgable : true,
stylable : true,
copyable : true,
status : '',
previousModel : '',
content : '',
style : {},
attributes : {},
},
initialize: function(options) {
this.defaultC = options.components || [];
this.components = new Components(this.defaultC);
this.set('components', this.components);
},
/**
* Override original clone method
*/
clone: function()
{
var attr = _.clone(this.attributes),
comp = this.get('components');
attr.components = [];
if(comp.length){
comp.each(function(md,i){
attr.components[i] = md.clone();
});
}
return new this.constructor(attr);
},
/**
* Get name of the component
*
*
* @return string
* */
getName: function(){
@ -40,6 +57,6 @@ define(['backbone','./Components'],
}
return this.name;
},
});
});

30
src/dom_components/view/ComponentImageView.js

@ -1,53 +1,53 @@
define(['backbone', './ComponentView'],
define(['backbone', './ComponentView'],
function (Backbone, ComponentView) {
/**
* @class ComponentImageView
* */
return ComponentView.extend({
tagName : 'img',
events : {
'dblclick' : 'openModal',
},
initialize: function(o){
ComponentView.prototype.initialize.apply(this, arguments);
this.listenTo( this.model, 'change:src', this.updateSrc);
this.listenTo( this.model, 'dblclick', this.openModal);
this.classEmpty = this.config.stylePrefix + 'image-placeholder ' + this.config.imageCompClass;
if(!this.model.get('src'))
this.$el.attr('class', this.classEmpty);
if(this.config.modal)
this.modal = this.config.modal;
if(this.config.am)
this.am = this.config.am;
},
/**
/**
* Update src attribute
*
*
* @return void
* */
updateSrc: function(){
this.$el.attr('src',this.model.get("src"));
},
/**
* Open dialog for image changing
* @param {Object} e Event
*
*
* @return void
* */
openModal: function(e){
var that = this;
if(this.modal && this.am){
this.modal.setTitle('Select image');
this.modal.setContent(this.am.render());
this.modal.setContent(this.am.render(1));
this.am.setTarget(this.model);
this.modal.show();
this.am.onSelect(function(){
@ -56,7 +56,7 @@ define(['backbone', './ComponentView'],
});
}
},
render: function() {
this.updateAttributes();
return this;

95
src/dom_components/view/ComponentView.js

@ -1,34 +1,55 @@
define(['backbone', './ComponentsView'],
define(['backbone', './ComponentsView'],
function (Backbone, ComponentsView) {
/**
/**
* @class ComponentView
* */
return Backbone.View.extend({
className : function(){ //load classes from model
return this.getClasses();
return this.getClasses();
},
tagName: function(){ //load tagName from model
return this.model.get('tagName');
return this.model.get('tagName');
},
initialize: function(opt){
this.config = opt.config;
this.components = this.model.get('components');
this.attr = this.model.get("attributes");
this.pfx = this.config.stylePrefix;
this.components = this.model.get('components');
this.attr = this.model.get("attributes");
this.classe = this.attr.class || [];
this.listenTo( this.model, 'destroy remove', this.remove);
this.listenTo( this.model, 'change:style', this.updateStyle);
this.listenTo( this.model, 'change:attributes', this.updateAttributes);
this.listenTo(this.model, 'destroy remove', this.remove);
this.listenTo(this.model, 'change:style', this.updateStyle);
this.listenTo(this.model, 'change:attributes', this.updateAttributes);
this.listenTo(this.model, 'change:status', this.updateStatus);
this.$el.data("model", this.model);
this.$el.data("model-comp", this.components);
},
/**
* Get classes from attributes.
/**
* Update item on status change
* @param Event
* */
updateStatus: function(e)
{
var s = this.model.get('status'),
pfx = this.pfx;
switch(s) {
case 'selected':
this.$el.addClass(pfx + 'selected');
break;
case 'moving':
break;
default:
this.$el.removeClass(pfx + 'selected');
}
},
/**
* Get classes from attributes.
* This method is called before initialize
*
*
* @return {Array}|null
* */
getClasses: function(){
@ -39,40 +60,40 @@ define(['backbone', './ComponentsView'],
}else
return null;
},
/**
/**
* Update attributes
*
*
* @return void
* */
updateAttributes: function(){
var attributes = {},
attr = this.model.get("attributes");
for(var key in attr) {
for(var key in attr) {
if(attr.hasOwnProperty(key))
attributes[key] = attr[key];
}
// Update src
if(this.model.get("src"))
attributes.src = this.model.get("src");
attributes.style = this.getStyleString();
this.$el.attr(attributes);
},
/**
/**
* Update style attribute
*
*
* @return void
* */
updateStyle: function(){
this.$el.attr('style', this.getStyleString());
},
/**
/**
* Return style string
*
*
* @return {String}
* */
getStyleString: function(){
@ -82,32 +103,32 @@ define(['backbone', './ComponentsView'],
if(this.style.hasOwnProperty(key))
style += key + ':' + this.style[key] + ';';
}
return style;
},
/**
/**
* Update classe attribute
*
*
* @return void
* */
updateClasses: function(){
if(this.classe.length)
this.$el.attr('class', this.classe.join(" "));
},
/**
* Reply to event call
* Reply to event call
* @param object Event that generated the request
* */
eventCall: function(event){
event.viewResponse = this;
},
render: function() {
this.updateAttributes();
this.$el.html(this.model.get('content'));
var view = new ComponentsView({
var view = new ComponentsView({
collection : this.components,
config : this.config,
});
@ -116,6 +137,6 @@ define(['backbone', './ComponentsView'],
this.$el.append(view.render(this.$el).el.childNodes);
return this;
},
});
});

21
src/editor/config/config.js

@ -13,12 +13,15 @@ define(function () {
// Where render the editor
container : '',
idCanvas : 'canvas',
idCanvas : 'canvas',
idCanvasOverlay : 'canvas-overlay',
idCanvasOverlay : 'canvas-overlay',
idWrapper : 'wrapper',
// Enable/Disable possibility to copy(ctrl + c) & paste(ctrl + v) components
copyPaste : true,
// Enable/Disable undo manager
undoManager : true,
@ -29,34 +32,34 @@ define(function () {
assetManager : {},
//Configurations for Canvas
canvas : {},
canvas : {},
//Configurations for Style Manager
styleManager : {},
//Configurations for Layers
layers : {},
layers : {},
//Configurations for Storage Manager
storageManager : {},
storageManager : {},
//Configurations for Rich Text Editor
rte : {},
rte : {},
//Configurations for Components
components : {},
//Configurations for Modal Dialog
modal : {},
modal : {},
//Configurations for Code Manager
codeManager : {},
//Configurations for Panels
panels : {},
panels : {},
//Configurations for Commands
commands : {},
commands : {},
};
return config;

180
src/editor/model/Editor.js

@ -2,9 +2,9 @@ define([
'backbone',
'backboneUndo',
'keymaster',
'AssetManager',
'StorageManager',
'ModalDialog',
'AssetManager',
'StorageManager',
'ModalDialog',
'CodeManager',
'Commands',
'Canvas',
@ -15,10 +15,10 @@ define([
Backbone,
UndoManager,
Keymaster,
AssetManager,
StorageManager,
ModalDialog,
CodeManager,
AssetManager,
StorageManager,
ModalDialog,
CodeManager,
Commands,
Canvas,
RichTextEditor,
@ -26,18 +26,20 @@ define([
Panels
){
return Backbone.Model.extend({
defaults:{
selectedComponent: null,
changesCount: 0,
clipboard : null,
selectedComponent : null,
previousModel : null,
changesCount : 0,
},
initialize: function(c)
{
this.config = c;
this.compName = this.config.storagePrefix + 'components' + this.config.id;
this.set('Config', c);
this.initStorage();
this.initModal();
this.initAssetManager();
@ -48,43 +50,49 @@ define([
this.initComponents();
this.initCanvas();
this.initUndoManager();
this.on('change:selectedComponent', this.componentSelected, this);
},
/**
* Initialize components
* */
initComponents: function()
{
var cfg = this.config.components,
comp = this.loadComponentsTree(),
var cfg = this.config.components,
comp = this.loadComponents(),
cmpStylePfx = cfg.stylePrefix || 'comp-';
cfg.stylePrefix = this.config.stylePrefix + cmpStylePfx;
if(comp)
cfg.wrapper = comp;
if(this.rte)
cfg.rte = this.rte;
cfg.rte = this.rte;
if(this.modal)
cfg.modal = this.modal;
cfg.modal = this.modal;
if(this.am)
cfg.am = this.am;
cfg.em = this;
this.cmp = new DomComponents(cfg);
if(this.stm.isAutosave()){ // TODO Currently doesn't listen already created models
this.updateComponents( this.cmp.getComponent(), null, { avoidStore : 1 });
cfg.am = this.am;
cfg.em = this;
this.cmp = new DomComponents(cfg);
if(this.stm.isAutosave()){
var md = this.cmp.getComponent();
this.updateComponents( md, null, { avoidStore : 1 });
// Call UndoManager here so it's possible to call it also for children inside
this.initUndoManager();
this.initChildrenComp(md);
}
this.set('Components', this.cmp);
},
/**
* Initialize canvas
* */
@ -98,10 +106,10 @@ define([
if(this.cmp)
this.cv.setWrapper(this.cmp);
this.set('Canvas', this.cv);
},
/**
* Initialize rich text editor
* */
@ -113,7 +121,7 @@ define([
this.rte = new RichTextEditor(cfg);
this.set('RichTextEditor', this.rte);
},
/**
* Initialize storage
* */
@ -123,7 +131,7 @@ define([
this.stm.loadDefaultProviders().setCurrentProvider(this.config.storageType);
this.set('StorageManager', this.stm);
},
/**
* Initialize asset manager
* */
@ -132,14 +140,14 @@ define([
var cfg = this.config.assetManager,
pfx = cfg.stylePrefix || 'am-';
cfg.stylePrefix = this.config.stylePrefix + pfx;
if(this.stm)
cfg.stm = this.stm;
this.am = new AssetManager(cfg);
this.set('AssetManager', this.am);
},
/**
* Initialize modal
* */
@ -152,7 +160,7 @@ define([
this.modal.render().appendTo('body');
this.set('Modal', this.modal);
},
/**
* Initialize Code Manager
* */
@ -165,7 +173,7 @@ define([
this.cm.loadDefaultGenerators().loadDefaultEditors();
this.set('CodeManager', this.cm);
},
/**
* Initialize Commands
* */
@ -181,7 +189,7 @@ define([
this.com.loadDefaultCommands();
this.set('Commands', this.com);
},
/**
* Initialize Panels
* */
@ -195,23 +203,28 @@ define([
this.pn.addPanel({ id: 'views-container'});
this.set('Panels', this.pn);
},
/**
* Initialize Undo manager
* */
initUndoManager: function(){
initUndoManager: function()
{
if(this.um)
return;
if(this.cmp && this.config.undoManager){
var backboneUndo = new Backbone.UndoManager({
var that = this;
this.um = new Backbone.UndoManager({
register: [this.cmp.getComponent().get('components')],
track: true
});
this.set('UndoManager', this.um);
key('⌘+z, ctrl+z', function(){
backboneUndo.undo();
that.um.undo();
});
key('⌘+shift+z, ctrl+shift+z', function(){
backboneUndo.redo();
that.um.redo();
});
Backbone.UndoManager.removeUndoType("change");
var beforeCache;
Backbone.UndoManager.addUndoType("change:style", {
@ -237,12 +250,12 @@ define([
model.set(af);
}
});
//TODO when, for example, undo delete cant redelete it, so need to
//TODO when, for example, undo delete cant redelete it, so need to
//recall 'remove command'
}
},
/**
* Triggered when components are updated
* */
@ -253,16 +266,16 @@ define([
if(this.stm.isAutosave() && updatedCount < this.stm.getChangesBeforeSave()){
return;
}
this.storeComponentsTree();
this.storeComponents();
this.set('changesCount', 0 );
},
/**
/**
* Callback on component selection
* @param {Object} Model
* @param {Mixed} New value
* @param {Object} Options
*
*
* */
componentSelected: function(model, val, options)
{
@ -271,13 +284,13 @@ define([
else
this.trigger('select-comp',[model,val,options]);
},
/**
/**
* Load components from storage
*
*
* @return {Object}
* */
loadComponentsTree: function(){
loadComponents: function(){
var result = null;
try{
result = JSON.parse(this.stm.load(this.compName));
@ -286,57 +299,78 @@ define([
}
return result;
},
/**
/**
* Save components to storage
*
*
* @return void
* */
storeComponentsTree: function(){
storeComponents: function(){
var wrp = this.cmp.getComponent();
if(wrp && this.cm){
var res = this.cm.getCode(wrp, 'json');
this.stm.store(this.compName, JSON.stringify(res));
}
},
/**
* Triggered when components are updated
* @param {Object} model
* @param {Mixed} val Value
* @param {Object} opt Options
*
*
* */
updateComponents: function(model, val, opt){
var comps = model.get('components'),
avSt = opt ? opt.avoidStore : 0;
avSt = opt ? opt.avoidStore : 0;
// Observe component with Undo Manager
if(this.um)
this.um.register(comps);
// Call stopListening for not creating nested listenings
// Call stopListening for not creating nested listenings
this.stopListening(comps, 'add', this.updateComponents);
this.stopListening(comps, 'remove', this.rmComponents);
this.listenTo(comps, 'add', this.updateComponents);
this.listenTo(comps, 'remove', this.rmComponents);
this.stopListening(model, 'change:style change:content', this.updateComponents);
this.listenTo(model, 'change:style change:content', this.updateComponents);
if(!avSt)
this.componentsUpdated();
},
/**
* Init stuff like storage for already existing elements
* @param {Object} model
*/
initChildrenComp: function(model)
{
var comps = model.get('components');
if(comps.length){
comps.each(function(md){
this.updateComponents(md, null, { avoidStore : 1 });
this.initChildrenComp(md);
if(this.um)
this.um.register(md);
}, this);
}
},
/**
* Triggered when some component is removed updated
* @param {Object} model
* @param {Mixed} val Value
* @param {Object} opt Options
*
*
* */
rmComponents: function(model, val, opt){
var avSt = opt ? opt.avoidStore : 0;
if(!avSt)
this.componentsUpdated();
}
});
});

16
src/navigator/main.js

@ -7,34 +7,34 @@ define(function(require) {
function Navigator(collection, c)
{
var config = c,
defaults = require('./config/config'),
ItemsView = require('./view/ItemsView');
defaults = require('./config/config'),
ItemsView = require('./view/ItemsView');
// Set default options
for (var name in defaults) {
if (!(name in config))
config[name] = defaults[name];
}
var obj = {
collection : collection,
config : config,
config : config,
};
// Check if sort is required
if(config.sortable){
var ItemSort = require('./view/ItemSort');
obj.sorter = new ItemSort({config : config});
}
this.ItemsView = new ItemsView(obj);
}
Navigator.prototype = {
render : function(){
return this.ItemsView.render().$el;
},
};
return Navigator;
});

34
src/navigator/view/ItemView.js

@ -9,14 +9,16 @@ define(['backbone', 'text!./../template/item.html','require'],
template: _.template(ItemTemplate),
initialize: function(o){
this.opt = o;
this.opt = o;
this.config = o.config;
this.em = o.config.em;
this.sorter = o.sorter || {};
this.pfx = this.config.stylePrefix;
this.pfx = this.config.stylePrefix;
if(typeof this.model.get('open') == 'undefined')
this.model.set('open',false);
this.listenTo(this.model.components, 'remove add change reset', this.checkChildren);
this.listenTo(this.model, 'destroy remove', this.remove);
this.listenTo(this.model, 'change:status', this.updateStatus);
this.listenTo(this.model, 'change:open', this.updateOpening);
this.className = this.pfx + 'item no-select';
this.events = {};
@ -24,6 +26,8 @@ define(['backbone', 'text!./../template/item.html','require'],
this.events['click .'+this.pfx+'title'] = 'toggleOpening';
this.$el.data("model", this.model);
//TODO listen
if(o.config.sortable)
this.events['mousedown > #'+this.pfx+'move'] = 'startSort';
@ -53,6 +57,17 @@ define(['backbone', 'text!./../template/item.html','require'],
* */
toggleOpening: function(e){
e.stopPropagation();
// Selection
if(this.em){
var md = this.em.get('selectedComponent');
if(md){
md.set('status','');
this.model.set('status','selected');
this.em.set('selectedComponent', this.model);
}
}
if(!this.model.components.length)
return;
this.model.set('open', !this.model.get('open') );
@ -87,13 +102,11 @@ define(['backbone', 'text!./../template/item.html','require'],
/**
* Update item on status change
* @param Event
*
* @return void
* */
updateStatus: function(e){
var s = this.model.get('status'),
pr = this.model.get('previousModel'),
pfx = this.pfx;
updateStatus: function(e)
{
var s = this.model.get('status'),
pfx = this.pfx;
switch(s) {
case 'selected':
this.$el.addClass(pfx + 'selected');
@ -103,10 +116,6 @@ define(['backbone', 'text!./../template/item.html','require'],
default:
this.$el.removeClass(pfx + 'selected');
}
if(pr){
pr.set('previousModel','');
pr.set('status','');
}
},
/**
@ -193,6 +202,7 @@ define(['backbone', 'text!./../template/item.html','require'],
if(!vis)
this.className += ' ' + pfx + 'hide';
this.$el.attr('class', _.result(this, 'className'));
this.updateOpening();
return this;
},

36
src/navigator/view/ItemsView.js

@ -1,55 +1,55 @@
define(['backbone','./ItemView'],
define(['backbone','./ItemView'],
function (Backbone, ItemView) {
/**
/**
* @class ItemsView
* */
return Backbone.View.extend({
initialize: function(o) {
this.opt = o;
this.opt = o;
this.config = o.config;
this.preview = o.preview;
this.sorter = o.sorter || {};
this.pfx = o.config.stylePrefix;
this.pfx = o.config.stylePrefix;
this.parent = o.parent;
this.listenTo( this.collection, 'add', this.addTo );
this.listenTo( this.collection, 'reset', this.render );
this.className = this.pfx + 'items';
if(!this.parent)
this.className += ' ' + this.pfx + this.config.containerId;
},
/**
* Add to collection
* @param Object Model
*
*
* @return Object
* */
addTo: function(model){
var i = this.collection.indexOf(model);
this.addToCollection(model, null, i);
},
/**
* Add new object to collection
* @param Object Model
* @param Object Fragment collection
* @param integer Index of append
*
*
* @return Object Object created
* */
addToCollection: function(model, fragmentEl, index){
var fragment = fragmentEl || null;
var viewObject = ItemView;
var view = new viewObject({
model : model,
var view = new viewObject({
model : model,
config : this.config,
sorter : this.sorter,
});
var rendered = view.render().el;
if(fragment){
fragment.appendChild(rendered);
}else{
@ -69,18 +69,18 @@ define(['backbone','./ItemView'],
}else
this.$el.append(rendered);
}
return rendered;
},
render: function() {
var fragment = document.createDocumentFragment();
this.$el.empty();
this.collection.each(function(model){
this.addToCollection(model, fragment);
},this);
this.$el.append(fragment);
this.$el.attr('class', _.result(this, 'className'));
return this;

29
src/style_manager/config/config.js

@ -1,11 +1,26 @@
define(function () {
return {
stylePrefix : 'sm-',
target : null,
sectors : [],
stylePrefix : 'sm-',
// Default sectors, which could include also properties
//
// Example:
// sectors: [{
// name: 'Some sector name',
// properties:[{
// name : 'Width',
// property : 'width',
// type : 'integer',
// units : ['px','%'],
// defaults : 'auto',
// min : 0,
// }],
// }]
sectors : [],
// Text to show in case no element selected
textNoElement : 'Select an element before using Style Manager',
};
});

4
src/style_manager/templates/sector.html

@ -0,0 +1,4 @@
<div class="<%= pfx %>title">
<i id="<%= pfx %>caret" class="fa"></i>
<%= label %>
</div>

16
src/style_manager/view/PropertyIntegerView.js

@ -10,8 +10,8 @@ define(['backbone','./PropertyView', 'text!./../templates/propertyInteger.html']
initialize: function(options) {
PropertyView.prototype.initialize.apply(this, arguments);
_.bindAll(this, 'moveIncrement', 'upIncrement');
this.events['click .'+this.pfx+'u-arrow'] = 'upArrowClick';
this.events['click .'+this.pfx+'d-arrow'] = 'downArrowClick';
this.events['click .'+this.pfx+'u-arrow'] = 'upArrowClick';
this.events['click .'+this.pfx+'d-arrow'] = 'downArrowClick';
this.events['mousedown .'+this.pfx+'int-arrows'] = 'downIncrement';
this.delegateEvents();
},
@ -107,22 +107,28 @@ define(['backbone','./PropertyView', 'text!./../templates/propertyInteger.html']
},
/** @inheritdoc */
setValue: function(value){
setValue: function(value)
{
var u = this.unit,
v = this.model.get('value') || this.defaultValue;
v = this.model.get('value') || this.defaultValue;
if(value){
v = parseInt(value, 10);
// Make it suitable for replace
value += '';
v = parseFloat(value.replace(',', '.'));
v = !isNaN(v) ? v : this.defaultValue;
var uN = value.replace(v,'');
// Check if exists as unit
if(_.indexOf(this.units, uN) > -1)
u = uN;
}
if(this.$input)
this.$input.val(v);
if(this.$unit)
this.$unit.val(u);
this.model.set({value: v, unit: u,},{silent: true});
},

109
src/style_manager/view/PropertyView.js

@ -1,17 +1,17 @@
define(['backbone', 'text!./../templates/propertyLabel.html'],
define(['backbone', 'text!./../templates/propertyLabel.html'],
function (Backbone, propertyTemplate) {
/**
/**
* @class PropertyView
* */
return Backbone.View.extend({
template: _.template(propertyTemplate),
templateLabel: _.template(propertyTemplate),
events: {
'change' : 'valueChanged',
},
initialize: function(o) {
this.config = o.config;
this.pfx = this.config.stylePrefix;
@ -30,19 +30,19 @@ define(['backbone', 'text!./../templates/propertyLabel.html'],
this.input = this.$input = null;
this.className = this.pfx + 'property';
this.selectedComponent = this.target.get('selectedComponent');
if(this.selectedComponent){
this.componentValue = this.selectedComponent.get('style')[this.property];
}
this.listenTo( this.target ,'change:selectedComponent',this.componentSelected);
this.listenTo( this.model ,'change:value', this.valueChanged);
},
/**
},
/**
* Rerender property for the new selected component, if necessary
* @param Array [Model, value, options]
*
*
* @return void
* */
componentSelected: function(e){
@ -55,39 +55,39 @@ define(['backbone', 'text!./../templates/propertyLabel.html'],
}
}
},
/**
* Checks if the value from selected component is the same with
* Checks if the value from selected component is the same with
* the value of the model
*
* @return boolean
*
* @return boolean
* */
sameValue: function(){
return this.getComponentValue() == (this.model.get('value')+this.model.get('unit'));
},
/**
* Get the value from the selected component of this property
*
*
* @return string
* */
getComponentValue: function(){
if(!this.selectedComponent)
return;
if(!this.selectedComponent)
return;
if(this.selectedComponent.get('style')[this.property])
this.componentValue = this.selectedComponent.get('style')[this.property];
else
this.componentValue = this.defaultValue + (this.unit ? this.unit : '');
// Check if wrap inside function is required
if(this.func){
var v = this.fetchFromFunction(this.componentValue);
if(v)
this.componentValue = v;
}
//This allow to ovveride the normal flow of selecting component value,
//useful in composite properties
if(this.customValue && typeof this.customValue === "function"){
@ -96,67 +96,68 @@ define(['backbone', 'text!./../templates/propertyLabel.html'],
if(t)
this.componentValue = t;
}
return this.componentValue;
},
/**
* Fetch string from function type value
* @param string Function type value
*
*
* @return string
* */
fetchFromFunction: function(v){
return v.substring(v.indexOf("(") + 1, v.lastIndexOf(")"));
},
/**
/**
* Property was changed, so I need to update the component too
* @param {Object} e Events
* @param {Mixed} val Value
* @param {Object} opt Options
*
*
* @return void
* */
valueChanged: function(e, val, opt){
if(!this.selectedComponent)
return;
// Check if component is allowed to be styled
var stylable = this.selectedComponent.get('stylable');
if( (stylable instanceof Array && _.indexOf(stylable, this.property) < 0) || !stylable )
return;
var v = e && e.currentTarget ? this.$input.val() : this.model.get('value'),
value = v + (this.$unit ? this.$unit.val() : ''),
avSt = opt ? opt.avoidStore : 0;
var v = e && e.currentTarget ? this.$input.val() : this.model.get('value'),
u = this.$unit ? this.$unit.val() : '',
value = v + u,
avSt = opt ? opt.avoidStore : 0;
//The easiest way to deal with radio inputs
if(this.model.get('type') == 'radio')
value = this.$el.find('input:checked').val();
if(this.$input)
this.$input.val(v);
this.model.set({ value : v },{ silent : true });
this.model.set({ value : v, unit: u },{ silent : true });
if(this.func)
value = this.func + '(' + value + ')';
if( !this.model.get('doNotStyle') ){
var componentCss = _.clone( this.selectedComponent.get('style') );
componentCss[this.property] = value;
this.selectedComponent.set('style', componentCss, { avoidStore : avSt});
}
this.selectedValue = value;//TODO ?
if(this.onChange && typeof this.onChange === "function"){
this.onChange(this.selectedComponent, this.model);
}
},
/**
* Set value to the input
* @param String value
*
*
* @return void
* */
setValue: function(value, force){
@ -169,10 +170,10 @@ define(['backbone', 'text!./../templates/propertyLabel.html'],
this.$input.val(v);
this.model.set({value: v},{silent: true});
},
/**
* Render label
*
*
* @return void
* */
renderLabel: function(){
@ -183,10 +184,10 @@ define(['backbone', 'text!./../templates/propertyLabel.html'],
label : this.model.get('name'),
}) );
},
/**
* Render field property
*
*
* @return void
* */
renderField : function() {
@ -194,10 +195,10 @@ define(['backbone', 'text!./../templates/propertyLabel.html'],
this.renderInput();
delete this.componentValue;
},
/**
* Render loaded template
*
*
* @return void
* */
renderTemplate: function(){
@ -208,19 +209,19 @@ define(['backbone', 'text!./../templates/propertyLabel.html'],
label : this.model.get('name'),
}));
},
/**
* Renders input, to override
*
*
* @return void
* */
renderInput: function(){
console.warn("No render input implemented for '"+this.model.get('type')+"'");
},
/**
* Request to render input of the property
*
*
* @return void
* */
renderInputRequest: function(){
@ -230,22 +231,22 @@ define(['backbone', 'text!./../templates/propertyLabel.html'],
this.onInputRender(this, index);
}
},
/**
* Clean input
*
*
* @return void
* */
cleanValue: function(){
this.setValue('');
},
render : function(){
this.renderLabel();
this.renderField();
this.$el.attr('class', this.className);
return this;
},
});
});

64
src/style_manager/view/SectorView.js

@ -1,68 +1,88 @@
define(['backbone','./PropertiesView'],
function (Backbone,PropertiesView) {
define(['backbone', './PropertiesView', 'text!./../templates/sector.html'],
function (Backbone, PropertiesView, sectorTemplate) {
/**
* @class SectorView
* */
return Backbone.View.extend({
template: _.template(sectorTemplate),
events:{},
initialize: function(o) {
this.config = o.config;
this.pfx = this.config.stylePrefix;
this.pfx = this.config.stylePrefix;
this.target = o.target || {};
this.open = this.model.get('open');
this.caretR = 'fa-caret-right';
this.caretD = 'fa-caret-down';
this.listenTo( this.model ,'change:open', this.updateOpen);
this.events['click .' + this.pfx + 'title'] = 'toggle';
this.delegateEvents();
},
/**
* Update visibility
*/
updateOpen: function()
{
if(this.model.get('open'))
this.show();
else
this.hide();
},
/**
* Show the content of the sector
* */
show : function(){
show : function()
{
this.$el.addClass(this.pfx + "open");
this.$el.find('.' + this.pfx + 'properties').show();
this.open = true;
this.$caret.removeClass(this.caretR).addClass(this.caretD);
},
/**
* Hide the content of the sector
* */
hide : function(){
hide : function()
{
this.$el.removeClass(this.pfx + "open");
this.$el.find('.' + this.pfx + 'properties').hide();
this.open = false;
this.$caret.removeClass(this.caretD).addClass(this.caretR);
},
/**
* Toggle visibility of the content
* Toggle visibility
* */
toggle: function(){
if(this.open)
this.hide();
else
this.show();
toggle: function()
{
var v = this.model.get('open') ? 0 : 1;
this.model.set('open', v);
},
render : function(){
if(this.open)
this.show();
else
this.hide();
this.$el.html('<div class="' + this.pfx + 'title">'+this.model.get('name')+'</div>');
render : function()
{
this.$el.html(this.template({
pfx : this.pfx,
label : this.model.get('name'),
}));
this.$caret = this.$el.find('#' + this.pfx + 'caret');
this.renderProperties();
this.$el.attr('class', this.pfx + 'sector no-select');
this.updateOpen();
return this;
},
renderProperties: function(){
renderProperties: function()
{
var objs = this.model.get('properties');
if(objs){
var view = new PropertiesView({
collection : objs,
target : this.target,
config : this.config,
target : this.target,
config : this.config,
});
this.$el.append(view.render().el);
}

22
src/style_manager/view/SectorsView.js

@ -1,31 +1,31 @@
define(['backbone','./SectorView'],
define(['backbone','./SectorView'],
function (Backbone, SectorView) {
/**
/**
* @class sectorsView
* */
return Backbone.View.extend({
initialize: function(o) {
this.config = o.config;
this.pfx = this.config.stylePrefix;
this.target = o.target || {};
},
render: function() {
var fragment = document.createDocumentFragment();
this.collection.each(function(obj){
var view = new SectorView({
model : obj,
id : this.pfx + obj.get('name').replace(' ','_').toLowerCase(),
name : obj.get('name'),
model : obj,
id : this.pfx + obj.get('name').replace(' ','_').toLowerCase(),
name : obj.get('name'),
properties : obj.get('properties'),
target : this.target,
config : this.config,
target : this.target,
config : this.config,
});
fragment.appendChild(view.render().el);
}, this);
this.$el.attr('id', this.pfx + 'sectors');
this.$el.append(fragment);
return this;

76
styles/css/main.css

@ -2579,7 +2579,7 @@ html, body, #wte-app, .wte-editor {
.clear {
clear: both; }
.no-select, .wte-com-no-select {
.no-select, .wte-com-no-select, .wte-com-no-select img {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
@ -2683,18 +2683,18 @@ ol.example li.placeholder:before {
outline-offset: -2px;
box-sizing: border-box; }
body .wte-cv-canvas .selected-component {
outline: 3px solid #3b97e3; }
.wte-cv-canvas .wte-comp-selected {
outline: 3px solid #3b97e3 !important; }
div.wte-com-hover {
*.wte-com-hover, div.wte-com-hover {
outline: 1px solid #3b97e3; }
div.wte-com-hover-delete {
*.wte-com-hover-delete, div.wte-com-hover-delete {
outline: 2px solid #DD3636;
opacity: 0.5;
filter: alpha(opacity=50); }
div.wte-com-hover-move {
*.wte-com-hover-move, div.wte-com-hover-move {
outline: 3px solid #ffca6f; }
.wte-com-badge, .wte-com-badge-red, .wte-com-badge-yellow {
@ -2746,7 +2746,7 @@ div.wte-com-hover-move {
z-index: 4; }
.wte-pn-panel#wte-pn-views-container {
height: 100%;
padding: 50px 0 0;
padding: 52px 0 0;
right: 0;
width: 16.5%;
overflow: auto; }
@ -2928,6 +2928,13 @@ div.wte-com-hover-move {
opacity: 0.7;
filter: alpha(opacity=70); }
.wte-sm-header {
color: #eee;
font-size: 11px;
font-weight: lighter;
padding: 10px;
text-shadow: 0 1px 0 #252525; }
.wte-sm-sector {
clear: both;
border-bottom: 1px solid #303030;
@ -2938,11 +2945,14 @@ div.wte-com-hover-move {
/*------------------END Field--------------------*/
/*------------------Property--------------------*/
/*------------------END Property--------------------*/ }
.wte-sm-sector #wte-sm-caret {
padding-right: 5px;
font-size: 11px; }
.wte-sm-sector .wte-sm-title {
background-color: #3a3a3a;
font-size: 13px;
letter-spacing: 1px;
padding: 12px 10px 12px 25px;
padding: 12px 10px 12px 20px;
text-shadow: 0 1px 0 #252525;
border-bottom: 1px solid #303030;
border-top: 1px solid #414141;
@ -3142,7 +3152,8 @@ div.wte-com-hover-move {
.wte-sm-sector .wte-sm-property .wte-sm-layer > #wte-sm-preview-box #wte-sm-preview {
background-color: white;
height: 100%;
width: 100%; }
width: 100%;
background-size: cover !important; }
.wte-sm-sector .wte-sm-property .wte-sm-layer.wte-sm-active {
background-color: #4c4c4c; }
.wte-sm-sector .wte-sm-property .wte-sm-layer.wte-sm-no-preview #wte-sm-preview-box {
@ -3310,6 +3321,8 @@ div.wte-com-hover-move {
float: left;
box-sizing: border-box;
width: 50%; }
.wte-cm-editor-c .CodeMirror {
height: 450px; }
.wte-cm-editor {
font-size: 12px; }
@ -3420,49 +3433,4 @@ div.wte-com-hover-move {
box-shadow: none;
padding: 3px 5px; }
/*********JQuery-UI**********/
.ui-sortable-helper {
opacity: 0.7;
filter: alpha(opacity=70); }
.ui-sort-highlight {
/*ui-sortable-placeholder*/
background: #123;
height: 20px; }
.ui-resizable {
position: relative; }
.ui-resizable-se, .ui-resizable-s, .ui-resizable-e {
position: absolute;
right: 0;
bottom: 0;
cursor: nwse-resize;
height: 15px;
width: 15px;
outline: none !important; }
.ui-resizable-se {
opacity: 0;
filter: alpha(opacity=0);
font-size: 10px;
font-family: FontAwesome; }
.ui-resizable-se::before {
content: "\f065"; }
.ui-resizable:hover > .ui-resizable-se {
opacity: 0.3;
filter: alpha(opacity=30); }
.ui-resizable-s {
height: 10px;
width: 100%;
cursor: ns-resize; }
.ui-resizable-e {
width: 10px;
height: 100%;
cursor: ew-resize; }
/*# sourceMappingURL=main.css.map */

2
styles/css/main.css.map

File diff suppressed because one or more lines are too long

71
styles/scss/main.scss

@ -149,21 +149,21 @@ ol.example li.placeholder:before {position: absolute;}
box-sizing: border-box;
}
.#{$com-prefix}no-select{
.#{$com-prefix}no-select, .#{$com-prefix}no-select img{
@extend .no-select;
}
body .#{$cv-prefix}canvas .selected-component{//TODO
outline: 3px solid $colorBlue;
.#{$cv-prefix}canvas .#{$comp-prefix}selected{//TODO
outline: 3px solid $colorBlue !important;
}
div.#{$com-prefix}hover { outline: 1px solid $colorBlue; }
*.#{$com-prefix}hover, div.#{$com-prefix}hover { outline: 1px solid $colorBlue; }
div.#{$com-prefix}hover-delete{
*.#{$com-prefix}hover-delete, div.#{$com-prefix}hover-delete{
outline: 2px solid $colorRed;
@include opacity(0.50);
}
div.#{$com-prefix}hover-move{
*.#{$com-prefix}hover-move, div.#{$com-prefix}hover-move{
outline: 3px solid $colorYell;
}
.#{$com-prefix}badge{
@ -226,7 +226,7 @@ $leftWidth: 16.5%;
&##{$pn-prefix}views-container{
height: 100%;
padding: 50px 0 0;
padding: 52px 0 0;
right: 0;
width: $leftWidth;
overflow: auto;
@ -422,6 +422,13 @@ $arrowColor: darken($fontColor,24%); /*b1b1b1*/
&:hover{ @include opacity(0.7); }
}
.#{$sm-prefix}header {
color: $fontColor;
font-size: 11px;
font-weight: lighter;
padding: 10px;
text-shadow: 0 1px 0 $darkTextShadow;
}
.#{$sm-prefix}sector {
clear:both;
border-bottom: 1px solid $darkBorder;
@ -429,11 +436,16 @@ $arrowColor: darken($fontColor,24%); /*b1b1b1*/
font-weight: lighter;
text-align:left;
##{$sm-prefix}caret{
padding-right: 5px;
font-size: 11px;
}
.#{$sm-prefix}title{
background-color: $mainDkColor;
font-size: 13px;
letter-spacing: 1px;
padding: 12px 10px 12px 25px;
padding: 12px 10px 12px 20px;
text-shadow: 0 1px 0 $darkTextShadow;
border-bottom: 1px solid $darkBorder;
border-top: 1px solid $lightBorder;
@ -655,6 +667,7 @@ $arrowColor: darken($fontColor,24%); /*b1b1b1*/
background-color: white;
height: 100%;
width: 100%;
background-size: cover !important;
}
&.#{$sm-prefix}active {
background-color: lighten($mainDkColor, 7%);
@ -855,6 +868,10 @@ $uploadPadding: 150px 10px;
float:left;
box-sizing: border-box;
width:50%;
.CodeMirror{
height: 450px;
}
}
.#{$cm-prefix}editor{
font-size: 12px;
@ -951,42 +968,4 @@ $uploadPadding: 150px 10px;
text-shadow: none;
box-shadow: none;
padding: 3px 5px;
}
/*********JQuery-UI**********/
.ui-sortable-helper{
opacity: 0.7; filter: alpha(opacity=70);
}
.ui-sort-highlight{/*ui-sortable-placeholder*/
background:#123;
height:20px;
}
.ui-resizable{ position:relative;}
.ui-resizable-se, .ui-resizable-s,.ui-resizable-e{
position:absolute;
right: 0;
bottom:0;
cursor: nwse-resize;
height:15px;
width:15px;
outline: none !important;
}
.ui-resizable-se{
opacity: 0; filter: alpha(opacity=0);
font-size: 10px;
font-family: FontAwesome;
}
.ui-resizable-se::before{
content: "\f065";
}
.ui-resizable:hover > .ui-resizable-se{ opacity: 0.3; filter: alpha(opacity=30); }
.ui-resizable-s{
height:10px;
width:100%;
cursor: ns-resize;
}
.ui-resizable-e{
width:10px;
height:100%;
cursor: ew-resize;
}
Loading…
Cancel
Save