Browse Source

Merge branch 'dev' of github.com:artf/grapesjs into update-am-docs

pull/1773/head
David Polak 8 years ago
parent
commit
89dc2f5414
  1. 715
      dist/grapes.js
  2. 8
      dist/grapes.min.js
  3. 2
      dist/grapes.min.js.map
  4. 3
      docs/modules/Style-manager.md
  5. 4
      index.html
  6. 2
      package-lock.json
  7. 2
      package.json
  8. 12
      src/asset_manager/config/config.js
  9. 21
      src/asset_manager/view/FileUploader.js
  10. 2
      src/code_manager/model/JsGenerator.js
  11. 10
      src/commands/view/SelectComponent.js
  12. 16
      src/editor/config/config.js
  13. 4
      src/editor/view/EditorView.js
  14. 2
      src/storage_manager/config/config.js
  15. 14
      src/style_manager/model/Property.js
  16. 116
      src/style_manager/model/PropertyFactory.js
  17. 11
      src/style_manager/model/Sector.js
  18. 42
      src/style_manager/view/PropertyView.js
  19. 10
      src/style_manager/view/SectorView.js
  20. 14
      src/style_manager/view/SectorsView.js
  21. 5
      src/utils/mixins.js
  22. 123
      test/specs/style_manager/model/Models.js

715
dist/grapes.js

File diff suppressed because it is too large

8
dist/grapes.min.js

File diff suppressed because one or more lines are too long

2
dist/grapes.min.js.map

File diff suppressed because one or more lines are too long

3
docs/modules/Style-manager.md

@ -13,8 +13,7 @@ Coming soon
Here you can find all the available built-in properties that you can use inside Style Manager via `buildProps`:
`float`, `position`, `text-align`, `display`, `font-family`, `font-weight`, `border`, `border-style`, `border-color`, `border-width`, `box-shadow`, `background-repeat`, `background-position`, `background-attachment`, `background-size`, `transition`, `transition-duration`, `transition-property`, `transition-timing-function`, `top`, `right`, `bottom`, `left`, `margin`, `margin-top`, `margin-right`, `margin-bottom`, `margin-left`, `padding`, `padding-top`, `padding-right`, `padding-bottom`, `padding-left`, `width`, `heigth`, `min-width`, `min-heigth`, `max-width`, `max-heigth`, `font-size`, `letter-spacing`, `line-height`, `text-shadow`, `border-radius`, `border-top-left-radius`, `border-top-right-radius`, `border-bottom-left-radius`, `border-bottom-right-radius`, `perspective`, `transform`, `transform-rotate-x`, `transform-rotate-y`, `transform-rotate-z`, `transform-scale-x`, `transform-scale-y`, `transform-scale-z`, `color`, `background-color`, `background`, `background-image`, `cursor`
`overflow`, `overflow-x`, `overflow-y`
`float`, `position`, `text-align`, `display`, `font-family`, `font-weight`, `border`, `border-style`, `border-color`, `border-width`, `box-shadow`, `background-repeat`, `background-position`, `background-attachment`, `background-size`, `transition`, `transition-duration`, `transition-property`, `transition-timing-function`, `top`, `right`, `bottom`, `left`, `margin`, `margin-top`, `margin-right`, `margin-bottom`, `margin-left`, `padding`, `padding-top`, `padding-right`, `padding-bottom`, `padding-left`, `width`, `height`, `min-width`, `min-height`, `max-width`, `max-height`, `font-size`, `letter-spacing`, `line-height`, `text-shadow`, `border-radius`, `border-top-left-radius`, `border-top-right-radius`, `border-bottom-left-radius`, `border-bottom-right-radius`, `perspective`, `transform`, `transform-rotate-x`, `transform-rotate-y`, `transform-rotate-z`, `transform-scale-x`, `transform-scale-y`, `transform-scale-z`, `color`, `background-color`, `background`, `background-image`, `cursor`, `flex-direction`, `flex-wrap`, `justify-content`, `align-items`, `align-content`, `order`, `flex-basis`, `flex-grow`, `flex-shrink`, `align-self`, `overflow`, `overflow-x`, `overflow-y`
Example usage:
```js

4
index.html

@ -91,6 +91,10 @@
name: 'General',
open: false,
buildProps: ['float', 'display', 'position', 'top', 'right', 'left', 'bottom']
},{
name: 'Flex',
open: false,
buildProps: ['flex-direction', 'flex-wrap', 'justify-content', 'align-items', 'align-content', 'order', 'flex-basis', 'flex-grow', 'flex-shrink', 'align-self']
},{
name: 'Dimension',
open: false,

2
package-lock.json

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

2
package.json

@ -1,7 +1,7 @@
{
"name": "grapesjs",
"description": "Free and Open Source Web Builder Framework",
"version": "0.14.50",
"version": "0.14.52",
"author": "Artur Arseniev",
"license": "BSD-3-Clause",
"homepage": "http://grapesjs.com",

12
src/asset_manager/config/config.js

@ -55,7 +55,17 @@ module.exports = {
// Label for the add button
addBtnText: 'Add image',
// Custom uploadFile function
// To upload your assets, the module uses Fetch API, with this option you
// overwrite it with something else.
// It should return a Promise
// @example
// customFetch: (url, options) => axios(url, { data: options.body }),
customFetch: '',
// Custom uploadFile function.
// Differently from the `customFetch` option, this gives a total control
// over the uploading process, but you also have to emit all `asset:upload:*` events
// by yourself (if you need to use them somewhere)
// @example
// uploadFile: (e) => {
// var files = e.dataTransfer ? e.dataTransfer.files : e.target.files;

21
src/asset_manager/view/FileUploader.js

@ -104,9 +104,9 @@ module.exports = Backbone.View.extend(
* */
uploadFile(e, clb) {
const files = e.dataTransfer ? e.dataTransfer.files : e.target.files;
const { config } = this;
const body = new FormData();
const config = this.config;
const params = config.params;
const { params, customFetch } = config;
for (let param in params) {
body.append(param, params[param]);
@ -131,17 +131,20 @@ module.exports = Backbone.View.extend(
if (url) {
this.onUploadStart();
return fetch(url, {
const fetchOpts = {
method: 'post',
credentials: config.credentials || 'include',
headers,
body
})
.then(res =>
((res.status / 200) | 0) == 1
? res.text()
: res.text().then(text => Promise.reject(text))
)
};
const fetchResult = customFetch
? customFetch(url, fetchOpts)
: fetch(url, fetchOpts).then(res =>
((res.status / 200) | 0) == 1
? res.text()
: res.text().then(text => Promise.reject(text))
);
return fetchResult
.then(text => this.onUploadResponse(text, clb))
.catch(err => this.onUploadError(err));
}

2
src/code_manager/model/JsGenerator.js

@ -13,7 +13,7 @@ module.exports = Backbone.Model.extend({
// If the component has scripts we need to expose his ID
var attr = model.get('attributes');
attr = extend({}, attr, { id });
model.set('attributes', attr);
model.set('attributes', attr, { silent: 1 });
var scrStr = model.getScriptString();
// If the script was updated, I'll put its code in a separate container

10
src/commands/view/SelectComponent.js

@ -350,7 +350,7 @@ module.exports = {
* @private
*/
initResize(elem) {
const em = this.em;
const { em, canvas } = this;
const editor = em ? em.get('Editor') : '';
const config = em ? em.get('Config') : '';
const pfx = config.stylePrefix || '';
@ -444,7 +444,13 @@ module.exports = {
const style = modelToStyle.getStyle();
if (!onlyHeight) {
style[keyWidth] = autoWidth ? 'auto' : `${rect.w}${unitWidth}`;
const padding = 10;
const frameOffset = canvas.getCanvasView().getFrameOffset();
const width =
rect.w < frameOffset.width - padding
? rect.w
: frameOffset.width - padding;
style[keyWidth] = autoWidth ? 'auto' : `${width}${unitWidth}`;
}
if (!onlyWidth) {

16
src/editor/config/config.js

@ -223,6 +223,22 @@ module.exports = {
'bottom'
]
},
{
name: 'Flex',
open: false,
buildProps: [
'flex-direction',
'flex-wrap',
'justify-content',
'align-items',
'align-content',
'order',
'flex-basis',
'flex-grow',
'flex-shrink',
'align-self'
]
},
{
name: 'Dimension',
open: false,

4
src/editor/view/EditorView.js

@ -2,7 +2,7 @@ const $ = Backbone.$;
module.exports = Backbone.View.extend({
initialize() {
const model = this.model;
const { model } = this;
model.view = this;
this.conf = model.config;
this.pn = model.get('Panels');
@ -10,7 +10,7 @@ module.exports = Backbone.View.extend({
this.pn.active();
this.pn.disableButtons();
model.runDefault();
setTimeout(() => model.trigger('load'), 0);
setTimeout(() => model.trigger('load', model.get('Editor')));
});
},

2
src/storage_manager/config/config.js

@ -53,7 +53,7 @@ module.exports = {
// set contentType paramater of $.ajax
// true: application/json; charset=utf-8'
// false: 'x-www-form-urlencoded'
contentTypeJson: false,
contentTypeJson: true,
credentials: 'include'
};

14
src/style_manager/model/Property.js

@ -26,7 +26,19 @@ const Property = require('backbone').Model.extend(
// Use case:
// you can add all SVG CSS properties with toRequire as true
// and then require them on SVG Components
toRequire: 0
toRequire: 0,
// Specifies dependency on other properties of the selected object.
// Property is shown only when all conditions are matched.
//
// example: { display: ['flex', 'block'], position: ['absolute'] };
// in this case the property is only shown when display is
// of value 'flex' or 'block' AND position is 'absolute'
requires: null,
// Specifies dependency on properties of the parent of the selected object.
// Property is shown only when all conditions are matched.
requiresParent: null
},
initialize(props = {}, opts = {}) {

116
src/style_manager/model/PropertyFactory.js

@ -40,6 +40,7 @@ module.exports = () => ({
case 'height':
case 'max-height':
case 'min-height':
case 'flex-basis':
obj.fixedValues = ['initial', 'inherit', 'auto'];
break;
case 'font-size':
@ -72,6 +73,12 @@ module.exports = () => ({
obj.type = 'radio';
break;
case 'display':
case 'flex-direction':
case 'flex-wrap':
case 'justify-content':
case 'align-items':
case 'align-content':
case 'align-self':
case 'font-family':
case 'font-weight':
case 'border-style':
@ -130,6 +137,10 @@ module.exports = () => ({
case 'transform-scale-x':
case 'transform-scale-y':
case 'transform-scale-z':
case 'order':
case 'flex-grow':
case 'flex-shrink':
case 'flex-basis':
obj.type = 'integer';
break;
case 'margin':
@ -168,6 +179,24 @@ module.exports = () => ({
case 'display':
obj.defaults = 'block';
break;
case 'flex-direction':
obj.defaults = 'row';
break;
case 'flex-wrap':
obj.defaults = 'nowrap';
break;
case 'justify-content':
obj.defaults = 'flex-start';
break;
case 'align-items':
obj.defaults = 'stretch';
break;
case 'align-content':
obj.defaults = 'stretch';
break;
case 'align-self':
obj.defaults = 'auto';
break;
case 'position':
obj.defaults = 'static';
break;
@ -194,6 +223,8 @@ module.exports = () => ({
case 'transform-rotate-x':
case 'transform-rotate-y':
case 'transform-rotate-z':
case 'order':
case 'flex-grow':
obj.defaults = 0;
break;
case 'border-top-left-radius':
@ -205,6 +236,7 @@ module.exports = () => ({
case 'transform-scale-x':
case 'transform-scale-y':
case 'transform-scale-z':
case 'flex-shrink':
obj.defaults = 1;
break;
case 'box-shadow-blur':
@ -218,6 +250,7 @@ module.exports = () => ({
case 'height':
case 'background-size':
case 'cursor':
case 'flex-basis':
obj.defaults = 'auto';
break;
case 'font-family':
@ -274,6 +307,30 @@ module.exports = () => ({
break;
}
/*
* Add styleable dependency on other properties. Allows properties to be
* dynamically hidden or shown based on values of other properties.
*
* Property will be styleable if all of the properties (keys) in the
* requires object have any of the values specified in the array.
*/
switch (prop) {
case 'flex-direction':
case 'flex-wrap':
case 'justify-content':
case 'align-items':
case 'align-content':
obj.requires = { display: ['flex'] };
break;
case 'order':
case 'flex-basis':
case 'flex-grow':
case 'flex-shrink':
case 'align-self':
obj.requiresParent = { display: ['flex'] };
break;
}
// Units
switch (prop) {
case 'top':
@ -298,6 +355,9 @@ module.exports = () => ({
case 'width':
obj.units = ['px', '%', 'vw'];
break;
case 'flex-basis':
obj.units = ['px', '%', 'vw', 'vh'];
break;
case 'text-shadow-v':
case 'text-shadow-h':
case 'text-shadow-blur':
@ -356,6 +416,7 @@ module.exports = () => ({
case 'box-shadow-blur':
case 'transition-duration':
case 'perspective':
case 'flex-basis':
obj.min = 0;
break;
}
@ -411,9 +472,64 @@ module.exports = () => ({
{ value: 'block' },
{ value: 'inline' },
{ value: 'inline-block' },
{ value: 'flex' },
{ value: 'none' }
];
break;
case 'flex-direction':
obj.list = [
{ value: 'row' },
{ value: 'row-reverse' },
{ value: 'column' },
{ value: 'column-reverse' }
];
break;
case 'flex-wrap':
obj.list = [
{ value: 'nowrap' },
{ value: 'wrap' },
{ value: 'wrap-reverse' }
];
break;
case 'justify-content':
obj.list = [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'space-between' },
{ value: 'space-around' },
{ value: 'space-evenly' }
];
break;
case 'align-items':
obj.list = [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'baseline' },
{ value: 'stretch' }
];
break;
case 'align-content':
obj.list = [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'space-between' },
{ value: 'space-around' },
{ value: 'stretch' }
];
break;
case 'align-self':
obj.list = [
{ value: 'auto' },
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'baseline' },
{ value: 'stretch' }
];
break;
case 'position':
obj.list = [
{ value: 'static' },

11
src/style_manager/model/Sector.js

@ -15,15 +15,16 @@ module.exports = Backbone.Model.extend({
},
initialize(opts) {
var o = opts || {};
var props = [];
var builded = this.buildProperties(o.buildProps);
!this.get('id') && this.set('id', this.get('name'));
const o = opts || {};
const builded = this.buildProperties(o.buildProps);
const name = this.get('name') || '';
let props = [];
!this.get('id') && this.set('id', name.replace(/ /g, '_').toLowerCase());
if (!builded) props = this.get('properties');
else props = this.extendProperties(builded);
var propsModel = new Properties(props);
const propsModel = new Properties(props);
propsModel.sector = this;
this.set('properties', propsModel);
},

42
src/style_manager/view/PropertyView.js

@ -1,6 +1,7 @@
import Backbone from 'backbone';
import { bindAll, isArray, isUndefined, debounce } from 'underscore';
import { camelCase } from 'utils/mixins';
import { includes, each } from 'underscore';
const clearProp = 'data-clear-style';
@ -70,6 +71,15 @@ module.exports = Backbone.View.extend({
em && em.on(`update:component:style:${this.property}`, this.targetUpdated);
//em && em.on(`styleable:change:${this.property}`, this.targetUpdated);
// Listening to changes of properties in this.requires, so that styleable
// changes based on other properties are propagated
const requires = model.get('requires');
requires &&
Object.keys(requires).forEach(property => {
em && em.on(`component:styleUpdate:${property}`, this.targetUpdated);
});
this.listenTo(
this.propTarget,
'update styleManager:update',
@ -406,6 +416,10 @@ module.exports = Backbone.View.extend({
const toRequire = model.get('toRequire');
const unstylable = trg.get('unstylable');
const stylableReq = trg.get('stylable-require');
const requires = model.get('requires');
const requiresParent = model.get('requiresParent');
const sectors = this.sector ? this.sector.collection : null;
const selected = this.em ? this.em.getSelected() : null;
let stylable = trg.get('stylable');
// Stylable could also be an array indicating with which property
@ -427,6 +441,34 @@ module.exports = Backbone.View.extend({
(stylableReq.indexOf(id) >= 0 || stylableReq.indexOf(property) >= 0));
}
// Check if the property is available based on other property's values
if (sectors && requires) {
const properties = Object.keys(requires);
sectors.each(sector => {
sector.get('properties').each(model => {
if (includes(properties, model.id)) {
const values = requires[model.id];
stylable = stylable && includes(values, model.get('value'));
}
});
});
}
// Check if the property is available based on parent's property values
if (requiresParent) {
const parent = selected && selected.parent();
const parentEl = parent && parent.getEl();
if (parentEl) {
const styles = window.getComputedStyle(parentEl);
each(requiresParent, (values, property) => {
stylable =
stylable && styles[property] && includes(values, styles[property]);
});
} else {
stylable = false;
}
}
return stylable;
},

10
src/style_manager/view/SectorView.js

@ -78,15 +78,17 @@ module.exports = Backbone.View.extend({
},
render() {
const { pfx, model } = this;
const { id } = model.attributes;
this.$el.html(
this.template({
pfx: this.pfx,
label: this.model.get('name')
pfx,
label: model.get('name')
})
);
this.$caret = this.$el.find('#' + this.pfx + 'caret');
this.$caret = this.$el.find(`#${pfx}caret`);
this.renderProperties();
this.$el.attr('class', this.pfx + 'sector no-select');
this.$el.attr('class', `${pfx}sector ${pfx}sector__${id} no-select`);
this.updateOpen();
return this;
},

14
src/style_manager/view/SectorsView.js

@ -134,20 +134,16 @@ module.exports = Backbone.View.extend({
* @private
* */
addToCollection(model, fragmentEl) {
const { pfx, target, propTarget, config } = this;
var fragment = fragmentEl || null;
var view = new SectorView({
model,
id:
this.pfx +
model
.get('name')
.replace(' ', '_')
.toLowerCase(),
id: `${pfx}${model.get('id')}`,
name: model.get('name'),
properties: model.get('properties'),
target: this.target,
propTarget: this.propTarget,
config: this.config
target,
propTarget,
config
});
var rendered = view.render().el;

5
src/utils/mixins.js

@ -126,7 +126,8 @@ const getModel = (el, $) => {
* @param {Event} ev
* @return {Event}
*/
const getPointerEvent = (ev) => ev.touches && ev.touches[0] ? ev.touches[0] : ev;
const getPointerEvent = ev =>
ev.touches && ev.touches[0] ? ev.touches[0] : ev;
export {
on,
@ -140,5 +141,5 @@ export {
shallowDiff,
normalizeFloat,
getPointerEvent,
getUnitFromValue,
getUnitFromValue
};

123
test/specs/style_manager/model/Models.js

@ -60,6 +60,7 @@ module.exports = {
{ value: 'block' },
{ value: 'inline' },
{ value: 'inline-block' },
{ value: 'flex' },
{ value: 'none' }
]
});
@ -369,12 +370,121 @@ module.exports = {
{ value: 'block' },
{ value: 'inline' },
{ value: 'inline-block' },
{ value: 'flex' },
{ value: 'none' }
]
}
]);
});
test('Build flex-direction', () => {
expect(obj.build('flex-direction')).toEqual([
{
property: 'flex-direction',
type: 'select',
defaults: 'row',
list: [
{ value: 'row' },
{ value: 'row-reverse' },
{ value: 'column' },
{ value: 'column-reverse' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build flex-wrap', () => {
expect(obj.build('flex-wrap')).toEqual([
{
property: 'flex-wrap',
type: 'select',
defaults: 'nowrap',
list: [
{ value: 'nowrap' },
{ value: 'wrap' },
{ value: 'wrap-reverse' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build justify-content', () => {
expect(obj.build('justify-content')).toEqual([
{
property: 'justify-content',
type: 'select',
defaults: 'flex-start',
list: [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'space-between' },
{ value: 'space-around' },
{ value: 'space-evenly' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build align-items', () => {
expect(obj.build('align-items')).toEqual([
{
property: 'align-items',
type: 'select',
defaults: 'stretch',
list: [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'baseline' },
{ value: 'stretch' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build align-content', () => {
expect(obj.build('align-content')).toEqual([
{
property: 'align-content',
type: 'select',
defaults: 'stretch',
list: [
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'space-between' },
{ value: 'space-around' },
{ value: 'stretch' }
],
requires: { display: ['flex'] }
}
]);
});
test('Build align-self', () => {
expect(obj.build('align-self')).toEqual([
{
property: 'align-self',
type: 'select',
defaults: 'auto',
list: [
{ value: 'auto' },
{ value: 'flex-start' },
{ value: 'flex-end' },
{ value: 'center' },
{ value: 'baseline' },
{ value: 'stretch' }
],
requiresParent: { display: ['flex'] }
}
]);
});
test('Build position', () => {
expect(obj.build('position')).toEqual([
{
@ -431,6 +541,19 @@ module.exports = {
expect(obj.build('max-width')).toEqual([res]);
});
test('Build flex-basis', () => {
var res = {
type: 'integer',
units: ['px', '%', 'vw', 'vh'],
defaults: 'auto',
fixedValues: ['initial', 'inherit', 'auto'],
requiresParent: { display: ['flex'] },
min: 0
};
res.property = 'flex-basis';
expect(obj.build('flex-basis')).toEqual([res]);
});
test('Build height family', () => {
var res = {
type: 'integer',

Loading…
Cancel
Save