Browse Source

Merge branch 'dev' of https://github.com/artf/grapesjs into dev

pull/539/head
Michal Tomaszewski 9 years ago
parent
commit
23bc3d6aba
  1. 1
      README.md
  2. 2
      dist/css/grapes.min.css
  3. 46621
      dist/grapes.js
  4. 6
      dist/grapes.min.js
  5. 1422
      index.html
  6. 2
      package-lock.json
  7. 12
      package.json
  8. 4
      src/asset_manager/view/AssetImageView.js
  9. 5
      src/block_manager/view/BlockView.js
  10. 25
      src/commands/index.js
  11. 2
      src/commands/view/SelectComponent.js
  12. 12
      src/css_composer/index.js
  13. 8
      src/dom_components/model/Component.js
  14. 4
      src/dom_components/model/ComponentImage.js
  15. 29
      src/dom_components/view/ComponentImageView.js
  16. 3
      src/domain_abstract/ui/InputColor.js
  17. 26
      src/editor/index.js
  18. 13
      src/editor/model/Editor.js
  19. 2
      src/editor/view/EditorView.js
  20. 54
      src/modal_dialog/view/ModalView.js
  21. 4
      src/navigator/view/ItemView.js
  22. 65
      src/panels/view/ButtonView.js
  23. 18
      src/panels/view/PanelView.js
  24. 2
      src/rich_text_editor/index.js
  25. 9
      src/selector_manager/view/ClassTagView.js
  26. 16
      src/storage_manager/index.js
  27. 1
      src/style_manager/view/LayerView.js
  28. 2
      src/style_manager/view/PropertyStackView.js
  29. 2
      src/style_manager/view/PropertyView.js
  30. 4
      src/styles/scss/_gjs_blocks.scss
  31. 6
      src/styles/scss/_gjs_inputs.scss
  32. 4
      src/styles/scss/_gjs_layers.scss
  33. 3
      src/styles/scss/_gjs_rte.scss
  34. 2
      src/styles/scss/_gjs_style_manager.scss
  35. 12
      src/styles/scss/_gjs_variables.scss
  36. 53
      src/styles/scss/main.scss
  37. 27
      src/utils/Sorter.js
  38. 2
      test/specs/asset_manager/view/AssetImageView.js
  39. 10
      test/specs/dom_components/model/Component.js
  40. 4
      test/specs/panels/view/ButtonView.js
  41. 3
      test/specs/panels/view/PanelView.js
  42. 87
      webpack.config.js

1
README.md

@ -193,6 +193,7 @@ $ npm test
* [grapesjs-style-gradient](https://github.com/artf/grapesjs-style-gradient) - Add a gradient type input
### Presets
* [grapesjs-preset-webpage](https://github.com/artf/grapesjs-preset-webpage) - Webpage Builder
* [grapesjs-preset-newsletter](https://github.com/artf/grapesjs-preset-newsletter) - Newsletter Builder
* [grapesjs-mjml](https://github.com/artf/grapesjs-mjml) - Newsletter Builder with MJML components

2
dist/css/grapes.min.css

File diff suppressed because one or more lines are too long

46621
dist/grapes.js

File diff suppressed because it is too large

6
dist/grapes.min.js

File diff suppressed because one or more lines are too long

1422
index.html

File diff suppressed because it is too large

2
package-lock.json

@ -1,6 +1,6 @@
{
"name": "grapesjs",
"version": "0.12.37",
"version": "0.12.45",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

12
package.json

@ -1,11 +1,11 @@
{
"name": "grapesjs",
"description": "Free and Open Source Web Builder Framework",
"version": "0.12.37",
"version": "0.12.45",
"author": "Artur Arseniev",
"license": "BSD-3-Clause",
"homepage": "http://grapesjs.com",
"main": "dist/grapes.min.js",
"main": "dist/grapes.js",
"repository": {
"type": "git",
"url": "https://github.com/artf/grapesjs.git"
@ -74,11 +74,13 @@
},
"scripts": {
"lint": "eslint src",
"build": "cross-env WEBPACK_ENV=prod && npm run lint && npm run test && npm run v:patch && webpack && npm run build:css",
"build-n": "cross-env WEBPACK_ENV=prod && npm run lint && npm run test && webpack && npm run build:css",
"check": "npm run lint && npm run test",
"build": "npm run check && npm run v:patch && npm run build-dev && webpack --env=prod",
"build-n": "npm run check && npm run build:css && webpack --env=prod",
"build-dev": "webpack --env=dev && npm run build:css",
"build:css": "node-sass src/styles/scss/main.scss dist/css/grapes.min.css --output-style compressed",
"v:patch": "npm version --no-git-tag-version patch",
"start": "cross-env WEBPACK_ENV=dev webpack-dev-server --progress --colors & npm run build:css -- -w",
"start": "webpack-dev-server --open --progress --colors & npm run build:css -- -w",
"test": "cross-env NODE_PATH=./src mocha --compilers js:babel-core/register --require test/helper.js --timeout 10000 --recursive test/main.js",
"test:dev": "npm test -- -R min -w"
}

4
src/asset_manager/view/AssetImageView.js

@ -1,9 +1,9 @@
module.exports = require('./AssetView').extend({
events: {
'click [data-toggle=asset-remove]': 'onRemove',
click: 'onClick',
dblclick: 'onDblClick',
'click [data-toggle=asset-remove]': 'onRemove',
},
getPreview() {
@ -79,7 +79,7 @@ module.exports = require('./AssetView').extend({
* @private
* */
onRemove(e) {
e.stopPropagation();
e.stopImmediatePropagation();
this.model.collection.remove(this.model);
}
});

5
src/block_manager/view/BlockView.js

@ -53,8 +53,9 @@ module.exports = Backbone.View.extend({
render() {
const el = this.el;
const className = `${this.ppfx}block`;
el.className += ` ${className}`;
const pfx = this.ppfx;
const className = `${pfx}block`;
el.className += ` ${className} ${pfx}one-bg ${pfx}four-color-h`;
el.innerHTML = `<div class="${className}-label">${this.model.get('label')}</div>`;
return this;
},

25
src/commands/index.js

@ -38,6 +38,7 @@
* },
* ...
*/
import { isFunction } from 'underscore';
module.exports = () => {
var c = {},
@ -47,7 +48,11 @@ module.exports = () => {
AbsCommands = require('./view/CommandAbstract');
// Need it here as it would be used below
var add = function(id, obj){
var add = function(id, obj) {
if (isFunction(obj)) {
obj = { run: obj };
}
delete obj.initialize;
commands[id] = AbsCommands.extend(obj);
return this;
@ -193,6 +198,14 @@ module.exports = () => {
},
};
// Core commands
defaultCommands['core:undo'] = e => e.UndoManager.undo(1);
defaultCommands['core:redo'] = e => e.UndoManager.redo(1);
defaultCommands['core:canvas-clear'] = e => {
e.DomComponents.clear();
e.CssComposer.clear();
};
if(c.em)
c.model = c.em.get('Canvas');
@ -204,16 +217,20 @@ module.exports = () => {
/**
* 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
* @param {Object|Function} command Object representing your command,
* By passing just a function it's intended as a stateless command
* (just like passing an object with only `run` method).
* @return {this}
* @example
* commands.add('myCommand', {
* run: function(editor, sender){
* run(editor, sender) {
* alert('Hello world!');
* },
* stop: function(editor, sender){
* stop(editor, sender) {
* },
* });
* // As a function
* commands.add('myCommand2', editor => { ... });
* */
add,

2
src/commands/view/SelectComponent.js

@ -274,7 +274,7 @@ module.exports = {
var $el = $(el);
var model = $el.data('model');
if(!model || (model && model.get('status') == 'selected')) {
if(!model || !model.get("hoverable") || model.get('status') == 'selected') {
return;
}

12
src/css_composer/index.js

@ -3,6 +3,7 @@
* * [get](#get)
* * [set](#set)
* * [getAll](#getall)
* * [clear](#clear)
* * [load](#load)
* * [store](#store)
* * [setIdRule](#setidrule)
@ -231,6 +232,17 @@ module.exports = () => {
return rules;
},
/**
* Remove all rules
* @return {this}
*/
clear() {
this.getAll().reset();
return this;
},
/**
* Add a raw collection of rule objects
* This method overrides styles, in case, of already defined rule

8
src/dom_components/model/Component.js

@ -62,6 +62,12 @@ module.exports = Backbone.Model.extend(Styleable).extend({
// Hide the component inside Layers
layerable: true,
// Allow component to be selected when clicked
selectable: true,
// Shows a highlight outline when hovering on the element if true
hoverable: true,
// This property is used by the HTML exporter as void elements do not
// have closing tag, eg. <br/>, <hr/>, etc.
void: false,
@ -554,7 +560,7 @@ module.exports = Backbone.Model.extend(Styleable).extend({
for (let attr in attributes) {
const value = attributes[attr];
if (!isUndefined(value) && value !== '') {
if (!isUndefined(value)) {
attrs.push(`${attr}="${value}"`);
}
}

4
src/dom_components/model/ComponentImage.js

@ -2,7 +2,7 @@ var Component = require('./Component');
module.exports = Component.extend({
defaults: _.extend({}, Component.prototype.defaults, {
defaults: { ...Component.prototype.defaults,
type: 'image',
tagName: 'img',
src: '',
@ -12,7 +12,7 @@ module.exports = Component.extend({
highlightable: 0,
resizable: 1,
traits: ['alt']
}),
},
initialize(o, opt) {
Component.prototype.initialize.apply(this, arguments);

29
src/dom_components/view/ComponentImageView.js

@ -11,31 +11,29 @@ module.exports = ComponentView.extend({
},
initialize(o) {
const model = this.model;
ComponentView.prototype.initialize.apply(this, arguments);
this.listenTo(this.model, 'change:src', this.updateSrc);
this.listenTo(this.model, 'dblclick active', this.openModal);
this.classEmpty = this.ppfx + 'plh-image';
if(this.config.modal)
this.modal = this.config.modal;
if(this.config.am)
this.am = this.config.am;
this.listenTo(model, 'change:src', this.updateSrc);
this.listenTo(model, 'dblclick active', this.openModal);
this.classEmpty = `${this.ppfx}plh-image`;
const config = this.config;
config.modal && (this.modal = config.modal);
config.am && (this.am = config.am);
},
/**
* Update src attribute
* @private
* */
updateSrc() {
var src = this.model.get("src");
this.$el.attr('src', src);
if(!src)
this.$el.addClass(this.classEmpty);
else
this.$el.removeClass(this.classEmpty);
const src = this.model.get("src");
const el = this.$el;
el.attr('src', src);
el[src ? 'removeClass' : 'addClass'](this.classEmpty);
},
/**
* Open dialog for image changing
* @param {Object} e Event
@ -56,6 +54,7 @@ module.exports = ComponentView.extend({
}
},
render() {
this.updateAttributes();
this.updateClasses();

3
src/domain_abstract/ui/InputColor.js

@ -53,6 +53,7 @@ module.exports = Input.extend({
getColorEl() {
if (!this.colorEl) {
const self = this;
const ppfx = this.ppfx;
var model = this.model;
var colorEl = $(`<div class="${this.ppfx}field-color-picker"></div>`);
@ -66,8 +67,8 @@ module.exports = Input.extend({
let changed = 0;
let previousСolor;
this.$el.find(`[data-colorp-c]`).append(colorEl);
colorEl.spectrum({
containerClassName: `${ppfx}one-bg ${ppfx}two-color`,
appendTo: elToAppend || 'body',
maxSelectionSize: 8,
showPalette: true,

26
src/editor/index.js

@ -1,29 +1,4 @@
/**
*
* * [getConfig](#getconfig)
* * [getHtml](#gethtml)
* * [getCss](#getcss)
* * [getJs](#getjs)
* * [getComponents](#getcomponents)
* * [setComponents](#setcomponents)
* * [addComponents](#addcomponents)
* * [getStyle](#getstyle)
* * [setStyle](#setstyle)
* * [getSelected](#getselected)
* * [getSelectedToStyle](#getselectedtostyle)
* * [setDevice](#setdevice)
* * [getDevice](#getdevice)
* * [runCommand](#runcommand)
* * [stopCommand](#stopcommand)
* * [store](#store)
* * [load](#load)
* * [getContainer](#getcontainer)
* * [refresh](#refresh)
* * [on](#on)
* * [off](#off)
* * [trigger](#trigger)
* * [render](#render)
*
* Editor class contains the top level API which you'll probably use to custom the editor or extend it with plugins.
* You get the Editor instance on init method
*
@ -75,7 +50,6 @@
* * `canvasScroll` - Triggered when the canvas is scrolle
* * `load` - When the editor is loaded
*
* @module Editor
* @param {Object} config Configurations
* @param {string} config.container='' Selector for the editor container, eg. '#myEditor'
* @param {string|Array<Object>} [config.components=''] HTML string or object of components

13
src/editor/model/Editor.js

@ -281,9 +281,9 @@ module.exports = Backbone.Model.extend({
return;
} else {
var obj = {
"object": model,
"before": beforeCache,
"after": model.toJSON()
object: model,
before: beforeCache,
after: model.toJSON()
};
beforeCache = null;
return obj;
@ -305,6 +305,7 @@ module.exports = Backbone.Model.extend({
UndoManager.addUndoType("change:style", customUndoType);
UndoManager.addUndoType("change:attributes", customUndoType);
UndoManager.addUndoType("change:content", customUndoType);
UndoManager.addUndoType("change:src", customUndoType);
}
},
@ -349,7 +350,7 @@ module.exports = Backbone.Model.extend({
this.stopListening(classes, 'add remove', this.handleUpdates);
this.listenTo(classes, 'add remove', this.handleUpdates);
var evn = 'change:style change:content change:attributes';
var evn = 'change:style change:content change:attributes change:src';
this.stopListening(model, evn, this.handleUpdates);
this.listenTo(model, evn, this.handleUpdates);
@ -408,6 +409,10 @@ module.exports = Backbone.Model.extend({
model = $(el).data('model');
}
if (model && !model.get("selectable")) {
return;
}
this.set('selectedComponent', model, opts);
},

2
src/editor/view/EditorView.js

@ -31,7 +31,7 @@ module.exports = Backbone.View.extend({
el.append(model.get('Canvas').render());
el.append(this.pn.render());
el.attr('class', `${pfx}editor`);
el.attr('class', `${pfx}editor ${pfx}one-bg ${pfx}two-color`);
contEl.addClass(`${pfx}editor-cont`).empty().append(el);
return this;

54
src/modal_dialog/view/ModalView.js

@ -1,33 +1,35 @@
var Backbone = require('backbone');
module.exports = require('backbone').View.extend({
module.exports = Backbone.View.extend({
template: _.template(`
<div class="<%= pfx %>dialog">
<div class="<%= pfx %>header">
<div class="<%= pfx %>title"><%= title %></div>
<div class="<%= pfx %>btn-close">&Cross;</div>
template({pfx, ppfx, content, title}) {
return `<div class="${pfx}dialog ${ppfx}one-bg">
<div class="${pfx}header">
<div class="${pfx}title">${title}</div>
<div class="${pfx}btn-close">&Cross;</div>
</div>
<div class="<%= pfx %>content">
<div id="<%= pfx %>c"> <%= content %> </div>
<div class="${pfx}content">
<div id="${pfx}c">${content}</div>
<div style="clear:both"></div>
</div>
</div>
<div class="<%= pfx %>backlayer"></div>
<div class="<%= pfx %>collector" style="display: none"></div>`),
<div class="${pfx}backlayer"></div>
<div class="${pfx}collector" style="display: none"></div>`;
},
events: {},
initialize(o) {
this.config = o.config || {};
this.pfx = this.config.stylePrefix || '';
this.listenTo(this.model, 'change:open', this.updateOpen);
this.listenTo(this.model, 'change:title', this.updateTitle);
this.listenTo(this.model, 'change:content', this.updateContent);
this.events['click .'+this.pfx+'btn-close'] = 'hide';
if(this.config.backdrop)
this.events['click .'+this.pfx+'backlayer'] = 'hide';
const model = this.model;
const config = o.config || {};
const pfx = config.stylePrefix || '';
const bkd = config.backdrop;
this.config = config;
this.pfx = pfx;
this.ppfx = config.pStylePrefix || '';
this.listenTo(model, 'change:open', this.updateOpen);
this.listenTo(model, 'change:title', this.updateTitle);
this.listenTo(model, 'change:content', this.updateContent);
this.events[`click .${pfx}btn-close`] = 'hide';
bkd && (this.events[`click .${pfx}backlayer`] = 'hide');
this.delegateEvents();
},
@ -116,10 +118,14 @@ module.exports = Backbone.View.extend({
},
render() {
var obj = this.model.toJSON();
const el = this.$el;
const pfx = this.pfx;
const ppfx = this.ppfx;
const obj = this.model.toJSON();
obj.pfx = this.pfx;
this.$el.html( this.template(obj) );
this.$el.attr('class', this.pfx + 'container');
obj.ppfx = this.ppfx;
el.html(this.template(obj));
el.attr('class', `${pfx}container`);
this.updateOpen();
return this;
},

4
src/navigator/view/ItemView.js

@ -18,7 +18,7 @@ module.exports = Backbone.View.extend({
<i id="<%= prefix %>btn-eye" class="btn fa fa-eye <%= (visible ? '' : 'fa-eye-slash') %>" data-toggle-visible></i>
<% } %>
<div class="<%= prefix %>title-c">
<div class="<%= prefix %>title-c <%= ppfx %>one-bg">
<div class="<%= prefix %>title <%= addClass %>" style="padding-left: <%= 30 + level * 10 %>px" data-toggle-select>
<div class="<%= prefix %>title-inn">
<i id="<%= prefix %>caret" class="fa fa-chevron-right <%= caretCls %>" data-toggle-open></i>
@ -298,7 +298,7 @@ module.exports = Backbone.View.extend({
const el = this.$el;
const level = this.level + 1;
el.html( this.template({
el.html(this.template({
title: model.getName(),
icon: model.getIcon(),
addClass: (count ? '' : pfx+'no-chld'),

65
src/panels/view/ButtonView.js

@ -1,3 +1,4 @@
import { isString, isObject, isFunction } from 'underscore';
const $ = Backbone.$;
module.exports = Backbone.View.extend({
@ -9,14 +10,16 @@ module.exports = Backbone.View.extend({
var cls = this.model.get('className');
this.config = o.config || {};
this.em = this.config.em || {};
this.pfx = this.config.stylePrefix || '';
const pfx = this.config.stylePrefix || '';
const ppfx = this.config.pStylePrefix || '';
this.pfx = pfx;
this.ppfx = this.config.pStylePrefix || '';
this.id = this.pfx + this.model.get('id');
this.activeCls = this.pfx + 'active';
this.disableCls = this.pfx + 'active';
this.btnsVisCls = this.pfx + 'visible';
this.id = pfx + this.model.get('id');
this.activeCls = `${pfx}active ${ppfx}four-color`;
this.disableCls = pfx + 'active';
this.btnsVisCls = pfx + 'visible';
this.parentM = o.parentM || null;
this.className = this.pfx + 'btn' + (cls ? ' ' + cls : '');
this.className = pfx + 'btn' + (cls ? ' ' + cls : '');
this.listenTo(this.model, 'change:active updateActive', this.updateActive);
this.listenTo(this.model, 'checkActive', this.checkActive);
this.listenTo(this.model, 'change:bntsVis', this.updateBtnsVis);
@ -26,7 +29,7 @@ module.exports = Backbone.View.extend({
if(this.model.get('buttons').length){
this.$el.on('mousedown', this.startTimer);
this.$el.append($('<div>',{class: this.pfx + 'arrow-rd'}));
this.$el.append($('<div>',{class: pfx + 'arrow-rd'}));
}
if(this.em && this.em.get)
@ -197,40 +200,40 @@ module.exports = Backbone.View.extend({
* @return void
* */
updateActive() {
const model = this.model;
const context = model.get('context');
const parent = this.parentM;
var command = null;
var editor = this.em && this.em.get ? this.em.get('Editor') : null;
var commandName = this.model.get('command');
var commandName = model.get('command');
if (this.commands && typeof commandName === 'string') {
if (this.commands && isString(commandName)) {
command = this.commands.get(commandName);
} else if (commandName !== null && typeof commandName === 'object') {
} else if (isFunction(commandName)) {
command = { run: commandName };
} else if (commandName !== null && isObject(commandName)) {
command = commandName;
} else if (typeof commandName === 'function') {
command = {run: commandName};
}
if(this.model.get('active')){
if (model.get('active')) {
model.collection.deactivateAll(context);
model.set('active', true, { silent: true }).trigger('checkActive');
parent && parent.set('active', true, { silent: true }).trigger('checkActive');
this.model.collection.deactivateAll(this.model.get('context'));
this.model.set('active', true, { silent: true }).trigger('checkActive');
if(this.parentM)
this.parentM.set('active', true, { silent: true }).trigger('checkActive');
if(command && command.run){
command.run(editor, this.model, this.model.get('options'));
if (command && command.run) {
command.run(editor, model, model.get('options'));
editor.trigger('run:' + commandName);
}
}else{
this.$el.removeClass(this.activeCls);
this.model.collection.deactivateAll(this.model.get('context'));
if(this.parentM)
this.parentM.set('active', false, { silent: true }).trigger('checkActive');
// Disable button if there is no stop method
!command.stop && model.set('active', false);
} else {
this.$el.removeClass(this.activeCls);
model.collection.deactivateAll(context);
parent && parent.set('active', false, { silent: true }).trigger('checkActive');
if(command && command.stop){
command.stop(editor, this.model, this.model.get('options'));
if (command && command.stop) {
command.stop(editor, model, model.get('options'));
editor.trigger('stop:' + commandName);
}
}
@ -242,7 +245,7 @@ module.exports = Backbone.View.extend({
} else {
this.$el.removeClass(this.disableCls);
}
},
/**
@ -266,7 +269,7 @@ module.exports = Backbone.View.extend({
clicked(e) {
if(this.model.get('bntsVis') )
return;
if(this.model.get('disable') )
return;

18
src/panels/view/PanelView.js

@ -4,8 +4,10 @@ var ButtonsView = require('./ButtonsView');
module.exports = Backbone.View.extend({
initialize(o) {
this.config = o.config || {};
this.pfx = this.config.stylePrefix || '';
const config = o.config || {};
this.config = config;
this.pfx = config.stylePrefix || '';
this.ppfx = config.pStylePrefix || '';
this.buttons = this.model.get('buttons');
this.className = this.pfx + 'panel';
this.id = this.pfx + this.model.get('id');
@ -76,20 +78,20 @@ module.exports = Backbone.View.extend({
},
render() {
this.$el.attr('class', this.className);
if(this.id)
this.$el.attr('id', this.id);
const el = this.$el;
const pfx = this.ppfx;
el.attr('class', `${this.className} ${pfx}one-bg`);
this.id && el.attr('id', this.id);
if (this.buttons.length) {
var buttons = new ButtonsView({
collection: this.buttons,
config: this.config,
});
this.$el.append(buttons.render().el);
el.append(buttons.render().el);
}
this.$el.append(this.model.get('content'));
el.append(this.model.get('content'));
return this;
},

2
src/rich_text_editor/index.js

@ -63,7 +63,7 @@ module.exports = () => {
this.pfx = config.stylePrefix;
actions = config.actions || [];
toolbar = document.createElement('div');
toolbar.className = `${ppfx}rte-toolbar`;
toolbar.className = `${ppfx}rte-toolbar ${ppfx}one-bg`;
globalRte = this.initRte(document.createElement('div'));
//Avoid closing on toolbar clicking

9
src/selector_manager/view/ClassTagView.js

@ -16,7 +16,6 @@ module.exports = Backbone.View.extend({
this.ppfx = this.config.pStylePrefix || '';
this.inputProp = 'readonly';
this.target = this.config.em;
this.className = this.pfx + 'tag';
this.closeId = this.pfx + 'close';
this.chkId = this.pfx + 'checkbox';
this.labelId = this.pfx + 'tag-label';
@ -124,13 +123,15 @@ module.exports = Backbone.View.extend({
render() {
const pfx = this.pfx;
const ppfx = this.ppfx;
this.$el.html( this.template({
label: this.model.get('label'),
pfx: this.pfx,
ppfx: this.ppfx,
pfx,
ppfx,
inputProp: this.inputProp,
}));
this.$el.attr('class', this.className);
this.$el.attr('class', `${pfx}tag ${ppfx}three-bg`);
this.updateStatus();
this.updateInputLabel();
return this;

16
src/storage_manager/index.js

@ -1,24 +1,9 @@
/**
* - [isAutosave](#isautosave)
* - [setAutosave](#setautosave)
* - [getStepsBeforeSave](#getstepsbeforesave)
* - [setStepsBeforeSave](#setstepsbeforesave)
* - [getStorages](#getstorages)
* - [getCurrent](#getcurrent)
* - [setCurrent](#setcurrent)
* - [add](#add)
* - [get](#get)
* - [store](#store)
* - [load](#load)
*
*
* Before using methods you should get first the module from the editor instance, in this way:
*
* ```js
* var storageManager = editor.StorageManager;
* ```
*
* @module StorageManager
*/
module.exports = () => {
var c = {},
@ -47,6 +32,7 @@ module.exports = () => {
* @param {number} [config.stepsBeforeSave=1] If autosave enabled, indicates how many steps/changes are necessary
* before autosave is triggered
* @param {string} [config.type='local'] Default storage type. Available: 'local' | 'remote' | ''(do not store)
* @private
* @example
* ...
* {

1
src/style_manager/view/LayerView.js

@ -156,6 +156,7 @@ module.exports = Backbone.View.extend({
const properties = new PropertiesView({
collection: model.get('properties'),
config: this.config,
target: propsConfig.target,
customValue: propsConfig.customValue,
propTarget: propsConfig.propTarget,
onChange: propsConfig.onChange,

2
src/style_manager/view/PropertyStackView.js

@ -135,6 +135,7 @@ module.exports = PropertyCompositeView.extend({
const fieldEl = this.el.querySelector('[data-layers-wrapper]');
const PropertiesView = require('./PropertiesView');
const propsConfig = {
target: this.target,
propTarget: this.propTarget,
// Things to do when a single sub-property is changed
@ -160,6 +161,7 @@ module.exports = PropertyCompositeView.extend({
// Will use it to propogate changes
new PropertiesView({
target: this.target,
collection: this.model.get('properties'),
stackModel: model,
config: this.config,

2
src/style_manager/view/PropertyView.js

@ -87,7 +87,7 @@ module.exports = Backbone.View.extend({
const pfx = this.pfx;
const ppfx = this.ppfx;
const config = this.config;
const updatedCls = `${ppfx}color-hl`;
const updatedCls = `${ppfx}four-color`;
const computedCls = `${ppfx}color-warn`;
const labelEl = this.$el.children(`.${pfx}label`);
const clearStyle = this.getClearEl().style;

4
src/styles/scss/_gjs_blocks.scss

@ -23,8 +23,6 @@
.#{$app-prefix}block {
@include user-select(none);
@extend .#{$app-prefix}bg-main;
width: 45%;
padding: 1em;
box-sizing: border-box;
@ -52,7 +50,7 @@
}
.#{$app-prefix}block-svg-path {
@extend .#{$app-prefix}color-main;
fill: currentColor;
}
.#{$app-prefix}block.fa {

6
src/styles/scss/_gjs_inputs.scss

@ -90,14 +90,13 @@
}
.#{$app-prefix}field {
background-color: $mainDkColor;
background-color: rgba(0, 0, 0, 0.2);
border: none;
box-shadow: none;
border-radius: 2px;
box-sizing: border-box;
padding: 0;
position: relative;
color: $inputFontColor;
textarea {
resize: vertical;
@ -320,8 +319,7 @@
}
.#{$app-prefix}btn-prim {
@extend .#{$app-prefix}color-main;
color: inherit;
background-color: $mainLhColor;
border-radius: 2px;
padding: 3px 6px;

4
src/styles/scss/_gjs_layers.scss

@ -62,10 +62,6 @@
}
}
.#{$nv-prefix}item .#{$nv-prefix}title-c {
@extend .#{$app-prefix}bg-main;
}
.#{$nv-prefix}title {
@extend .#{$app-prefix}category-title;

3
src/styles/scss/_gjs_rte.scss

@ -1,6 +1,5 @@
.#{$rte-prefix} {
&toolbar {
@extend .#{$app-prefix}bg-main;
@extend .#{$app-prefix}no-user-select;
border: 1px solid $mainDkColor;
@ -14,8 +13,6 @@
}
&action {
@extend .#{$app-prefix}color-main;
display: flex;
align-items: center;
justify-content: center;

2
src/styles/scss/_gjs_style_manager.scss

@ -167,8 +167,6 @@
}
&.#{$sm-prefix}composite {
@extend .#{$app-prefix}color-main;
border-radius: 2px;
}

12
src/styles/scss/_gjs_variables.scss

@ -14,9 +14,15 @@ $cv-prefix: $app-prefix + 'cv-' !default;
$clm-prefix: $app-prefix + 'clm-' !default;
$trt-prefix: $app-prefix + 'trt-' !default;
/* Colors / Theme */
/*
New Pattern Color System
With this should be easier to overwrite colors
not only in SCSS but even CSS
*/
$primaryColor: #444 !default;
$secondaryColor: #ddd !default;
$tertiaryColor: #804f7b !default;
$quaternaryColor: #d278c9 !default;
/* Dark theme */
$mainColor: #444 !default; /* Light: #573454 Dark: #3b2639 -moz-linear-gradient(top, #fca99b 0%, #6e2842 100%) */

53
src/styles/scss/main.scss

@ -48,6 +48,26 @@
transform: $v;
}
$prefix: $app-prefix;
.#{$prefix} {
@each $cnum, $ccol in (one, $primaryColor), (two, $secondaryColor), (three, $tertiaryColor), (four, $quaternaryColor) {
&#{$cnum} {
&-bg {
background-color: $ccol;
}
&-color {
color: $ccol;
&-h:hover {
color: $ccol;
}
}
}
}
}
.#{$app-prefix}bg {
&-main {
@ -193,9 +213,9 @@
@include user-select(none);
}
.#{$app-prefix}editor{
.#{$app-prefix}editor {
font-family: $mainFont;
background-color: $mainColor;
//background-color: $mainColor;
position:relative;
box-sizing: border-box;
height: 100%;
@ -219,7 +239,6 @@
display: flex;
justify-content: start;
padding: 5px 10px;
font-size: 0.75em;
font-weight: lighter;
.#{$app-prefix}label {
@ -313,8 +332,8 @@
/********* PANELS **********/
.#{$pn-prefix}panel {
@extend .#{$app-prefix}bg-main;
@extend .#{$app-prefix}color-main;
//@extend .#{$app-prefix}bg-main;
//@extend .#{$app-prefix}color-main;
display: inline-block;
padding: 5px;
position: absolute;
@ -362,14 +381,13 @@
}
}
.#{$pn-prefix}buttons{
.#{$pn-prefix}buttons {
align-items: center;
display: flex;
justify-content: center;
justify-content: space-between;
}
.#{$pn-prefix}btn, .#{$app-prefix}btnt{
@extend .#{$app-prefix}color-main;
.#{$pn-prefix}btn, .#{$app-prefix}btnt {
box-sizing: border-box;
height: 30px; width: 30px;
line-height: 21px;
@ -382,8 +400,7 @@
padding: 5px;
position: relative;
&.#{$pn-prefix}active{
@extend .#{$app-prefix}color-active;
&.#{$pn-prefix}active {
background-color: rgba(0, 0, 0, 0.15);
box-shadow: 0 0 3px rgba(0, 0, 0, 0.25) inset;
}
@ -559,14 +576,10 @@
}
.#{$clm-prefix}tag {
background-color: $tagBg;
border: 1px solid darken($tagBg, 12%);
box-shadow: 1px 1px lighten($tagBg, 9%) inset;
text-shadow: 1px 1px darken($tagBg, 7%);
display: inline-block;
border-radius:3px;
margin: 0 3px 3px 0;
padding: 4px;
padding: 5px;
cursor: default;
}
##{$clm-prefix}close {
@ -619,8 +632,6 @@
}
.#{$mdl-prefix}dialog {
@extend .#{$app-prefix}bg-main;
@extend .#{$app-prefix}color-main;
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.05);
animation: #{$app-prefix}slide-down 0.215s;
margin: 30px auto 0;
@ -646,14 +657,13 @@
padding:10px 15px;
clear: both;
}
.#{$mdl-prefix}header{
position: relative;
border-bottom: 1px solid $mainDkColor;
padding: 15px 15px 7px;
}
.#{$mdl-prefix}content{
border-top: 1px solid $mainLhColor;
}
.#{$app-prefix}export-dl::after{
content: "";
clear: both;
@ -749,7 +759,6 @@
.sp-hue{ left: 90%; }
.sp-color{right: 15%;}
.sp-container {
@extend .#{$app-prefix}bg-main;
border: 1px solid $mainDkColor;
box-shadow: 0 0 7px $mainDkColor;
border-radius: 3px;

27
src/utils/Sorter.js

@ -115,23 +115,24 @@ module.exports = Backbone.View.extend({
* @param {Event} event
*/
setDragHelper(el, event) {
var ev = event || '';
var clonedEl = el.cloneNode(1);
const ev = event || '';
const clonedEl = el.cloneNode(1);
const rect = el.getBoundingClientRect();
const computed = getComputedStyle(el);
let style = '';
// Attach style
var style = '';
var o = getComputedStyle(el);
for(var i = 0; i < o.length; i++) {
style += o[i] + ':' + o.getPropertyValue(o[i])+';';
for (var i = 0; i < computed.length; i++) {
const prop = computed[i];
style += `${prop}:${computed.getPropertyValue(prop)};`;
}
clonedEl.setAttribute('style', style);
clonedEl.className += ' ' + this.pfx + 'bdrag';
document.body.appendChild(clonedEl);
clonedEl.className += ` ${this.pfx}bdrag`;
clonedEl.setAttribute('style', style);
this.dragHelper = clonedEl;
if(ev) {
this.moveDragHelper(ev);
}
clonedEl.style.width = `${rect.width}px`;
clonedEl.style.height = `${rect.height}px`;
ev && this.moveDragHelper(ev);
// Listen mouse move events
if(this.em) {

2
test/specs/asset_manager/view/AssetImageView.js

@ -66,7 +66,7 @@ module.exports = {
it('Could be removed', function() {
var spy = sinon.spy();
obj.model.on("remove", spy);
obj.onRemove({stopPropagation() {}});
obj.onRemove({stopImmediatePropagation() {}});
expect(spy.called).toEqual(true);
});

10
test/specs/dom_components/model/Component.js

@ -82,6 +82,16 @@ module.exports = {
expect(obj.toHTML()).toEqual('<article data-test1="value1" data-test2="value2"></article>');
});
it('Component toHTML with value-less attribute', () => {
obj = new Component({
tagName: 'div',
attributes: {
'data-is-a-test': ''
}
});
expect(obj.toHTML()).toEqual('<div data-is-a-test=""></div>');
});
it('Component toHTML with classes', () => {
obj = new Component({
tagName: 'article'

4
test/specs/panels/view/ButtonView.js

@ -44,7 +44,7 @@ module.exports = {
it('Check enable active', () => {
model.set('active', true, {silent: true});
view.checkActive();
expect(view.el.getAttribute('class')).toEqual(btnClass + ' active');
expect(view.el.getAttribute('class')).toContain(btnClass + ' active');
});
it('Check disable active', () => {
@ -60,7 +60,7 @@ module.exports = {
view.updateDisable();
expect(view.el.getAttribute('class')).toEqual(btnClass + ' active');
});
it('Enable the disabled button', () => {
model.set('disable', true, {silent: true});
view.updateDisable();

3
test/specs/panels/view/PanelView.js

@ -25,7 +25,8 @@ module.exports = {
});
it('Panel empty', () => {
expect(fixtures.innerHTML).toEqual('<div class="panel"></div>');
fixtures.firstChild.className = "";
expect(fixtures.innerHTML).toEqual('<div class=""></div>');
});
it('Append content', () => {

87
webpack.config.js

@ -1,38 +1,43 @@
var HtmlWebpackPlugin = require('html-webpack-plugin');
var pkg = require('./package.json');
var webpack = require('webpack');
var fs = require('fs');
var plugins = [];
const HtmlWebpackPlugin = require('html-webpack-plugin');
const pkg = require('./package.json');
const webpack = require('webpack');
const fs = require('fs');
let plugins = [];
if (process.env.WEBPACK_ENV !== 'dev') {
plugins = [
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.optimize.UglifyJsPlugin({ minimize:true, compressor: {warnings:false}}),
new webpack.BannerPlugin(pkg.name + ' - ' + pkg.version),
]
} else {
var index = 'index.html';
var indexDev = '_' + index;
plugins.push(new HtmlWebpackPlugin({
template: fs.existsSync(indexDev) ? indexDev : index
}));
}
module.exports = env => {
const output = {
filename: './dist/grapes.min.js',
library: 'grapesjs',
libraryTarget: 'umd',
};
plugins.push(new webpack.ProvidePlugin({
_: 'underscore',
Backbone: 'backbone'
}));
if (env == 'prod') {
plugins = [
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.optimize.UglifyJsPlugin({ minimize:true, compressor: {warnings:false}}),
new webpack.BannerPlugin(`${pkg.name} - ${pkg.version}`),
];
} else if (env == 'dev') {
output.filename = './dist/grapes.js';
} else {
const index = 'index.html';
const indexDev = `_${index}`;
const template = fs.existsSync(indexDev) ? indexDev : index;
plugins.push(new HtmlWebpackPlugin({ template }));
}
plugins.push(new webpack.ProvidePlugin({
_: 'underscore',
Backbone: 'backbone'
}));
module.exports = {
entry: './src',
output: {
filename: './dist/grapes.min.js',
library: 'grapesjs',
libraryTarget: 'umd',
},
plugins: plugins,
module: {
loaders: [{
return {
entry: './src',
output: output,
plugins: plugins,
module: {
loaders: [{
test: /grapesjs\/index\.js$/,
loader: 'string-replace-loader',
query: {
@ -42,14 +47,14 @@ module.exports = {
},{
test: /\.js$/,
loader: 'babel-loader',
include: /src/,
exclude: /node_modules/
}],
},
resolve: {
modules: ['src', 'node_modules'],
alias: {
jquery: 'cash-dom'
include: /src/
}],
},
resolve: {
modules: ['src', 'node_modules'],
alias: {
jquery: 'cash-dom'
}
}
},
};
}

Loading…
Cancel
Save