Browse Source

Create show offset command

pull/67/head
Artur Arseniev 9 years ago
parent
commit
4e3410959a
  1. 4
      index.html
  2. 531
      src/canvas/main.js
  3. 23
      src/canvas/view/CanvasView.js
  4. 322
      src/commands/main.js
  5. 50
      src/commands/view/Resize.js
  6. 509
      src/commands/view/SelectComponent.js
  7. 146
      src/commands/view/ShowOffset.js
  8. 383
      src/editor/config/config.js
  9. 2
      src/editor/main.js
  10. 7
      src/style_manager/view/PropertyView.js
  11. 23
      styles/css/main.css
  12. 26
      styles/scss/_gjs_canvas.scss

4
index.html

@ -6,7 +6,6 @@
<link rel="stylesheet" href="styles/css/main.css">
<link rel="stylesheet" href="node_modules/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="node_modules/codemirror/theme/hopscotch.css">
<script src="private/ckeditor/ckeditor.js"></script>
</head>
<style>
body, html{ height: 100%; margin: 0;}
@ -312,7 +311,8 @@
font-weight: 400;
}
.lead-title{
margin: 150px 0 30px 0;
padding: 25px;
margin: 150px 50px 30px 30px;
font-size: 40px;
}
.sub-lead-title{

531
src/canvas/main.js

@ -1,15 +1,13 @@
define(function(require) {
/**
* @class Canvas}
* */
return function() {
var c = {},
defaults = require('./config/config'),
Canvas = require('./model/Canvas'),
CanvasView = require('./view/CanvasView');
var canvas;
return {
return function() {
var c = {},
defaults = require('./config/config'),
Canvas = require('./model/Canvas'),
CanvasView = require('./view/CanvasView');
var canvas;
return {
/**
* Used inside RTE
@ -19,7 +17,7 @@ define(function(require) {
return CanvasView;
},
/**
/**
* Name of the module
* @type {String}
* @private
@ -33,254 +31,279 @@ define(function(require) {
init: function(config) {
c = config || {};
for (var name in defaults) {
if (!(name in c))
c[name] = defaults[name];
}
if (!(name in c))
c[name] = defaults[name];
}
var ppfx = c.pStylePrefix;
if(ppfx)
c.stylePrefix = ppfx + c.stylePrefix;
var ppfx = c.pStylePrefix;
if(ppfx)
c.stylePrefix = ppfx + c.stylePrefix;
canvas = new Canvas(config);
CanvasView = new CanvasView({
model: canvas,
config: c,
});
canvas = new Canvas(config);
CanvasView = new CanvasView({
model: canvas,
config: c,
});
var cm = c.em.get('DomComponents');
if(cm)
this.setWrapper(cm);
var cm = c.em.get('DomComponents');
if(cm)
this.setWrapper(cm);
return this;
},
/**
* Add wrapper
* @param {Object} wrp Wrapper
*
* */
setWrapper: function(wrp) {
canvas.set('wrapper', wrp);
},
/**
* Returns canvas element
* @return {HTMLElement}
*/
getElement: function(){
return CanvasView.el;
},
/**
* Returns frame element of the canvas
* @return {HTMLElement}
*/
getFrameEl: function(){
return CanvasView.frame.el;
},
/**
* Returns body element of the frame
* @return {HTMLElement}
*/
getBody: function(){
return CanvasView.frame.el.contentDocument.body;
},
/**
* Returns body wrapper element of the frame
* @return {HTMLElement}
*/
getWrapperEl: function(){
return this.getBody().querySelector('#wrapper');
},
/**
* Returns element containing canvas tools
* @return {HTMLElement}
*/
getToolsEl: function(){
return CanvasView.toolsEl;
},
/**
* Returns highlighter element
* @return {HTMLElement}
*/
getHighlighter: function(){
return CanvasView.hlEl;
},
/**
* Returns badge element
* @return {HTMLElement}
*/
getBadgeEl: function(){
return CanvasView.badgeEl;
},
/**
* Returns placer element
* @return {HTMLElement}
*/
getPlacerEl: function(){
return CanvasView.placerEl;
},
/**
* Returns ghost element
* @return {HTMLElement}
* @private
*/
getGhostEl: function(){
return CanvasView.ghostEl;
},
/**
* Returns toolbar element
* @return {HTMLElement}
*/
getToolbarEl: function(){
return CanvasView.toolbarEl;
},
/**
* Returns resizer element
* @return {HTMLElement}
*/
getResizerEl: function(){
return CanvasView.resizerEl;
},
/**
* Render canvas
* */
render: function() {
return CanvasView.render().el;
},
/**
* Get frame position
* @return {Object}
* @private
*/
getOffset: function() {
var frameOff = this.offset(this.getFrameEl());
var canvasOff = this.offset(this.getElement());
return {
top: frameOff.top - canvasOff.top,
left: frameOff.left - canvasOff.left
};
},
/**
* Get the offset of the element
* @param {HTMLElement} el
* @return {Object}
* @private
*/
offset: function(el){
var rect = el.getBoundingClientRect();
return {
top: rect.top + document.body.scrollTop,
left: rect.left + document.body.scrollLeft
};
},
/**
* This method comes handy when you need to attach something like toolbars
* to elements inside the canvas, dealing with all relative position,
* offsets, etc. and returning as result the object with positions which are
* viewable by the user (when the canvas is scrolled the top edge of the element
* is not viewable by the user anymore so the new top edge is the one of the canvas)
*
* The target should be visible before being passed here as invisible elements
* return empty string as width
* @param {HTMLElement} target The target in this case could be the toolbar
* @param {HTMLElement} element The element on which I'd attach the toolbar
* @param {Object} options Custom options
* @param {Boolean} options.toRight Set to true if you want the toolbar attached to the right
* @return {Object}
*/
getTargetToElementDim: function (target, element, options) {
var opts = options || {};
var canvasPos = CanvasView.getPosition();
var pos = CanvasView.getElementPos(element);
var toRight = options.toRight || 0;
var targetHeight = opts.targetHeight || target.offsetHeight;
var targetWidth = opts.targetWidth || target.offsetWidth;
var eventToTrigger = opts.event || null;
var elTop = pos.top - targetHeight;
var elLeft = pos.left;
elLeft += toRight ? pos.width : 0;
elLeft = toRight ? (elLeft - targetWidth) : elLeft;
var leftPos = elLeft < canvasPos.left ? canvasPos.left : elLeft;
var topPos = elTop < canvasPos.top ? canvasPos.top : elTop;
topPos = topPos > (pos.top + pos.height) ? (pos.top + pos.height) : topPos;
var result = {
top: topPos,
left: leftPos,
elementTop: pos.top,
elementLeft: pos.left,
elementWidth: pos.width,
elementHeight: pos.height,
targetWidth: target.offsetWidth,
targetHeight: target.offsetHeight,
canvasTop: canvasPos.top,
canvasLeft: canvasPos.left,
};
// In this way I can catch data and also change the position strategy
if(eventToTrigger && c.em) {
c.em.trigger(eventToTrigger, result);
}
return result;
},
/**
* Instead of simply returning e.clientX and e.clientY this function
* calculates also the offset based on the canvas. This is helpful when you
* need to get X and Y position while moving between the editor area and
* canvas area, which is in the iframe
* @param {Event} e
* @return {Object}
*/
getMouseRelativePos: function (e, options) {
var opts = options || {};
var addTop = 0;
var addLeft = 0;
var subWinOffset = opts.subWinOffset;
var doc = e.target.ownerDocument;
var win = doc.defaultView || doc.parentWindow;
var frame = win.frameElement;
var yOffset = subWinOffset ? win.pageYOffset : 0;
var xOffset = subWinOffset ? win.pageXOffset : 0;
if(frame) {
var frameRect = frame.getBoundingClientRect(); // maybe to cache ?!?
addTop = frameRect.top || 0;
addLeft = frameRect.left || 0;
}
return {
y: e.clientY + addTop - yOffset,
x: e.clientX + addLeft - xOffset,
};
},
/**
* Returns wrapper element
* @return {HTMLElement}
* ????
*/
getFrameWrapperEl: function(){
return CanvasView.frame.getWrapper();
},
};
};
/**
* Add wrapper
* @param {Object} wrp Wrapper
*
* */
setWrapper: function(wrp) {
canvas.set('wrapper', wrp);
},
/**
* Returns canvas element
* @return {HTMLElement}
*/
getElement: function(){
return CanvasView.el;
},
/**
* Returns frame element of the canvas
* @return {HTMLElement}
*/
getFrameEl: function(){
return CanvasView.frame.el;
},
/**
* Returns body element of the frame
* @return {HTMLElement}
*/
getBody: function(){
return CanvasView.frame.el.contentDocument.body;
},
/**
* Returns body wrapper element of the frame
* @return {HTMLElement}
*/
getWrapperEl: function(){
return this.getBody().querySelector('#wrapper');
},
/**
* Returns element containing canvas tools
* @return {HTMLElement}
*/
getToolsEl: function(){
return CanvasView.toolsEl;
},
/**
* Returns highlighter element
* @return {HTMLElement}
*/
getHighlighter: function(){
return CanvasView.hlEl;
},
/**
* Returns badge element
* @return {HTMLElement}
*/
getBadgeEl: function(){
return CanvasView.badgeEl;
},
/**
* Returns placer element
* @return {HTMLElement}
*/
getPlacerEl: function(){
return CanvasView.placerEl;
},
/**
* Returns ghost element
* @return {HTMLElement}
* @private
*/
getGhostEl: function(){
return CanvasView.ghostEl;
},
/**
* Returns toolbar element
* @return {HTMLElement}
*/
getToolbarEl: function() {
return CanvasView.toolbarEl;
},
/**
* Returns resizer element
* @return {HTMLElement}
*/
getResizerEl: function() {
return CanvasView.resizerEl;
},
/**
* Returns offset viewer element
* @return {HTMLElement}
*/
getOffsetViewerEl: function() {
return CanvasView.offsetEl;
},
/**
* Returns fixed offset viewer element
* @return {HTMLElement}
*/
getFixedOffsetViewerEl: function() {
return CanvasView.fixedOffsetEl;
},
/**
* Render canvas
* */
render: function() {
return CanvasView.render().el;
},
/**
* Get frame position
* @return {Object}
* @private
*/
getOffset: function() {
var frameOff = this.offset(this.getFrameEl());
var canvasOff = this.offset(this.getElement());
return {
top: frameOff.top - canvasOff.top,
left: frameOff.left - canvasOff.left
};
},
/**
* Get the offset of the element
* @param {HTMLElement} el
* @return {Object}
* @private
*/
offset: function(el){
var rect = el.getBoundingClientRect();
return {
top: rect.top + document.body.scrollTop,
left: rect.left + document.body.scrollLeft
};
},
/**
* Get element position relative to the canvas
* @param {HTMLElement} el
* @return {Object}
*/
getElementPos: function(el) {
return CanvasView.getElementPos(el);
},
/**
* This method comes handy when you need to attach something like toolbars
* to elements inside the canvas, dealing with all relative position,
* offsets, etc. and returning as result the object with positions which are
* viewable by the user (when the canvas is scrolled the top edge of the element
* is not viewable by the user anymore so the new top edge is the one of the canvas)
*
* The target should be visible before being passed here as invisible elements
* return empty string as width
* @param {HTMLElement} target The target in this case could be the toolbar
* @param {HTMLElement} element The element on which I'd attach the toolbar
* @param {Object} options Custom options
* @param {Boolean} options.toRight Set to true if you want the toolbar attached to the right
* @return {Object}
*/
getTargetToElementDim: function (target, element, options) {
var opts = options || {};
var canvasPos = CanvasView.getPosition();
var pos = opts.elPos || CanvasView.getElementPos(element);
var toRight = options.toRight || 0;
var targetHeight = opts.targetHeight || target.offsetHeight;
var targetWidth = opts.targetWidth || target.offsetWidth;
var eventToTrigger = opts.event || null;
var elTop = pos.top - targetHeight;
var elLeft = pos.left;
elLeft += toRight ? pos.width : 0;
elLeft = toRight ? (elLeft - targetWidth) : elLeft;
var leftPos = elLeft < canvasPos.left ? canvasPos.left : elLeft;
var topPos = elTop < canvasPos.top ? canvasPos.top : elTop;
topPos = topPos > (pos.top + pos.height) ? (pos.top + pos.height) : topPos;
var result = {
top: topPos,
left: leftPos,
elementTop: pos.top,
elementLeft: pos.left,
elementWidth: pos.width,
elementHeight: pos.height,
targetWidth: target.offsetWidth,
targetHeight: target.offsetHeight,
canvasTop: canvasPos.top,
canvasLeft: canvasPos.left,
};
// In this way I can catch data and also change the position strategy
if(eventToTrigger && c.em) {
c.em.trigger(eventToTrigger, result);
}
return result;
},
/**
* Instead of simply returning e.clientX and e.clientY this function
* calculates also the offset based on the canvas. This is helpful when you
* need to get X and Y position while moving between the editor area and
* canvas area, which is in the iframe
* @param {Event} e
* @return {Object}
*/
getMouseRelativePos: function (e, options) {
var opts = options || {};
var addTop = 0;
var addLeft = 0;
var subWinOffset = opts.subWinOffset;
var doc = e.target.ownerDocument;
var win = doc.defaultView || doc.parentWindow;
var frame = win.frameElement;
var yOffset = subWinOffset ? win.pageYOffset : 0;
var xOffset = subWinOffset ? win.pageXOffset : 0;
if(frame) {
var frameRect = frame.getBoundingClientRect(); // maybe to cache ?!?
addTop = frameRect.top || 0;
addLeft = frameRect.left || 0;
}
return {
y: e.clientY + addTop - yOffset,
x: e.clientX + addLeft - xOffset,
};
},
/**
* Returns wrapper element
* @return {HTMLElement}
* ????
*/
getFrameWrapperEl: function(){
return CanvasView.frame.getWrapper();
},
};
};
});

23
src/canvas/view/CanvasView.js

@ -163,7 +163,7 @@ function(Backbone, FrameView) {
frame.el.onload = this.renderBody;
}
var ppfx = this.ppfx;
this.toolsEl = $('<div>', { id: ppfx + 'tools' }).get(0);
toolsEl = $('<div>', { id: ppfx + 'tools' }).get(0);
this.hlEl = $('<div>', { class: ppfx + 'highlighter' }).get(0);
this.badgeEl = $('<div>', {class: ppfx + 'badge'}).get(0);
this.placerEl = $('<div>', {class: ppfx + 'placeholder'}).get(0);
@ -171,19 +171,24 @@ function(Backbone, FrameView) {
this.ghostEl = $('<div>', {class: ppfx + 'ghost'}).get(0);
this.toolbarEl = $('<div>', {class: ppfx + 'toolbar'}).get(0);
this.resizerEl = $('<div>', {class: ppfx + 'resizer'}).get(0);
this.offsetEl = $('<div>', {class: ppfx + 'offset-v'}).get(0);
this.fixedOffsetEl = $('<div>', {class: ppfx + 'offset-fixed-v'}).get(0);
this.placerEl.appendChild(this.placerIntEl);
this.toolsEl.appendChild(this.hlEl);
this.toolsEl.appendChild(this.badgeEl);
this.toolsEl.appendChild(this.placerEl);
this.toolsEl.appendChild(this.ghostEl);
this.toolsEl.appendChild(this.toolbarEl);
this.toolsEl.appendChild(this.resizerEl);
this.$el.append(this.toolsEl);
toolsEl.appendChild(this.hlEl);
toolsEl.appendChild(this.badgeEl);
toolsEl.appendChild(this.placerEl);
toolsEl.appendChild(this.ghostEl);
toolsEl.appendChild(this.toolbarEl);
toolsEl.appendChild(this.resizerEl);
toolsEl.appendChild(this.offsetEl);
toolsEl.appendChild(this.fixedOffsetEl);
this.$el.append(toolsEl);
var rte = this.em.get('rte');
if(rte)
this.toolsEl.appendChild(rte.render());
toolsEl.appendChild(rte.render());
this.toolsEl = toolsEl;
this.$el.attr({class: this.className});
return this;
},

322
src/commands/main.js

@ -39,23 +39,23 @@
*/
define(function(require) {
return function() {
var c = {},
commands = {},
defaultCommands = {},
defaults = require('./config/config'),
AbsCommands = require('./view/CommandAbstract');
// Need it here as it would be used below
var add = function(id, obj){
delete obj.initialize;
commands[id] = AbsCommands.extend(obj);
return this;
};
return {
/**
return function() {
var c = {},
commands = {},
defaultCommands = {},
defaults = require('./config/config'),
AbsCommands = require('./view/CommandAbstract');
// Need it here as it would be used below
var add = function(id, obj){
delete obj.initialize;
commands[id] = AbsCommands.extend(obj);
return this;
};
return {
/**
* Name of the module
* @type {String}
* @private
@ -70,99 +70,101 @@ define(function(require) {
init: function(config) {
c = config || {};
for (var name in defaults) {
if (!(name in c))
c[name] = defaults[name];
}
var ppfx = c.pStylePrefix;
if(ppfx)
c.stylePrefix = ppfx + c.stylePrefix;
// Load commands passed via configuration
for( var k in c.defaults){
var obj = c.defaults[k];
if(obj.id)
this.add(obj.id, obj);
}
defaultCommands['select-comp'] = require('./view/SelectComponent');
defaultCommands['create-comp'] = require('./view/CreateComponent');
defaultCommands['delete-comp'] = require('./view/DeleteComponent');
defaultCommands['image-comp'] = require('./view/ImageComponent');
defaultCommands['move-comp'] = require('./view/MoveComponent');
defaultCommands['text-comp'] = require('./view/TextComponent');
defaultCommands['insert-custom'] = require('./view/InsertCustom');
defaultCommands['export-template'] = require('./view/ExportTemplate');
defaultCommands['sw-visibility'] = require('./view/SwitchVisibility');
defaultCommands['open-layers'] = require('./view/OpenLayers');
defaultCommands['open-sm'] = require('./view/OpenStyleManager');
defaultCommands['open-tm'] = require('./view/OpenTraitManager');
defaultCommands['open-blocks'] = require('./view/OpenBlocks');
defaultCommands['open-assets'] = require('./view/OpenAssets');
defaultCommands.fullscreen = require('./view/Fullscreen');
defaultCommands.preview = require('./view/Preview');
defaultCommands.resize = require('./view/Resize');
defaultCommands['tlb-delete'] = {
run: function(ed) {
var sel = ed.getSelected();
if(!sel || !sel.get('removable')) {
console.warn('The element is not removable');
return;
}
sel.collection.remove(sel);
ed.Canvas.getToolbarEl().style.display = 'none';
ed.editor.runDefault();
},
};
defaultCommands['tlb-clone'] = {
run: function(ed){
var sel = ed.getSelected();
if(!sel || !sel.get('copyable')) {
console.warn('The element is not clonable');
return;
}
var collection = sel.collection;
var index = collection.indexOf(sel);
collection.add(sel.clone(), {at: index + 1});
},
};
defaultCommands['tlb-move'] = {
run: function(ed){
var sel = ed.getSelected();
if(!sel || !sel.get('draggable')) {
console.warn('The element is not draggable');
return;
}
var toolbarEl = ed.Canvas.getToolbarEl();
var toolbarDisplay = toolbarEl.style.display;
var cmdMove = ed.Commands.get('move-comp');
cmdMove.onEndMoveFromModel = function() {
ed.editor.runDefault();
ed.editor.set('selectedComponent', sel);
//toolbarEl.style.display = toolbarDisplay;
//ed.trigger('canvasScroll'); <- Need first this on SelectComponent
};
ed.editor.stopDefault();
cmdMove.initSorterFromModel(sel);
sel.set('status', 'selected');
toolbarEl.style.display = 'none';
},
};
if(c.em)
c.model = c.em.get('Canvas');
if (!(name in c))
c[name] = defaults[name];
}
var ppfx = c.pStylePrefix;
if(ppfx)
c.stylePrefix = ppfx + c.stylePrefix;
// Load commands passed via configuration
for( var k in c.defaults) {
var obj = c.defaults[k];
if(obj.id)
this.add(obj.id, obj);
}
defaultCommands['select-comp'] = require('./view/SelectComponent');
defaultCommands['create-comp'] = require('./view/CreateComponent');
defaultCommands['delete-comp'] = require('./view/DeleteComponent');
defaultCommands['image-comp'] = require('./view/ImageComponent');
defaultCommands['move-comp'] = require('./view/MoveComponent');
defaultCommands['text-comp'] = require('./view/TextComponent');
defaultCommands['insert-custom'] = require('./view/InsertCustom');
defaultCommands['export-template'] = require('./view/ExportTemplate');
defaultCommands['sw-visibility'] = require('./view/SwitchVisibility');
defaultCommands['open-layers'] = require('./view/OpenLayers');
defaultCommands['open-sm'] = require('./view/OpenStyleManager');
defaultCommands['open-tm'] = require('./view/OpenTraitManager');
defaultCommands['open-blocks'] = require('./view/OpenBlocks');
defaultCommands['open-assets'] = require('./view/OpenAssets');
defaultCommands['show-offset'] = require('./view/ShowOffset');
defaultCommands.fullscreen = require('./view/Fullscreen');
defaultCommands.preview = require('./view/Preview');
defaultCommands.resize = require('./view/Resize');
defaultCommands['tlb-delete'] = {
run: function(ed) {
var sel = ed.getSelected();
if(!sel || !sel.get('removable')) {
console.warn('The element is not removable');
return;
}
sel.collection.remove(sel);
ed.Canvas.getToolbarEl().style.display = 'none';
ed.editor.runDefault();
ed.trigger('component:update', sel);
},
};
defaultCommands['tlb-clone'] = {
run: function(ed) {
var sel = ed.getSelected();
if(!sel || !sel.get('copyable')) {
console.warn('The element is not clonable');
return;
}
var collection = sel.collection;
var index = collection.indexOf(sel);
collection.add(sel.clone(), {at: index + 1});
ed.trigger('component:update', sel);
},
};
defaultCommands['tlb-move'] = {
run: function(ed){
var sel = ed.getSelected();
if(!sel || !sel.get('draggable')) {
console.warn('The element is not draggable');
return;
}
var toolbarEl = ed.Canvas.getToolbarEl();
var toolbarDisplay = toolbarEl.style.display;
var cmdMove = ed.Commands.get('move-comp');
cmdMove.onEndMoveFromModel = function() {
ed.editor.runDefault();
ed.editor.set('selectedComponent', sel);
ed.trigger('component:update', sel);
};
ed.editor.stopDefault();
cmdMove.initSorterFromModel(sel);
sel.set('status', 'selected');
toolbarEl.style.display = 'none';
},
};
if(c.em)
c.model = c.em.get('Canvas');
return this;
},
@ -175,54 +177,54 @@ define(function(require) {
this.loadDefaultCommands();
},
/**
* Add new command to the collection
* @param {string} id Command's ID
* @param {Object} command Object representing you command. Methods `run` and `stop` are required
* @return {this}
* @example
* commands.add('myCommand', {
* run: function(editor, sender){
* alert('Hello world!');
* },
* stop: function(editor, sender){
* },
* });
* */
add: add,
/**
* Get command by ID
* @param {string} id Command's ID
* @return {Object} Object representing the command
* @example
* var myCommand = commands.get('myCommand');
* myCommand.run();
* */
get: function(id){
var el = commands[id];
if(typeof el == 'function'){
el = new el(c);
commands[id] = el;
}
return el;
},
/**
* Load default commands
* @return {this}
* @private
* */
loadDefaultCommands: function(){
for (var id in defaultCommands) {
this.add(id, defaultCommands[id]);
}
return this;
},
};
};
/**
* Add new command to the collection
* @param {string} id Command's ID
* @param {Object} command Object representing you command. Methods `run` and `stop` are required
* @return {this}
* @example
* commands.add('myCommand', {
* run: function(editor, sender){
* alert('Hello world!');
* },
* stop: function(editor, sender){
* },
* });
* */
add: add,
/**
* Get command by ID
* @param {string} id Command's ID
* @return {Object} Object representing the command
* @example
* var myCommand = commands.get('myCommand');
* myCommand.run();
* */
get: function(id){
var el = commands[id];
if(typeof el == 'function'){
el = new el(c);
commands[id] = el;
}
return el;
},
/**
* Load default commands
* @return {this}
* @private
* */
loadDefaultCommands: function(){
for (var id in defaultCommands) {
this.add(id, defaultCommands[id]);
}
return this;
},
};
};
});

50
src/commands/view/Resize.js

@ -1,32 +1,32 @@
define(function() {
return {
return {
run: function(editor, sender, opts) {
var el = (opts && opts.el) || '';
var canvas = editor.Canvas;
var canvasResizer = this.canvasResizer;
var options = opts.options || {};
run: function(editor, sender, opts) {
var el = (opts && opts.el) || '';
var canvas = editor.Canvas;
var canvasResizer = this.canvasResizer;
var options = opts.options || {};
// Create the resizer for the canvas if not yet created
if(!canvasResizer) {
var canvasView = canvas.getCanvasView();
options.ratioDefault = 1;
options.appendTo = canvas.getResizerEl();
options.prefix = editor.getConfig().stylePrefix;
options.posFetcher = canvasView.getElementPos.bind(canvasView);
options.mousePosFetcher = canvas.getMouseRelativePos;
this.canvasResizer = editor.Utils.Resizer.init(options);
canvasResizer = this.canvasResizer;
}
// Create the resizer for the canvas if not yet created
if(!canvasResizer) {
var canvasView = canvas.getCanvasView();
options.ratioDefault = 1;
options.appendTo = canvas.getResizerEl();
options.prefix = editor.getConfig().stylePrefix;
options.posFetcher = canvasView.getElementPos.bind(canvasView);
options.mousePosFetcher = canvas.getMouseRelativePos;
this.canvasResizer = editor.Utils.Resizer.init(options);
canvasResizer = this.canvasResizer;
}
canvasResizer.setOptions(options);
canvasResizer.focus(el);
},
canvasResizer.setOptions(options);
canvasResizer.focus(el);
},
stop: function() {
if(this.canvasResizer)
this.canvasResizer.blur();
},
stop: function() {
if(this.canvasResizer)
this.canvasResizer.blur();
},
};
};
});

509
src/commands/view/SelectComponent.js

@ -20,7 +20,9 @@ define(function(require) {
this.startSelectComponent();
this.toggleClipboard(config.copyPaste);
var em = this.config.em;
em.on('change:canvasOffset', this.onFrameScroll);
em.on('component:update', this.updateAttached, this);
em.on('change:canvasOffset', this.updateAttached, this);
em.on('change:selectedComponent', this.updateToolbar, this);
},
@ -65,34 +67,48 @@ define(function(require) {
}
},
/**
* Start select component event
* @private
* */
startSelectComponent: function() {
this.selEl = $(this.getCanvasBody()).find('*');
this.selEl.on('mouseover', this.onHover)
.on('mouseout', this.onOut)
.on('click', this.onClick);
var cw = this.getContentWindow();
cw.on('scroll', this.onFrameScroll);
cw.on('keydown', this.onKeyPress);
},
/**
* Stop select component event
* @private
* */
stopSelectComponent: function() {
if(this.selEl)
this.selEl.trigger('mouseout').off('mouseover', this.onHover)
.off('mouseout', this.onOut)
.off('click', this.onClick);
this.selEl = null;
var cw = this.getContentWindow();
cw.off('scroll', this.onFrameScroll);
cw.off('keydown', this.onKeyPress);
},
/**
* Returns canavs body el
*/
getCanvasBodyEl: function() {
if(!this.$bodyEl) {
this.$bodyEl = $(this.getCanvasBody());
}
return this.$bodyEl;
},
/**
* Start select component event
* @private
* */
startSelectComponent: function() {
this.toggleSelectComponent(1);
},
/**
* Stop select component event
* @private
* */
stopSelectComponent: function() {
this.toggleSelectComponent();
},
/**
* Toggle select component event
* @private
* */
toggleSelectComponent: function(enable) {
var el = '*';
var method = enable ? 'on' : 'off';
this.getCanvasBodyEl()
[method]('mouseover', el, this.onHover)
[method]('mouseout', el, this.onOut)
[method]('click', el, this.onClick);
var cw = this.getContentWindow();
cw[method]('scroll', this.onFrameScroll);
cw[method]('keydown', this.onKeyPress);
},
/**
* On key press event
@ -120,35 +136,88 @@ define(function(require) {
}
},
/**
* Hover command
* @param {Object} e
* @private
*/
onHover: function(e) {
e.stopPropagation();
var trg = e.target;
// Adjust tools scroll top
if(!this.adjScroll){
this.adjScroll = 1;
this.onFrameScroll(e);
}
var pos = this.getElementPos(trg);
this.updateBadge(trg, pos);
// Not mirrored
this.updateHighlighter(trg, pos);
},
/**
* Out command
* @param {Object} e
* @private
*/
onOut: function(e) {
e.stopPropagation();
this.hideBadge();
this.hideHighlighter();
},
/**
* Hover command
* @param {Object} e
* @private
*/
onHover: function(e) {
e.stopPropagation();
var trg = e.target;
// Adjust tools scroll top
if(!this.adjScroll){
this.adjScroll = 1;
this.onFrameScroll(e);
this.updateAttached();
}
var pos = this.getElementPos(trg);
this.updateBadge(trg, pos);
this.updateHighlighter(trg, pos);
this.showElementOffset(trg, pos);
},
/**
* Out command
* @param {Object} e
* @private
*/
onOut: function(e) {
e.stopPropagation();
this.hideBadge();
this.hideHighlighter();
this.hideElementOffset();
},
/**
* Show element offset viewer
* @param {HTMLElement} el
* @param {Object} pos
*/
showElementOffset: function(el, pos) {
var $el = $(el);
var model = $el.data('model');
if(model && model.get('status') == 'selected'){
return;
}
this.editor.runCommand('show-offset', {
el: el,
elPos: pos,
});
},
/**
* Hide element offset viewer
* @param {HTMLElement} el
* @param {Object} pos
*/
hideElementOffset: function(el, pos) {
this.editor.stopCommand('show-offset');
},
/**
* Show fixed element offset viewer
* @param {HTMLElement} el
* @param {Object} pos
*/
showFixedElementOffset: function(el, pos) {
this.editor.runCommand('show-offset', {
el: el,
elPos: pos,
state: 'Fixed',
});
},
/**
* Hide fixed element offset viewer
* @param {HTMLElement} el
* @param {Object} pos
*/
hideFixedElementOffset: function(el, pos) {
if(this.editor)
this.editor.stopCommand('show-offset', {state: 'Fixed'});
},
/**
* Hide Highlighter element
@ -246,70 +315,67 @@ define(function(require) {
this.editorModel.set('selectedComponent', nMd);
nMd.set('status','selected');
//this.updateToolbar(nMd);
this.showFixedElementOffset(el);
this.hideElementOffset();
}
},
/**
* Update toolbar if the component has one
* @param {Object} mod
*/
updateToolbar: function(mod) {
var em = this.config.em;
var model = mod == em ? em.get('selectedComponent') : mod;
if(!model){
return;
}
var toolbar = model.get('toolbar');
var ppfx = this.ppfx;
var showToolbar = em.get('Config').showToolbar;
if (showToolbar && toolbar && toolbar.length) {
if(!this.toolbar) {
var toolbarEl = this.canvas.getToolbarEl();
toolbarEl.innerHTML = '';
this.toolbar = new Toolbar(toolbar);
var toolbarView = new ToolbarView({
collection: this.toolbar,
editor: this.editor
});
toolbarEl.appendChild(toolbarView.render().el);
}
this.toolbar.reset(toolbar);
var view = model.view;
if(view) {
this.updateToolbarPos(view.el);
}
}
},
/**
* Update toolbar positions
* @param {HTMLElement} el
* @param {Object} pos
*/
updateToolbarPos: function(el, elPos) {
var toolbarEl = this.canvas.getToolbarEl();
var canvasPos = this.getCanvasPosition();
var pos = elPos || this.getElementPos(el);
var toolbarStyle = toolbarEl.style;
var unit = 'px';
toolbarStyle.display = 'flex';
var elTop = pos.top - toolbarEl.offsetHeight;
var elLeft = pos.left + pos.width - toolbarEl.offsetWidth;
var leftPos = elLeft < canvasPos.left ? canvasPos.left : elLeft;
// This will make the toolbar follow the window up
// and down while scrolling
var topPos = elTop < canvasPos.top ? canvasPos.top : elTop;
// This will stop the toolbar when the end of the element is reached
topPos = topPos > (pos.top + pos.height) ? (pos.top + pos.height) : topPos;
toolbarStyle.top = topPos + unit;
toolbarStyle.left = leftPos + unit;
},
/**
* Update toolbar if the component has one
* @param {Object} mod
*/
updateToolbar: function(mod) {
var em = this.config.em;
var model = mod == em ? em.get('selectedComponent') : mod;
if(!model){
return;
}
var toolbar = model.get('toolbar');
var ppfx = this.ppfx;
var showToolbar = em.get('Config').showToolbar;
var toolbarEl = this.canvas.getToolbarEl();
var toolbarStyle = toolbarEl.style;
if (showToolbar && toolbar && toolbar.length) {
toolbarStyle.display = 'flex';
if(!this.toolbar) {
toolbarEl.innerHTML = '';
this.toolbar = new Toolbar(toolbar);
var toolbarView = new ToolbarView({
collection: this.toolbar,
editor: this.editor
});
toolbarEl.appendChild(toolbarView.render().el);
}
this.toolbar.reset(toolbar);
var view = model.view;
if(view) {
this.updateToolbarPos(view.el);
}
} else {
toolbarStyle.display = 'none';
}
},
/**
* Update toolbar positions
* @param {HTMLElement} el
* @param {Object} pos
*/
updateToolbarPos: function(el, elPos) {
var unit = 'px';
var toolbarEl = this.canvas.getToolbarEl();
var toolbarStyle = toolbarEl.style;
var pos = this.canvas.getTargetToElementDim(toolbarEl, el, {
elPos: elPos,
event: 'toolbarPosUpdate',
});
var leftPos = pos.left + pos.elementWidth - pos.targetWidth;
toolbarStyle.top = pos.top + unit;
toolbarStyle.left = leftPos + unit;
},
/**
* Return canvas dimensions and positions
@ -319,99 +385,114 @@ define(function(require) {
return this.canvas.getCanvasView().getPosition();
},
/**
* Removes all highlighting effects on components
* @private
* */
clean: function() {
if(this.selEl)
this.selEl.removeClass(this.hoverClass);
},
/**
* Returns badge element
* @return {HTMLElement}
* @private
*/
getBadge: function(){
return this.canvas.getBadgeEl();
},
/**
* On frame scroll callback
* @private
*/
onFrameScroll: function(e){
var el = this.cacheEl;
if(el){
var elPos = this.getElementPos(el);
this.updateBadge(el, elPos);
var model = this.editorModel.get('selectedComponent');
if (model) {
var view = model.view;
this.updateToolbarPos(view.el);
}
}
},
/**
* Returns element's data info
* @param {HTMLElement} el
* @return {Object}
* @private
*/
getElementPos: function(el, badge){
return this.canvas.getCanvasView().getElementPos(el);
},
/**
* Hide badge
* @private
* */
hideBadge: function () {
this.getBadge().style.display = 'none';
},
/**
* Clean previous model from different states
* @param {Component} model
* @private
*/
cleanPrevious: function(model) {
if(model)
model.set({
status: '',
state: '',
});
},
/**
* Returns content window
* @private
*/
getContentWindow: function(){
if(!this.contWindow)
this.contWindow = $(this.frameEl.contentWindow);
return this.contWindow;
},
run: function(em) {
if(em && em.get)
this.editor = em.get('Editor');
this.enable();
},
stop: function() {
this.stopSelectComponent();
this.cleanPrevious(this.em.get('selectedComponent'));
this.clean();
this.em.set('selectedComponent', null);
this.toggleClipboard();
this.hideBadge();
this.canvas.getToolbarEl().style.display = 'none';
this.em.off('change:canvasOffset', this.onFrameScroll);
this.em.off('change:selectedComponent', this.updateToolbar, this);
}
};
/**
* Removes all highlighting effects on components
* @private
* */
clean: function() {
if(this.selEl)
this.selEl.removeClass(this.hoverClass);
},
/**
* Returns badge element
* @return {HTMLElement}
* @private
*/
getBadge: function(){
return this.canvas.getBadgeEl();
},
/**
* On frame scroll callback
* @private
*/
onFrameScroll: function(e){
var el = this.cacheEl;
if (el) {
var elPos = this.getElementPos(el);
this.updateBadge(el, elPos);
var model = this.em.get('selectedComponent');
if (model) {
this.updateToolbarPos(model.view.el);
}
}
},
/**
* Update attached elements, eg. component toolbar
* @return {[type]} [description]
*/
updateAttached: function() {
var model = this.em.get('selectedComponent');
if (model) {
var view = model.view;
this.updateToolbarPos(view.el);
this.showFixedElementOffset(view.el);
}
},
/**
* Returns element's data info
* @param {HTMLElement} el
* @return {Object}
* @private
*/
getElementPos: function(el, badge){
return this.canvas.getCanvasView().getElementPos(el);
},
/**
* Hide badge
* @private
* */
hideBadge: function () {
this.getBadge().style.display = 'none';
},
/**
* Clean previous model from different states
* @param {Component} model
* @private
*/
cleanPrevious: function(model) {
if(model)
model.set({
status: '',
state: '',
});
},
/**
* Returns content window
* @private
*/
getContentWindow: function(){
if(!this.contWindow)
this.contWindow = $(this.frameEl.contentWindow);
return this.contWindow;
},
run: function(em) {
if(em && em.get)
this.editor = em.get('Editor');
this.enable();
},
stop: function() {
this.stopSelectComponent();
this.cleanPrevious(this.em.get('selectedComponent'));
this.clean();
this.em.set('selectedComponent', null);
this.toggleClipboard();
this.hideBadge();
this.hideFixedElementOffset();
this.canvas.getToolbarEl().style.display = 'none';
this.em.off('component:update', this.updateAttached, this);
this.em.off('change:canvasOffset', this.updateAttached, this);
this.em.off('change:selectedComponent', this.updateToolbar, this);
}
};
});

146
src/commands/view/ShowOffset.js

@ -0,0 +1,146 @@
define(function() {
return {
getOffsetMethod: function(state) {
var method = state || '';
return 'get' + method + 'OffsetViewerEl';
},
run: function(editor, sender, opts) {
if (!editor.getConfig().showOffsets) {
return;
}
var canvas = editor.Canvas;
var opt = opts || {};
var el = opt.el || '';
var state = opt.state || '';
var pos = opt.elPos || canvas.getElementPos(el);
var style = window.getComputedStyle(el);
var ppfx = this.ppfx;
var stateVar = state + 'State';
var method = this.getOffsetMethod(state);
var offsetViewer = canvas[method]();
offsetViewer.style.display = 'block';
var marginT = this['marginT' + state];
var marginB = this['marginB' + state];
var marginL = this['marginL' + state];
var marginR = this['marginR' + state];
var padT = this['padT' + state];
var padB = this['padB' + state];
var padL = this['padL' + state];
var padR = this['padR' + state];
if(!this[stateVar]) {
var stateLow = state.toLowerCase();
var marginName = stateLow + 'margin-v';
var paddingName = stateLow + 'padding-v';
var marginV = $('<div>', {class: ppfx + marginName}).get(0);
var paddingV = $('<div>', {class: ppfx + paddingName}).get(0);
var marginEls = ppfx + marginName + '-el';
var paddingEls = ppfx + paddingName + '-el';
marginT = $('<div>', {class: ppfx + marginName + '-top ' + marginEls}).get(0);
marginB = $('<div>', {class: ppfx + marginName + '-bottom ' + marginEls}).get(0);
marginL = $('<div>', {class: ppfx + marginName + '-left ' + marginEls}).get(0);
marginR = $('<div>', {class: ppfx + marginName + '-right ' + marginEls}).get(0);
padT = $('<div>', {class: ppfx + paddingName + '-top ' + paddingEls}).get(0);
padB = $('<div>', {class: ppfx + paddingName + '-bottom ' + paddingEls}).get(0);
padL = $('<div>', {class: ppfx + paddingName + '-left ' + paddingEls}).get(0);
padR = $('<div>', {class: ppfx + paddingName + '-right ' + paddingEls}).get(0);
this['marginT' + state] = marginT;
this['marginB' + state] = marginB;
this['marginL' + state] = marginL;
this['marginR' + state] = marginR;
this['padT' + state] = padT;
this['padB' + state] = padB;
this['padL' + state] = padL;
this['padR' + state] = padR;
marginV.appendChild(marginT);
marginV.appendChild(marginB);
marginV.appendChild(marginL);
marginV.appendChild(marginR);
paddingV.appendChild(padT);
paddingV.appendChild(padB);
paddingV.appendChild(padL);
paddingV.appendChild(padR);
offsetViewer.appendChild(marginV);
offsetViewer.appendChild(paddingV);
this[stateVar] = '1';
}
var unit = 'px';
var marginLeftSt = style.marginLeft.replace(unit, '');
var marginTopSt = parseInt(style.marginTop.replace(unit, ''));
var marginBottomSt = parseInt(style.marginBottom.replace(unit, ''));
var mtStyle = marginT.style;
var mbStyle = marginB.style;
var mlStyle = marginL.style;
var mrStyle = marginR.style;
var ptStyle = padT.style;
var pbStyle = padB.style;
var plStyle = padL.style;
var prStyle = padR.style;
var posLeft = parseInt(pos.left);
// Margin style
mtStyle.height = style.marginTop;
mtStyle.width = style.width;
mtStyle.top = pos.top - style.marginTop.replace(unit, '') + unit;
mtStyle.left = posLeft + unit;
mbStyle.height = style.marginBottom;
mbStyle.width = style.width;
mbStyle.top = pos.top + pos.height + unit;
mbStyle.left = posLeft + unit;
var marginSideH = pos.height + marginTopSt + marginBottomSt + unit;
var marginSideT = pos.top - marginTopSt + unit;
mlStyle.height = marginSideH;
mlStyle.width = style.marginLeft;
mlStyle.top = marginSideT;
mlStyle.left = posLeft - marginLeftSt + unit;
mrStyle.height = marginSideH;
mrStyle.width = style.marginRight;
mrStyle.top = marginSideT;
mrStyle.left = posLeft + pos.width + unit;
// Padding style
var padTop = parseInt(style.paddingTop.replace(unit, ''));
ptStyle.height = style.paddingTop;
ptStyle.width = style.width;
ptStyle.top = pos.top + unit;
ptStyle.left = posLeft + unit;
var padBot = parseInt(style.paddingBottom.replace(unit, ''));
pbStyle.height = style.paddingBottom;
pbStyle.width = style.width;
pbStyle.top = pos.top + pos.height - padBot + unit;
pbStyle.left = posLeft + unit;
var padSideH = (pos.height - padBot - padTop) + unit;
var padSideT = pos.top + padTop + unit;
plStyle.height = padSideH;
plStyle.width = style.paddingLeft;
plStyle.top = padSideT;
plStyle.left = pos.left + unit;
var padRight = parseInt(style.paddingRight.replace(unit, ''));
prStyle.height = padSideH;
prStyle.width = style.paddingRight;
prStyle.top = padSideT;
prStyle.left = pos.left + pos.width - padRight + unit;
},
stop: function(editor, sender, opts) {
var opt = opts || {};
var state = opt.state || '';
var method = this.getOffsetMethod(state);
var canvas = editor.Canvas;
var offsetViewer = canvas[method]();
offsetViewer.style.display = 'none';
},
};
});

383
src/editor/config/config.js

@ -1,6 +1,6 @@
define(function () {
var blkStyle = '.blk-row::after{ content: ""; clear: both; display: block;} .blk-row{padding: 10px;}';
return {
var blkStyle = '.blk-row::after{ content: ""; clear: both; display: block;} .blk-row{padding: 10px;}';
return {
// Style prefix
stylePrefix: 'gjs-',
@ -17,6 +17,9 @@ define(function () {
// Enable/Disable undo manager
undoManager: true,
// Show paddings and margins
showOffsets: false,
// Height for the editor container
height: '900px',
@ -88,192 +91,192 @@ define(function () {
//Configurations for Selector Manager
selectorManager: {},
//Configurations for Device Manager
deviceManager: {
'devices': [{
name: 'Desktop',
width: '',
},{
name: 'Tablet',
width: '992px',
},{
name: 'Mobile landscape',
width: '768px',
},{
name: 'Mobile portrait',
width: '480px',
}],
},
//Configurations for Style Manager
styleManager: {
sectors: [{
name: 'General',
open: false,
buildProps: ['float', 'display', 'position', 'top', 'right', 'left', 'bottom'],
},{
name: 'Dimension',
open: false,
buildProps: ['width', 'height', 'max-width', 'min-height', 'margin', 'padding'],
},{
name: 'Typography',
open: false,
buildProps: ['font-family', 'font-size', 'font-weight', 'letter-spacing', 'color', 'line-height', 'text-align', 'text-shadow'],
properties: [{
property: 'text-align',
list : [
{value: 'left', className: 'fa fa-align-left'},
{value: 'center', className: 'fa fa-align-center' },
{value: 'right', className: 'fa fa-align-right'},
{value: 'justify', className: 'fa fa-align-justify'}
],
}]
},{
name: 'Decorations',
open: false,
buildProps: ['border-radius-c', 'background-color', 'border-radius', 'border', 'box-shadow', 'background'],
},{
name: 'Extra',
open: false,
buildProps: ['transition', 'perspective', 'transform'],
}],
},
//Configurations for Block Manager
blockManager: {
'blocks': [{
id: 'b1',
label: '1 Block',
content: '<div class="blk-row"><div class="blk1"></div></div><style>'+ blkStyle +'.blk1{width: 100%;padding: 10px;min-height: 75px;}</style>',
attributes: {class:'gjs-fonts gjs-f-b1'}
},{
id: 'b2',
label: '2 Blocks',
content: '<div class="blk-row"><div class="blk2"></div><div class="blk2"></div></div><style>'+ blkStyle +'.blk2{float: left;width: 50%;padding: 10px;min-height: 75px;}</style>',
attributes: {class:'gjs-fonts gjs-f-b2'}
},{
id: 'b3',
label: '3 Blocks',
content: '<div class="blk-row"><div class="blk3"></div><div class="blk3"></div><div class="blk3"></div></div><style>'+ blkStyle +'.blk3{float: left;width: 33.3333%;padding: 10px;min-height: 75px;}</style>',
attributes: {class:'gjs-fonts gjs-f-b3'}
},{
id: 'b4',
label: '3/7 Block',
content: '<div class="blk-row"><div class="blk37l"></div><div class="blk37r"></div></div></div><style>'+ blkStyle +'.blk37l{float: left;width: 30%;padding: 10px;min-height: 75px;}.blk37r{float: left;width: 70%;padding: 10px;min-height: 75px;}</style>',
attributes: {class:'gjs-fonts gjs-f-b37'}
},{
id: 'hero',
label: 'Hero section',
content: '<header class="header-banner"> <div class="container-width">'+
'<div class="logo-container"><div class="logo">GrapesJS</div></div>'+
'<nav class="navbar">'+
'<div class="menu-item">BUILDER</div><div class="menu-item">TEMPLATE</div><div class="menu-item">WEB</div>'+
'</nav><div class="clearfix"></div>'+
'<div class="lead-title">Build your templates without coding</div>'+
'<div class="lead-btn">Try it now</div></div></header>',
attributes: {class:'gjs-fonts gjs-f-hero'}
},{
id: 'h1p',
label: 'Text section',
content: '<h1 class="heading">Insert title here</h1><p class="paragraph">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</p>',
attributes: {class:'gjs-fonts gjs-f-h1p'}
},{
id: '3ba',
label: 'Badges',
content: '<div class="badges">'+
'<div class="badge">'+
'<div class="badge-header"></div>'+
'<img class="badge-avatar" src="img/team1.jpg">'+
'<div class="badge-body">'+
'<div class="badge-name">Adam Smith</div><div class="badge-role">CEO</div><div class="badge-desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore ipsum dolor sit</div>'+
'</div>'+
'<div class="badge-foot"><span class="badge-link">f</span><span class="badge-link">t</span><span class="badge-link">ln</span></div>'+
'</div>'+
'<div class="badge">'+
'<div class="badge-header"></div>'+
'<img class="badge-avatar" src="img/team2.jpg">'+
'<div class="badge-body">'+
'<div class="badge-name">John Black</div><div class="badge-role">Software Engineer</div><div class="badge-desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore ipsum dolor sit</div>'+
'</div>'+
'<div class="badge-foot"><span class="badge-link">f</span><span class="badge-link">t</span><span class="badge-link">ln</span></div>'+
'</div>'+
'<div class="badge">'+
'<div class="badge-header"></div>'+
'<img class="badge-avatar" src="img/team3.jpg">'+
'<div class="badge-body">'+
'<div class="badge-name">Jessica White</div><div class="badge-role">Web Designer</div><div class="badge-desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore ipsum dolor sit</div>'+
'</div>'+
'<div class="badge-foot"><span class="badge-link">f</span><span class="badge-link">t</span><span class="badge-link">ln</span>'+
'</div>'+
'</div></div>',
attributes: {class:'gjs-fonts gjs-f-3ba'}
},{
id: 'text',
label: 'Text',
attributes: {class:'gjs-fonts gjs-f-text'},
content: {
type:'text',
content:'Insert your text here',
style: {padding: '10px' },
activeOnRender: 1
},
},{
id: 'image',
label: 'Image',
attributes: {class:'gjs-fonts gjs-f-image'},
content: {
style: {color: 'black'},
type:'image',
activeOnRender: 1
},
},{
id: 'quo',
label: 'Quote',
content: '<blockquote class="quote">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore ipsum dolor sit</blockquote>',
attributes: {class:'fa fa-quote-right'}
},{
id: 'link',
label: 'Link',
attributes: {class:'fa fa-link'},
content: {
type:'link',
content:'Link',
style:{color: '#d983a6'}
},
},{
id: 'map',
label: 'Map',
attributes: {class:'fa fa-map-o'},
content: {
type: 'map',
style: {height: '350px'}
},
},{
id: 'video',
label: 'Video',
attributes: {class:'fa fa-youtube-play'},
content: {
type: 'video',
src: 'img/video2.webm',
style: {
height: '350px',
width: '615px',
}
},
}/*,{
id: 'table',
label: 'Table',
attributes: {class:'fa fa-table'},
content: {
type: 'table',
columns: 3,
rows: 5,
style: {height: '150px', width: '100%'}
},
}*/],
},
};
//Configurations for Device Manager
deviceManager: {
'devices': [{
name: 'Desktop',
width: '',
},{
name: 'Tablet',
width: '992px',
},{
name: 'Mobile landscape',
width: '768px',
},{
name: 'Mobile portrait',
width: '480px',
}],
},
//Configurations for Style Manager
styleManager: {
sectors: [{
name: 'General',
open: false,
buildProps: ['float', 'display', 'position', 'top', 'right', 'left', 'bottom'],
},{
name: 'Dimension',
open: false,
buildProps: ['width', 'height', 'max-width', 'min-height', 'margin', 'padding'],
},{
name: 'Typography',
open: false,
buildProps: ['font-family', 'font-size', 'font-weight', 'letter-spacing', 'color', 'line-height', 'text-align', 'text-shadow'],
properties: [{
property: 'text-align',
list : [
{value: 'left', className: 'fa fa-align-left'},
{value: 'center', className: 'fa fa-align-center' },
{value: 'right', className: 'fa fa-align-right'},
{value: 'justify', className: 'fa fa-align-justify'}
],
}]
},{
name: 'Decorations',
open: false,
buildProps: ['border-radius-c', 'background-color', 'border-radius', 'border', 'box-shadow', 'background'],
},{
name: 'Extra',
open: false,
buildProps: ['transition', 'perspective', 'transform'],
}],
},
//Configurations for Block Manager
blockManager: {
'blocks': [{
id: 'b1',
label: '1 Block',
content: '<div class="blk-row"><div class="blk1"></div></div><style>'+ blkStyle +'.blk1{width: 100%;padding: 10px;min-height: 75px;}</style>',
attributes: {class:'gjs-fonts gjs-f-b1'}
},{
id: 'b2',
label: '2 Blocks',
content: '<div class="blk-row"><div class="blk2"></div><div class="blk2"></div></div><style>'+ blkStyle +'.blk2{float: left;width: 50%;padding: 10px;min-height: 75px;}</style>',
attributes: {class:'gjs-fonts gjs-f-b2'}
},{
id: 'b3',
label: '3 Blocks',
content: '<div class="blk-row"><div class="blk3"></div><div class="blk3"></div><div class="blk3"></div></div><style>'+ blkStyle +'.blk3{float: left;width: 33.3333%;padding: 10px;min-height: 75px;}</style>',
attributes: {class:'gjs-fonts gjs-f-b3'}
},{
id: 'b4',
label: '3/7 Block',
content: '<div class="blk-row"><div class="blk37l"></div><div class="blk37r"></div></div></div><style>'+ blkStyle +'.blk37l{float: left;width: 30%;padding: 10px;min-height: 75px;}.blk37r{float: left;width: 70%;padding: 10px;min-height: 75px;}</style>',
attributes: {class:'gjs-fonts gjs-f-b37'}
},{
id: 'hero',
label: 'Hero section',
content: '<header class="header-banner"> <div class="container-width">'+
'<div class="logo-container"><div class="logo">GrapesJS</div></div>'+
'<nav class="navbar">'+
'<div class="menu-item">BUILDER</div><div class="menu-item">TEMPLATE</div><div class="menu-item">WEB</div>'+
'</nav><div class="clearfix"></div>'+
'<div class="lead-title">Build your templates without coding</div>'+
'<div class="lead-btn">Try it now</div></div></header>',
attributes: {class:'gjs-fonts gjs-f-hero'}
},{
id: 'h1p',
label: 'Text section',
content: '<h1 class="heading">Insert title here</h1><p class="paragraph">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</p>',
attributes: {class:'gjs-fonts gjs-f-h1p'}
},{
id: '3ba',
label: 'Badges',
content: '<div class="badges">'+
'<div class="badge">'+
'<div class="badge-header"></div>'+
'<img class="badge-avatar" src="img/team1.jpg">'+
'<div class="badge-body">'+
'<div class="badge-name">Adam Smith</div><div class="badge-role">CEO</div><div class="badge-desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore ipsum dolor sit</div>'+
'</div>'+
'<div class="badge-foot"><span class="badge-link">f</span><span class="badge-link">t</span><span class="badge-link">ln</span></div>'+
'</div>'+
'<div class="badge">'+
'<div class="badge-header"></div>'+
'<img class="badge-avatar" src="img/team2.jpg">'+
'<div class="badge-body">'+
'<div class="badge-name">John Black</div><div class="badge-role">Software Engineer</div><div class="badge-desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore ipsum dolor sit</div>'+
'</div>'+
'<div class="badge-foot"><span class="badge-link">f</span><span class="badge-link">t</span><span class="badge-link">ln</span></div>'+
'</div>'+
'<div class="badge">'+
'<div class="badge-header"></div>'+
'<img class="badge-avatar" src="img/team3.jpg">'+
'<div class="badge-body">'+
'<div class="badge-name">Jessica White</div><div class="badge-role">Web Designer</div><div class="badge-desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore ipsum dolor sit</div>'+
'</div>'+
'<div class="badge-foot"><span class="badge-link">f</span><span class="badge-link">t</span><span class="badge-link">ln</span>'+
'</div>'+
'</div></div>',
attributes: {class:'gjs-fonts gjs-f-3ba'}
},{
id: 'text',
label: 'Text',
attributes: {class:'gjs-fonts gjs-f-text'},
content: {
type:'text',
content:'Insert your text here',
style: {padding: '10px' },
activeOnRender: 1
},
},{
id: 'image',
label: 'Image',
attributes: {class:'gjs-fonts gjs-f-image'},
content: {
style: {color: 'black'},
type:'image',
activeOnRender: 1
},
},{
id: 'quo',
label: 'Quote',
content: '<blockquote class="quote">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore ipsum dolor sit</blockquote>',
attributes: {class:'fa fa-quote-right'}
},{
id: 'link',
label: 'Link',
attributes: {class:'fa fa-link'},
content: {
type:'link',
content:'Link',
style:{color: '#d983a6'}
},
},{
id: 'map',
label: 'Map',
attributes: {class:'fa fa-map-o'},
content: {
type: 'map',
style: {height: '350px'}
},
},{
id: 'video',
label: 'Video',
attributes: {class:'fa fa-youtube-play'},
content: {
type: 'video',
src: 'img/video2.webm',
style: {
height: '350px',
width: '615px',
}
},
}/*,{
id: 'table',
label: 'Table',
attributes: {class:'fa fa-table'},
content: {
type: 'table',
columns: 3,
rows: 5,
style: {height: '150px', width: '100%'}
},
}*/],
},
};
});

2
src/editor/main.js

@ -28,6 +28,8 @@
* ```
* Available events
* #add:component - Triggered when a new component is added to the editor, the model is passed as an argument to the callback
* #component:update - Triggered when a component is, generally, updated (moved, styled, etc.)
* #component:styleUpdate - Triggered when the style of the component is updated
* #canvasScroll - Triggered when the canvas is scrolled
* #run:{commandName} - Triggered when some command is called to run (eg. editor.runCommand('preview'))
* #stop:{commandName} - Triggered when some command is called to stop (eg. editor.stopCommand('preview'))

7
src/style_manager/view/PropertyView.js

@ -144,7 +144,7 @@ define(['backbone', 'text!./../templates/propertyLabel.html', 'text!./../templat
* @param {Mixed} val Value
* @param {Object} opt Options
* */
valueChanged: function(e, val, opt){
valueChanged: function(e, val, opt) {
var mVal = this.getValueForTarget();
if(this.$input)
@ -170,6 +170,11 @@ define(['backbone', 'text!./../templates/propertyLabel.html', 'text!./../templat
onChange(target, this, opt);
}else
this.updateTargetStyle(value, null, opt);
var model = this.model;
this.config.em.trigger('component:update', model);
this.config.em.trigger('component:styleUpdate', model);
this.config.em.trigger('component:styleUpdate:' + model.get('property'), model);
},
/**

23
styles/css/main.css

@ -2647,7 +2647,10 @@ $fontColorActive: #4f8ef7;
-o-user-select: none;
user-select: none; }
.gjs-no-pointer-events, .gjs-resizer-c {
.gjs-no-pointer-events, .gjs-resizer-c, .gjs-margin-v-el,
.gjs-padding-v-el,
.gjs-fixedmargin-v-el,
.gjs-fixedpadding-v-el {
pointer-events: none; }
.gjs-bg-main, .gjs-off-prv, .gjs-select option,
@ -2859,6 +2862,24 @@ div.gjs-select {
position: absolute;
z-index: 9; }
.gjs-margin-v-el,
.gjs-padding-v-el,
.gjs-fixedmargin-v-el,
.gjs-fixedpadding-v-el {
opacity: 0.1;
filter: alpha(opacity=10);
position: absolute;
background-color: yellow; }
.gjs-fixedmargin-v-el,
.gjs-fixedpadding-v-el {
opacity: 0.2;
filter: alpha(opacity=20); }
.gjs-padding-v-el,
.gjs-fixedpadding-v-el {
background-color: navy; }
.gjs-resizer-h {
pointer-events: all;
position: absolute;

26
styles/scss/_gjs_canvas.scss

@ -91,6 +91,32 @@
z-index: 9;
}
.#{$app-prefix}margin-v {
}
.#{$app-prefix}margin-v-el,
.#{$app-prefix}padding-v-el,
.#{$app-prefix}fixedmargin-v-el,
.#{$app-prefix}fixedpadding-v-el {
@extend .#{$app-prefix}no-pointer-events;
@include opacity(0.1);
position: absolute;
background-color: yellow;
}
.#{$app-prefix}fixedmargin-v-el,
.#{$app-prefix}fixedpadding-v-el {
@include opacity(0.2);
}
.#{$app-prefix}padding-v-el,
.#{$app-prefix}fixedpadding-v-el {
background-color: navy;
}
$hndlMargin: -5px;
.#{$app-prefix}resizer-h {

Loading…
Cancel
Save