Browse Source

Merge pull request #856 from artf/dev

Merge dev branch
pull/883/head
Artur Arseniev 9 years ago
committed by GitHub
parent
commit
01254dc218
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      README.md
  2. 2
      dist/css/grapes.min.css
  3. 2385
      dist/grapes.js
  4. 6
      dist/grapes.min.js
  5. 2573
      package-lock.json
  6. 26
      package.json
  7. 4
      src/asset_manager/view/AssetsView.js
  8. 4
      src/block_manager/config/config.js
  9. 13
      src/block_manager/index.js
  10. 4
      src/block_manager/view/BlocksView.js
  11. 24
      src/canvas/view/CanvasView.js
  12. 2
      src/commands/index.js
  13. 40
      src/commands/view/OpenLayers.js
  14. 2
      src/commands/view/SelectComponent.js
  15. 2
      src/commands/view/SelectPosition.js
  16. 3
      src/dom_components/index.js
  17. 8
      src/dom_components/view/ComponentView.js
  18. 9
      src/domain_abstract/model/Styleable.js
  19. 12
      src/domain_abstract/ui/InputNumber.js
  20. 5
      src/editor/config/config.js
  21. 6
      src/editor/index.js
  22. 17
      src/editor/model/Editor.js
  23. 6
      src/index.js
  24. 6
      src/modal_dialog/index.js
  25. 2
      src/modal_dialog/view/ModalView.js
  26. 6
      src/navigator/config/config.js
  27. 77
      src/navigator/index.js
  28. 108
      src/navigator/view/ItemView.js
  29. 47
      src/navigator/view/ItemsView.js
  30. 2
      src/panels/view/ButtonsView.js
  31. 41
      src/panels/view/PanelView.js
  32. 32
      src/panels/view/PanelsView.js
  33. 4
      src/selector_manager/config/config.js
  34. 15
      src/selector_manager/index.js
  35. 16
      src/selector_manager/view/ClassTagsView.js
  36. 5
      src/storage_manager/index.js
  37. 4
      src/style_manager/config/config.js
  38. 11
      src/style_manager/index.js
  39. 17
      src/style_manager/model/Property.js
  40. 11
      src/style_manager/model/PropertyComposite.js
  41. 13
      src/style_manager/model/PropertyInteger.js
  42. 3
      src/style_manager/view/PropertiesView.js
  43. 8
      src/style_manager/view/PropertyCompositeView.js
  44. 6
      src/style_manager/view/PropertyIntegerView.js
  45. 10
      src/style_manager/view/PropertySliderView.js
  46. 7
      src/style_manager/view/PropertyStackView.js
  47. 11
      src/style_manager/view/PropertyView.js
  48. 25
      src/style_manager/view/SectorsView.js
  49. 3
      src/styles/scss/_gjs_blocks.scss
  50. 4
      src/styles/scss/_gjs_canvas.scss
  51. 211
      src/styles/scss/_gjs_layers.scss
  52. 71
      src/styles/scss/_gjs_panels.scss
  53. 91
      src/styles/scss/_gjs_selectors.scss
  54. 4
      src/styles/scss/_gjs_style_manager.scss
  55. 29
      src/styles/scss/_gjs_traits.scss
  56. 11
      src/styles/scss/_gjs_variables.scss
  57. 241
      src/styles/scss/main.scss
  58. 4
      src/trait_manager/config/config.js
  59. 20
      src/trait_manager/index.js
  60. 11
      src/trait_manager/view/TraitsView.js
  61. 73
      src/utils/Resizer.js
  62. 17
      src/utils/Sorter.js
  63. 8
      test/specs/style_manager/view/PropertyCompositeView.js

1
README.md

@ -191,6 +191,7 @@ $ npm test
* [grapesjs-style-gradient](https://github.com/artf/grapesjs-style-gradient) - Add a gradient type input * [grapesjs-style-gradient](https://github.com/artf/grapesjs-style-gradient) - Add a gradient type input
* [grapesjs-blocks-flexbox](https://github.com/artf/grapesjs-blocks-flexbox) - Add the flexbox block * [grapesjs-blocks-flexbox](https://github.com/artf/grapesjs-blocks-flexbox) - Add the flexbox block
* [grapesjs-lory-slider](https://github.com/artf/grapesjs-lory-slider) - Slider component by using [lory](https://github.com/meandmax/lory) * [grapesjs-lory-slider](https://github.com/artf/grapesjs-lory-slider) - Slider component by using [lory](https://github.com/meandmax/lory)
* [grapesjs-tabs](https://github.com/artf/grapesjs-tabs) - Simple tabs component
### Presets ### Presets
* [grapesjs-preset-webpage](https://github.com/artf/grapesjs-preset-webpage) - Webpage Builder * [grapesjs-preset-webpage](https://github.com/artf/grapesjs-preset-webpage) - Webpage Builder

2
dist/css/grapes.min.css

File diff suppressed because one or more lines are too long

2385
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

2573
package-lock.json

File diff suppressed because it is too large

26
package.json

@ -1,7 +1,7 @@
{ {
"name": "grapesjs", "name": "grapesjs",
"description": "Free and Open Source Web Builder Framework", "description": "Free and Open Source Web Builder Framework",
"version": "0.13.8", "version": "0.14.5",
"author": "Artur Arseniev", "author": "Artur Arseniev",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"homepage": "http://grapesjs.com", "homepage": "http://grapesjs.com",
@ -13,8 +13,8 @@
"dependencies": { "dependencies": {
"backbone": "^1.3.3", "backbone": "^1.3.3",
"backbone-undo": "^0.2.5", "backbone-undo": "^0.2.5",
"cash-dom": "^1.3.5", "cash-dom": "^1.3.7",
"codemirror": "^5.21.0", "codemirror": "^5.34.0",
"codemirror-formatting": "^1.0.0", "codemirror-formatting": "^1.0.0",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"keymaster": "^1.6.2", "keymaster": "^1.6.2",
@ -27,23 +27,23 @@
"babel-plugin-transform-object-rest-spread": "^6.26.0", "babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.6.1", "babel-preset-env": "^1.6.1",
"chai": "^4.1.2", "chai": "^4.1.2",
"cross-env": "^5.0.5", "cross-env": "^5.1.3",
"documentation": "^5.3.0", "documentation": "^5.3.5",
"eslint": "^4.1.1", "eslint": "^4.17.0",
"expect": "^1.20.2", "expect": "^1.20.2",
"html-webpack-plugin": "^2.30.1", "html-webpack-plugin": "^2.30.1",
"husky": "^0.14.3", "husky": "^0.14.3",
"istanbul": "^0.4.2", "istanbul": "^0.4.2",
"jsdom": "^11.2.0", "jsdom": "^11.6.2",
"lint-staged": "^6.0.0", "lint-staged": "^6.1.0",
"mocha": "^3.1.2", "mocha": "^3.1.2",
"node-sass": "^4.5.3", "node-sass": "^4.7.2",
"prettier": "1.10.1", "prettier": "1.10.2",
"promise-polyfill": "^6.0.2", "promise-polyfill": "^6.1.0",
"sinon": "^3.2.1", "sinon": "^3.2.1",
"string-replace-loader": "^1.3.0", "string-replace-loader": "^1.3.0",
"webpack": "^3.5.5", "webpack": "^3.10.0",
"webpack-dev-server": "^2.7.1", "webpack-dev-server": "^2.11.1",
"whatwg-fetch": "^2.0.3" "whatwg-fetch": "^2.0.3"
}, },
"keywords": [ "keywords": [

4
src/asset_manager/view/AssetsView.js

@ -20,10 +20,6 @@ module.exports = Backbone.View.extend({
<button class="${ppfx}btn-prim">${view.config.addBtnText}</button> <button class="${ppfx}btn-prim">${view.config.addBtnText}</button>
<div style="clear:both"></div> <div style="clear:both"></div>
</form> </form>
<div class="${pfx}dips" style="display:none">
<button class="fa fa-th <%${ppfx}btnt"></button>
<button class="fa fa-th-list <%${ppfx}btnt"></button>
</div>
</div> </div>
<div class="${pfx}assets" data-el="assets"></div> <div class="${pfx}assets" data-el="assets"></div>
<div style="clear:both"></div> <div style="clear:both"></div>

4
src/block_manager/config/config.js

@ -1,4 +1,8 @@
module.exports = { module.exports = {
// Specify the element to use as a container, string (query) or HTMLElement
// With the empty value, nothing will be rendered
appendTo: '',
blocks: [], blocks: [],
appendTo: '' appendTo: ''

13
src/block_manager/index.js

@ -28,6 +28,8 @@
* } * }
* ... * ...
*/ */
import { isElement } from 'underscore';
module.exports = () => { module.exports = () => {
var c = {}, var c = {},
defaults = require('./config/config'), defaults = require('./config/config'),
@ -108,6 +110,15 @@ module.exports = () => {
!blocks.length && blocks.reset(c.blocks); !blocks.length && blocks.reset(c.blocks);
}, },
postRender() {
const elTo = this.getConfig().appendTo;
if (elTo) {
const el = isElement(elTo) ? elTo : document.querySelector(elTo);
el.appendChild(this.render());
}
},
/** /**
* Add new block to the collection. * Add new block to the collection.
* @param {string} id Block id * @param {string} id Block id
@ -199,6 +210,7 @@ module.exports = () => {
* Render blocks * Render blocks
* @param {Array} blocks Blocks to render, without the argument will render * @param {Array} blocks Blocks to render, without the argument will render
* all global blocks * all global blocks
* @return {HTMLElement} Rendered element
* @example * @example
* // Render all blocks (inside the global collection) * // Render all blocks (inside the global collection)
* blockManager.render(); * blockManager.render();
@ -225,6 +237,7 @@ module.exports = () => {
} }
blocksView.collection.reset(toRender); blocksView.collection.reset(toRender);
return this.getContainer();
} }
}; };
}; };

4
src/block_manager/view/BlocksView.js

@ -174,6 +174,7 @@ module.exports = require('backbone').View.extend({
}, },
render() { render() {
const ppfx = this.ppfx;
const frag = document.createDocumentFragment(); const frag = document.createDocumentFragment();
this.catsEl = null; this.catsEl = null;
this.blocksEl = null; this.blocksEl = null;
@ -187,7 +188,8 @@ module.exports = require('backbone').View.extend({
this.collection.each(model => this.add(model, frag)); this.collection.each(model => this.add(model, frag));
this.append(frag); this.append(frag);
this.$el.addClass(this.blockContClass + 's'); const cls = `${this.blockContClass}s ${ppfx}one-bg ${ppfx}two-color`;
this.$el.addClass(cls);
return this; return this;
} }
}); });

24
src/canvas/view/CanvasView.js

@ -128,11 +128,12 @@ module.exports = Backbone.View.extend({
.${ppfx}dashed *[data-highlightable] { .${ppfx}dashed *[data-highlightable] {
outline: 1px dashed rgba(170,170,170,0.7); outline: 1px dashed rgba(170,170,170,0.7);
outline-offset: -3px outline-offset: -2px;
} }
.${ppfx}comp-selected { .${ppfx}comp-selected {
outline: 3px solid #3b97e3 !important; outline: 3px solid #3b97e3 !important;
outline-offset: -3px;
} }
.${ppfx}comp-selected-parent { .${ppfx}comp-selected-parent {
@ -206,8 +207,8 @@ module.exports = Backbone.View.extend({
// the keyCode/which will be always `0`. Even if it's an old/deprecated // the keyCode/which will be always `0`. Even if it's an old/deprecated
// property keymaster (and many others) still use it... using `defineProperty` // property keymaster (and many others) still use it... using `defineProperty`
// hack seems the only way // hack seems the only way
const createCustomEvent = e => { const createCustomEvent = (e, cls) => {
var oEvent = new KeyboardEvent(e.type, e); var oEvent = new window[cls](e.type, e);
oEvent.keyCodeVal = e.keyCode; oEvent.keyCodeVal = e.keyCode;
['keyCode', 'which'].forEach(prop => { ['keyCode', 'which'].forEach(prop => {
Object.defineProperty(oEvent, prop, { Object.defineProperty(oEvent, prop, {
@ -218,12 +219,17 @@ module.exports = Backbone.View.extend({
}); });
return oEvent; return oEvent;
}; };
fdoc.addEventListener('keydown', e => {
doc.dispatchEvent(createCustomEvent(e)); [
}); { event: 'keydown keyup', class: 'KeyboardEvent' }
fdoc.addEventListener('keyup', e => { //{ event: 'mousedown mousemove mouseup', class: 'MouseEvent' },
doc.dispatchEvent(createCustomEvent(e)); ].forEach(obj =>
}); obj.event.split(' ').forEach(event => {
fdoc.addEventListener(event, e =>
doc.dispatchEvent(createCustomEvent(e, obj.class))
);
})
);
} }
}, },

2
src/commands/index.js

@ -204,7 +204,7 @@ module.exports = () => {
cmdMove.initSorterFromModel(sel); cmdMove.initSorterFromModel(sel);
} }
sel.set('status', 'selected'); sel.set('status', 'freezed-selected');
} }
}; };

40
src/commands/view/OpenLayers.js

@ -2,36 +2,24 @@ const Layers = require('navigator');
const $ = Backbone.$; const $ = Backbone.$;
module.exports = { module.exports = {
run(em, sender) { run(editor) {
if (!this.toAppend) { const lm = editor.LayerManager;
var collection = em.DomComponents.getComponent().get('components'); const pn = editor.Panels;
var config = em.getConfig();
var pfx = config.stylePrefix;
var panels = em.Panels;
var lyStylePfx = config.layers.stylePrefix || 'nv-';
config.layers.stylePrefix = config.stylePrefix + lyStylePfx; if (!this.layers) {
config.layers.pStylePrefix = config.stylePrefix; const id = 'views-container';
config.layers.em = em.editor; const layers = document.createElement('div');
config.layers.opened = em.editor.get('opened'); const panels = pn.getPanel(id) || pn.addPanel({ id });
layers.appendChild(lm.render());
// Check if panel exists otherwise crate it panels.set('appendContent', layers).trigger('change:appendContent');
if (!panels.getPanel('views-container')) this.layers = layers;
this.panel = panels.addPanel({ id: 'views-container' });
else this.panel = panels.getPanel('views-container');
const toAppend = $(`<div class="${pfx}layers"></div>`);
this.panel.set('appendContent', toAppend).trigger('change:appendContent');
config.layers.sortContainer = toAppend.get(0);
const layers = new Layers().init(collection, config.layers);
this.$layers = layers.render();
toAppend.append(this.$layers);
this.toAppend = toAppend;
} }
this.toAppend.show();
this.layers.style.display = 'block';
}, },
stop() { stop() {
this.toAppend && this.toAppend.hide(); const layers = this.layers;
layers && (layers.style.display = 'none');
} }
}; };

2
src/commands/view/SelectComponent.js

@ -52,7 +52,7 @@ module.exports = {
methods[method](body, 'mouseover', this.onHover); methods[method](body, 'mouseover', this.onHover);
methods[method](body, 'mouseout', this.onOut); methods[method](body, 'mouseout', this.onOut);
methods[method](body, 'click', this.onClick); methods[method](body, 'click', this.onClick);
methods[method](win, 'scroll', this.onFrameScroll); methods[method](win, 'scroll resize', this.onFrameScroll);
methods[method](win, 'keydown', this.onKeyPress); methods[method](win, 'keydown', this.onKeyPress);
em[method]('change:selectedComponent', this.onSelect, this); em[method]('change:selectedComponent', this.onSelect, this);
}, },

2
src/commands/view/SelectPosition.js

@ -23,7 +23,7 @@ module.exports = {
em: this.editorModel, em: this.editorModel,
canvasRelative: 1 canvasRelative: 1
}); });
this.sorter.startSort(trg); trg && this.sorter.startSort(trg);
}, },
/** /**

3
src/dom_components/index.js

@ -513,12 +513,11 @@ module.exports = () => {
const previousModel = em.previous('selectedComponent'); const previousModel = em.previous('selectedComponent');
// Deselect the previous component // Deselect the previous component
if (previousModel) { previousModel &&
previousModel.set({ previousModel.set({
status: '', status: '',
state: '' state: ''
}); });
}
model && model.set('status', 'selected'); model && model.set('status', 'selected');
} }

8
src/dom_components/view/ComponentView.js

@ -106,6 +106,7 @@ module.exports = Backbone.View.extend({
var selectedCls = pfx + 'selected'; var selectedCls = pfx + 'selected';
var selectedParentCls = selectedCls + '-parent'; var selectedParentCls = selectedCls + '-parent';
var freezedCls = `${ppfx}freezed`; var freezedCls = `${ppfx}freezed`;
this.$el.removeClass(`${selectedCls} ${selectedParentCls} ${freezedCls}`);
var actualCls = el.getAttribute('class') || ''; var actualCls = el.getAttribute('class') || '';
var cls = ''; var cls = '';
@ -119,10 +120,9 @@ module.exports = Backbone.View.extend({
case 'freezed': case 'freezed':
cls = `${actualCls} ${freezedCls}`; cls = `${actualCls} ${freezedCls}`;
break; break;
default: case 'freezed-selected':
this.$el.removeClass( cls = `${actualCls} ${freezedCls} ${selectedCls}`;
`${selectedCls} ${selectedParentCls} ${freezedCls}` break;
);
} }
cls = cls.trim(); cls = cls.trim();

9
src/domain_abstract/model/Styleable.js

@ -39,7 +39,14 @@ export default {
const propNew = { ...prop }; const propNew = { ...prop };
this.set('style', propNew, opts); this.set('style', propNew, opts);
const diff = shallowDiff(propOrig, propNew); const diff = shallowDiff(propOrig, propNew);
keys(diff).forEach(pr => this.trigger(`change:style:${pr}`)); keys(diff).forEach(pr => {
const em = this.em;
this.trigger(`change:style:${pr}`);
if (em) {
em.trigger(`styleable:change`);
em.trigger(`styleable:change:${pr}`);
}
});
return propNew; return propNew;
}, },

12
src/domain_abstract/ui/InputNumber.js

@ -1,4 +1,4 @@
import { bindAll } from 'underscore'; import { bindAll, isUndefined } from 'underscore';
import { on, off } from 'utils/mixins'; import { on, off } from 'utils/mixins';
const Input = require('./Input'); const Input = require('./Input');
const Backbone = require('backbone'); const Backbone = require('backbone');
@ -228,7 +228,8 @@ module.exports = Input.extend({
var force = 0; var force = 0;
var opt = opts || {}; var opt = opts || {};
var model = this.model; var model = this.model;
var val = value !== '' ? value : model.get('defaults'); const defValue = ''; //model.get('defaults');
var val = !isUndefined(value) ? value : defValue;
var units = model.get('units') || []; var units = model.get('units') || [];
var unit = model.get('unit') || (units.length && units[0]) || ''; var unit = model.get('unit') || (units.length && units[0]) || '';
var max = model.get('max'); var max = model.get('max');
@ -248,7 +249,7 @@ module.exports = Input.extend({
var valCopy = val + ''; var valCopy = val + '';
val += ''; // Make it suitable for replace val += ''; // Make it suitable for replace
val = parseFloat(val.replace(',', '.')); val = parseFloat(val.replace(',', '.'));
val = !isNaN(val) ? val : model.get('defaults'); val = !isNaN(val) ? val : defValue;
var uN = valCopy.replace(val, ''); var uN = valCopy.replace(val, '');
// Check if exists as unit // Check if exists as unit
if (_.indexOf(units, uN) >= 0) unit = uN; if (_.indexOf(units, uN) >= 0) unit = uN;
@ -256,9 +257,8 @@ module.exports = Input.extend({
} }
} }
if (typeof max !== 'undefined' && max !== '') val = val > max ? max : val; if (!isUndefined(max) && max !== '') val = val > max ? max : val;
if (!isUndefined(min) && min !== '') val = val < min ? min : val;
if (typeof min !== 'undefined' && min !== '') val = val < min ? min : val;
return { return {
force, force,

5
src/editor/config/config.js

@ -230,9 +230,12 @@ module.exports = {
] ]
}, },
//Configurations for Block Manager // Configurations for Block Manager
blockManager: {}, blockManager: {},
// Configurations for Trait Manager
traitManager: {},
// Texts // Texts
textViewCode: 'Code' textViewCode: 'Code'

6
src/editor/index.js

@ -124,6 +124,12 @@ module.exports = config => {
*/ */
DomComponents: em.get('DomComponents'), DomComponents: em.get('DomComponents'),
/**
* @property {LayerManager}
* @private
*/
LayerManager: em.get('LayerManager'),
/** /**
* @property {CssComposer} * @property {CssComposer}
* @private * @private

17
src/editor/model/Editor.js

@ -1,4 +1,4 @@
import { isUndefined, defaults } from 'underscore'; import { isUndefined, isElement, defaults } from 'underscore';
const deps = [ const deps = [
require('utils'), require('utils'),
@ -17,6 +17,7 @@ const deps = [
require('css_composer'), require('css_composer'),
require('trait_manager'), require('trait_manager'),
require('dom_components'), require('dom_components'),
require('navigator'),
require('canvas'), require('canvas'),
require('commands'), require('commands'),
require('block_manager') require('block_manager')
@ -216,20 +217,14 @@ module.exports = Backbone.Model.extend({
/** /**
* Select a component * Select a component
* @param {Component|HTMLElement} el Component to select * @param {Component|HTMLElement} el Component to select
* @param {Object} opts Options, optional * @param {Object} [opts={}] Options, optional
* @private * @private
*/ */
setSelected(el, opts = {}) { setSelected(el, opts = {}) {
let model = el; let model = el;
isElement(el) && (model = $(el).data('model'));
if (el instanceof window.HTMLElement) { if (model && !model.get('selectable')) return;
model = $(el).data('model'); opts.forceChange && this.set('selectedComponent', '');
}
if (model && !model.get('selectable')) {
return;
}
this.set('selectedComponent', model, opts); this.set('selectedComponent', model, opts);
}, },

6
src/index.js

@ -1,7 +1,8 @@
import $ from 'cash-dom'; import $ from 'cash-dom';
import Editor from './editor'; import Editor from './editor';
import PluginManager from './plugin_manager'; import { isElement } from 'underscore';
import polyfills from 'utils/polyfills'; import polyfills from 'utils/polyfills';
import PluginManager from './plugin_manager';
polyfills(); polyfills();
@ -48,8 +49,7 @@ module.exports = (() => {
const els = config.container; const els = config.container;
if (!els) throw new Error("'container' is required"); if (!els) throw new Error("'container' is required");
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
const ilEl = els instanceof window.HTMLElement; config.el = isElement(els) ? els : document.querySelector(els);
config.el = ilEl ? els : document.querySelector(els);
const editor = new Editor(config).init(); const editor = new Editor(config).init();
// Load plugins // Load plugins

6
src/modal_dialog/index.js

@ -52,9 +52,9 @@ module.exports = () => {
return this; return this;
}, },
postRender(editorView) { postRender(view) {
// c.em.config.el || 'body' const el = view.model.getConfig().el || view.el;
this.render().appendTo(editorView.el); this.render().appendTo(el);
}, },
/** /**

2
src/modal_dialog/view/ModalView.js

@ -1,6 +1,6 @@
module.exports = require('backbone').View.extend({ module.exports = require('backbone').View.extend({
template({ pfx, ppfx, content, title }) { template({ pfx, ppfx, content, title }) {
return `<div class="${pfx}dialog ${ppfx}one-bg"> return `<div class="${pfx}dialog ${ppfx}one-bg ${ppfx}two-color">
<div class="${pfx}header"> <div class="${pfx}header">
<div class="${pfx}title">${title}</div> <div class="${pfx}title">${title}</div>
<div class="${pfx}btn-close">&Cross;</div> <div class="${pfx}btn-close">&Cross;</div>

6
src/navigator/config/config.js

@ -1,5 +1,9 @@
module.exports = { module.exports = {
stylePrefix: 'nv-', stylePrefix: '',
// Specify the element to use as a container, string (query) or HTMLElement
// With the empty value, nothing will be rendered
appendTo: '',
// Enable/Disable globally the possibility to sort layers // Enable/Disable globally the possibility to sort layers
sortable: 1, sortable: 1,

77
src/navigator/index.js

@ -1,42 +1,62 @@
import defaults from './config/config';
import ItemView from './view/ItemView';
import ItemsView from './view/ItemsView';
import { isElement } from 'underscore';
module.exports = () => { module.exports = () => {
let itemsView; let em;
let layers;
let config = {}; let config = {};
const defaults = require('./config/config'); let View = ItemsView;
const ItemView = require('./view/ItemView');
const ItemsView = require('./view/ItemsView');
return { return {
init(collection, opts) { name: 'LayerManager',
config = opts || config;
const em = config.em;
// Set default options init(opts = {}) {
for (var name in defaults) { config = { ...defaults, ...opts };
if (!(name in config)) config[name] = defaults[name]; config.stylePrefix = opts.pStylePrefix;
} em = config.em;
return this;
},
let View = ItemsView; onLoad() {
const level = 0; const collection = em.get('DomComponents').getComponents();
const opened = opts.opened || {}; const parent = collection.parent;
const options = { const options = {
level, level: 0,
config, config,
opened opened: config.opened || {}
}; };
// Show wrapper if requested // Show wrapper if requested
if (config.showWrapper && collection.parent) { if (config.showWrapper && parent) {
View = ItemView; View = ItemView;
options.model = collection.parent; options.model = parent;
} else { } else {
options.collection = collection; options.collection = collection;
} }
itemsView = new View(options); layers = new View(options);
em && em.on('change:selectedComponent', this.componentChanged); em && em.on('component:selected', this.componentChanged);
this.componentChanged(); this.componentChanged();
},
return this; postRender() {
const elTo = config.appendTo;
if (elTo) {
const el = isElement(elTo) ? elTo : document.querySelector(elTo);
el.appendChild(this.render());
}
},
/**
* Return the view of layers
* @return {View}
*/
getAll() {
return layers;
}, },
/** /**
@ -44,18 +64,11 @@ module.exports = () => {
* @private * @private
*/ */
componentChanged(e, md, opts = {}) { componentChanged(e, md, opts = {}) {
if (opts.fromLayers) { if (opts.fromLayers) return;
return;
}
const em = config.em;
const opened = em.get('opened'); const opened = em.get('opened');
const model = em.get('selectedComponent'); const model = em.getSelected();
let parent = model && model.collection ? model.collection.parent : null; let parent = model && model.collection ? model.collection.parent : null;
for (let cid in opened) opened[cid].set('open', 0);
for (let cid in opened) {
opened[cid].set('open', 0);
}
while (parent) { while (parent) {
parent.set('open', 1); parent.set('open', 1);
@ -65,7 +78,7 @@ module.exports = () => {
}, },
render() { render() {
return itemsView.render().$el; return layers.render().el;
} }
}; };
}; };

108
src/navigator/view/ItemView.js

@ -1,5 +1,6 @@
import { isUndefined } from 'underscore'; import { isUndefined } from 'underscore';
const ComponentView = require('dom_components/view/ComponentView'); const ComponentView = require('dom_components/view/ComponentView');
const inputProp = 'contentEditable';
let ItemsView; let ItemsView;
module.exports = require('backbone').View.extend({ module.exports = require('backbone').View.extend({
@ -8,8 +9,8 @@ module.exports = require('backbone').View.extend({
'click [data-toggle-visible]': 'toggleVisibility', 'click [data-toggle-visible]': 'toggleVisibility',
'click [data-toggle-select]': 'handleSelect', 'click [data-toggle-select]': 'handleSelect',
'click [data-toggle-open]': 'toggleOpening', 'click [data-toggle-open]': 'toggleOpening',
'dblclick input': 'handleEdit', 'dblclick [data-name]': 'handleEdit',
'focusout input': 'handleEditEnd' 'focusout [data-name]': 'handleEditEnd'
}, },
template(model) { template(model) {
@ -17,36 +18,37 @@ module.exports = require('backbone').View.extend({
const ppfx = this.ppfx; const ppfx = this.ppfx;
const hidable = this.config.hidable; const hidable = this.config.hidable;
const count = this.countChildren(model); const count = this.countChildren(model);
const addClass = !count ? `${pfx}no-chld` : ''; const addClass = !count ? this.clsNoChild : '';
const clsTitle = `${this.clsTitle} ${addClass}`;
const clsTitleC = `${this.clsTitleC} ${ppfx}one-bg`;
const clsCaret = `${this.clsCaret} fa fa-chevron-right`;
const clsInput = `${this.inputNameCls} ${ppfx}no-app`;
const level = this.level + 1; const level = this.level + 1;
const gut = `${30 + level * 10}px`;
const name = model.getName();
return ` return `
${ ${
hidable hidable
? `<i id="${pfx}btn-eye" class="${pfx}btn fa fa-eye ${ ? `<i class="${pfx}layer-vis fa fa-eye ${
this.isVisible() ? '' : 'fa-eye-slash' this.isVisible() ? '' : 'fa-eye-slash'
}" data-toggle-visible></i>` }" data-toggle-visible></i>`
: '' : ''
} }
<div class="${pfx}title-c ${ppfx}one-bg"> <div class="${clsTitleC}">
<div class="${pfx}title ${addClass}" style="padding-left: ${30 + <div class="${clsTitle}" style="padding-left: ${gut}" data-toggle-select>
level * 10}px" data-toggle-select> <div class="${pfx}layer-title-inn">
<div class="${pfx}title-inn"> <i class="${clsCaret}" data-toggle-open></i>
<i id="${pfx}caret" class="fa fa-chevron-right ${
this.caretCls
}" data-toggle-open></i>
${model.getIcon()} ${model.getIcon()}
<input class="${ppfx}no-app ${ <span class="${clsInput}" data-name>${name}</span>
this.inputNameCls
}" value="${model.getName()}" readonly>
</div> </div>
</div> </div>
</div> </div>
<div id="${pfx}counter">${count ? count : ''}</div> <div class="${this.clsCount}">${count || ''}</div>
<div id="${pfx}move" data-toggle-move> <div class="${this.clsMove}" data-toggle-move>
<i class="fa fa-arrows"></i> <i class="fa fa-arrows"></i>
</div> </div>
<div class="${pfx}children"></div> <div class="${this.clsChildren}"></div>
`; `;
}, },
@ -68,18 +70,22 @@ module.exports = require('backbone').View.extend({
this.listenTo(model, 'change:status', this.updateStatus); this.listenTo(model, 'change:status', this.updateStatus);
this.listenTo(model, 'change:open', this.updateOpening); this.listenTo(model, 'change:open', this.updateOpening);
this.listenTo(model, 'change:style:display', this.updateVisibility); this.listenTo(model, 'change:style:display', this.updateVisibility);
this.className = `${pfx}item no-select`; this.className = `${pfx}layer no-select ${ppfx}two-color`;
this.editBtnCls = `${pfx}nav-item-edit`; this.inputNameCls = `${ppfx}layer-name`;
this.inputNameCls = `${ppfx}nav-comp-name`; this.clsTitleC = `${pfx}layer-title-c`;
this.caretCls = `${ppfx}nav-item-caret`; this.clsTitle = `${pfx}layer-title`;
this.titleCls = `${pfx}title`; this.clsCaret = `${pfx}layer-caret`;
this.clsCount = `${pfx}layer-count`;
this.clsMove = `${pfx}layer-move`;
this.clsChildren = `${pfx}layer-children`;
this.clsNoChild = `${pfx}layer-no-chld`;
this.$el.data('model', model); this.$el.data('model', model);
this.$el.data('collection', components); this.$el.data('collection', components);
}, },
getVisibilityEl() { getVisibilityEl() {
if (!this.eyeEl) { if (!this.eyeEl) {
this.eyeEl = this.$el.children(`#${this.pfx}btn-eye`); this.eyeEl = this.$el.children(`.${this.pfx}layer-vis`);
} }
return this.eyeEl; return this.eyeEl;
@ -88,7 +94,7 @@ module.exports = require('backbone').View.extend({
updateVisibility() { updateVisibility() {
const pfx = this.pfx; const pfx = this.pfx;
const model = this.model; const model = this.model;
const hClass = `${pfx}hide`; const hClass = `${pfx}layer-hidden`;
const hideIcon = 'fa-eye-slash'; const hideIcon = 'fa-eye-slash';
const hidden = model.getStyle().display == 'none'; const hidden = model.getStyle().display == 'none';
const method = hidden ? 'addClass' : 'removeClass'; const method = hidden ? 'addClass' : 'removeClass';
@ -121,20 +127,21 @@ module.exports = require('backbone').View.extend({
* Handle the edit of the component name * Handle the edit of the component name
*/ */
handleEdit(e) { handleEdit(e) {
e.stopPropagation(); e && e.stopPropagation();
var inputName = this.getInputName(); const inputEl = this.getInputName();
inputName.readOnly = false; inputEl[inputProp] = true;
inputName.focus(); inputEl.focus();
}, },
/** /**
* Handle with the end of editing of the component name * Handle with the end of editing of the component name
*/ */
handleEditEnd(e) { handleEditEnd(e) {
e.stopPropagation(); e && e.stopPropagation();
var inputName = this.getInputName(); const inputEl = this.getInputName();
inputName.readOnly = true; const name = inputEl.textContent;
this.model.set('custom-name', inputName.value); inputEl[inputProp] = false;
this.model.set({ name });
}, },
/** /**
@ -143,7 +150,7 @@ module.exports = require('backbone').View.extend({
*/ */
getInputName() { getInputName() {
if (!this.inputName) { if (!this.inputName) {
this.inputName = this.el.querySelector('.' + this.inputNameCls); this.inputName = this.el.querySelector(`.${this.inputNameCls}`);
} }
return this.inputName; return this.inputName;
}, },
@ -197,13 +204,10 @@ module.exports = require('backbone').View.extend({
* */ * */
startSort(e) { startSort(e) {
e.stopPropagation(); e.stopPropagation();
const sorter = this.sorter;
//Right or middel click // Right or middel click
if (e.button !== 0) { if (e.button !== 0) return;
return; sorter && sorter.startSort(e.target);
}
this.sorter && this.sorter.startSort(e.target);
}, },
/** /**
@ -252,19 +256,21 @@ module.exports = require('backbone').View.extend({
const model = this.model; const model = this.model;
const c = this.countChildren(model); const c = this.countChildren(model);
const pfx = this.pfx; const pfx = this.pfx;
const noChildCls = `${pfx}no-chld`; const noChildCls = this.clsNoChild;
const title = this.$el.children(`.${pfx}title-c`).children(`.${pfx}title`); const title = this.$el
//tC = `> .${pfx}title-c > .${pfx}title`; .children(`.${this.clsTitleC}`)
if (!this.$counter) { .children(`.${this.clsTitle}`);
this.$counter = this.$el.children(`#${pfx}counter`);
if (!this.cnt) {
this.cnt = this.$el.children(`.${this.clsCount}`);
} }
if (c) { if (c) {
title.removeClass(noChildCls); title.removeClass(noChildCls);
this.$counter.html(c); this.cnt.html(c);
} else { } else {
title.addClass(noChildCls); title.addClass(noChildCls);
this.$counter.empty(); this.cnt.empty();
model.set('open', 0); model.set('open', 0);
} }
}, },
@ -289,7 +295,9 @@ module.exports = require('backbone').View.extend({
getCaret() { getCaret() {
if (!this.caret) { if (!this.caret) {
const pfx = this.pfx; const pfx = this.pfx;
this.caret = this.$el.children(`.${pfx}title-c`).find(`#${pfx}caret`); this.caret = this.$el
.children(`.${this.clsTitleC}`)
.find(`.${this.clsCaret}`);
} }
return this.caret; return this.caret;
@ -315,10 +323,10 @@ module.exports = require('backbone').View.extend({
parent: model, parent: model,
level level
}).render().$el; }).render().$el;
el.find(`.${pfx}children`).append(children); el.find(`.${this.clsChildren}`).append(children);
if (!model.get('draggable') || !this.config.sortable) { if (!model.get('draggable') || !this.config.sortable) {
el.children(`#${pfx}move`).remove(); el.children(`.${this.clsMove}`).remove();
} }
!vis && (this.className += ` ${pfx}hide`); !vis && (this.className += ` ${pfx}hide`);

47
src/navigator/view/ItemsView.js

@ -1,7 +1,6 @@
var Backbone = require('backbone'); const ItemView = require('./ItemView');
var ItemView = require('./ItemView');
module.exports = Backbone.View.extend({ module.exports = require('backbone').View.extend({
initialize(o = {}) { initialize(o = {}) {
this.opt = o; this.opt = o;
const config = o.config || {}; const config = o.config || {};
@ -11,33 +10,38 @@ module.exports = Backbone.View.extend({
this.ppfx = config.pStylePrefix || ''; this.ppfx = config.pStylePrefix || '';
this.pfx = config.stylePrefix || ''; this.pfx = config.stylePrefix || '';
this.parent = o.parent; this.parent = o.parent;
this.listenTo(this.collection, 'add', this.addTo); const pfx = this.pfx;
this.listenTo(this.collection, 'reset resetNavigator', this.render); const ppfx = this.ppfx;
this.className = this.pfx + 'items'; const parent = this.parent;
const coll = this.collection;
this.listenTo(coll, 'add', this.addTo);
this.listenTo(coll, 'reset resetNavigator', this.render);
this.className = `${pfx}layers`;
const em = config.em;
if (config.sortable && !this.opt.sorter) { if (config.sortable && !this.opt.sorter) {
var pfx = this.pfx; const utils = em.get('Utils');
var utils = config.em.get('Utils');
this.opt.sorter = new utils.Sorter({ this.opt.sorter = new utils.Sorter({
container: config.sortContainer || this.el, container: config.sortContainer || this.el,
containerSel: '.' + pfx + 'items', containerSel: `.${this.className}`,
itemSel: '.' + pfx + 'item', itemSel: `.${pfx}layer`,
ppfx: this.ppfx,
ignoreViewChildren: 1, ignoreViewChildren: 1,
onEndMove(created, sorter) {
const srcModel = sorter.getSourceModel();
em.setSelected(srcModel, { forceChange: 1 });
},
avoidSelectOnEnd: 1, avoidSelectOnEnd: 1,
pfx, nested: 1,
nested: 1 ppfx,
pfx
}); });
} }
this.sorter = this.opt.sorter || ''; this.sorter = this.opt.sorter || '';
// For the sorter // For the sorter
this.$el.data('collection', this.collection); this.$el.data('collection', coll);
parent && this.$el.data('model', parent);
if (this.parent) {
this.$el.data('model', this.parent);
}
}, },
/** /**
@ -123,10 +127,11 @@ module.exports = Backbone.View.extend({
render() { render() {
const frag = document.createDocumentFragment(); const frag = document.createDocumentFragment();
this.el.innerHTML = ''; const el = this.el;
el.innerHTML = '';
this.collection.each(model => this.addToCollection(model, frag)); this.collection.each(model => this.addToCollection(model, frag));
this.el.appendChild(frag); el.appendChild(frag);
this.$el.attr('class', this.className); el.className = this.className;
return this; return this;
} }
}); });

2
src/panels/view/ButtonsView.js

@ -8,7 +8,7 @@ module.exports = Backbone.View.extend({
this.pfx = this.config.stylePrefix || ''; this.pfx = this.config.stylePrefix || '';
this.parentM = this.opt.parentM || null; this.parentM = this.opt.parentM || null;
this.listenTo(this.collection, 'add', this.addTo); this.listenTo(this.collection, 'add', this.addTo);
this.listenTo(this.collection, 'reset', this.render); this.listenTo(this.collection, 'reset remove', this.render);
this.className = this.pfx + 'buttons'; this.className = this.pfx + 'buttons';
}, },

41
src/panels/view/PanelView.js

@ -68,16 +68,35 @@ module.exports = Backbone.View.extend({
bl: 0, bl: 0,
br: 0, br: 0,
appendTo: this.el, appendTo: this.el,
silentFrames: 1,
avoidContainerUpdate: 1,
prefix: editor.getConfig().stylePrefix, prefix: editor.getConfig().stylePrefix,
posFetcher: el => { onEnd() {
var rect = el.getBoundingClientRect(); em && em.trigger('change:canvasOffset');
},
posFetcher: (el, { target }) => {
const style = el.style;
const config = resizer.getConfig();
const keyWidth = config.keyWidth;
const keyHeight = config.keyHeight;
const rect = el.getBoundingClientRect();
const forContainer = target == 'container';
const styleWidth = style[keyWidth];
const styleHeight = style[keyHeight];
const width =
styleWidth && !forContainer ? parseFloat(styleWidth) : rect.width;
const height =
styleHeight && !forContainer
? parseFloat(styleHeight)
: rect.height;
return { return {
left: 0, left: 0,
top: 0, top: 0,
width: rect.width, width,
height: rect.height height
}; };
} },
...resizable
}); });
resizer.blur = () => {}; resizer.blur = () => {};
resizer.focus(this.el); resizer.focus(this.el);
@ -85,20 +104,20 @@ module.exports = Backbone.View.extend({
}, },
render() { render() {
const el = this.$el; const $el = this.$el;
const pfx = this.ppfx; const ppfx = this.ppfx;
el.attr('class', `${this.className} ${pfx}one-bg`); const cls = `${this.className} ${this.id} ${ppfx}one-bg ${ppfx}two-color`;
this.id && el.attr('id', this.id); $el.addClass(cls);
if (this.buttons.length) { if (this.buttons.length) {
var buttons = new ButtonsView({ var buttons = new ButtonsView({
collection: this.buttons, collection: this.buttons,
config: this.config config: this.config
}); });
el.append(buttons.render().el); $el.append(buttons.render().el);
} }
el.append(this.model.get('content')); $el.append(this.model.get('content'));
return this; return this;
} }
}); });

32
src/panels/view/PanelsView.js

@ -32,15 +32,20 @@ module.exports = Backbone.View.extend({
* @private * @private
* */ * */
addToCollection(model, fragmentEl) { addToCollection(model, fragmentEl) {
var fragment = fragmentEl || null; const fragment = fragmentEl || null;
var view = new PanelView({ const config = this.config;
const el = model.get('el');
const view = new PanelView({
el,
model, model,
config: this.config config
}); });
var rendered = view.render().el; const rendered = view.render().el;
var appendTo = model.get('appendTo'); const appendTo = model.get('appendTo');
if (appendTo) { // Do nothing if the panel was requested to be another element
if (el) {
} else if (appendTo) {
var appendEl = document.querySelector(appendTo); var appendEl = document.querySelector(appendTo);
appendEl.appendChild(rendered); appendEl.appendChild(rendered);
} else { } else {
@ -56,15 +61,12 @@ module.exports = Backbone.View.extend({
}, },
render() { render() {
var fragment = document.createDocumentFragment(); const $el = this.$el;
this.$el.empty(); const frag = document.createDocumentFragment();
$el.empty();
this.collection.each(function(model) { this.collection.each(model => this.addToCollection(model, frag));
this.addToCollection(model, fragment); $el.append(frag);
}, this); $el.attr('class', this.className);
this.$el.append(fragment);
this.$el.attr('class', this.className);
return this; return this;
} }
}); });

4
src/selector_manager/config/config.js

@ -2,6 +2,10 @@ module.exports = {
// Style prefix // Style prefix
stylePrefix: 'clm-', stylePrefix: 'clm-',
// Specify the element to use as a container, string (query) or HTMLElement
// With the empty value, nothing will be rendered
appendTo: '',
// Default selectors // Default selectors
selectors: [], selectors: [],

15
src/selector_manager/index.js

@ -49,7 +49,7 @@
* } * }
*/ */
import { isString } from 'underscore'; import { isString, isElement } from 'underscore';
module.exports = config => { module.exports = config => {
var c = config || {}, var c = config || {},
@ -80,6 +80,10 @@ module.exports = config => {
return c; return c;
}, },
getConfig() {
return c;
},
/** /**
* Initialize module. Automatically called with a new instance of the editor * Initialize module. Automatically called with a new instance of the editor
* @param {Object} config Configurations * @param {Object} config Configurations
@ -112,6 +116,15 @@ module.exports = config => {
return this; return this;
}, },
postRender() {
const elTo = this.getConfig().appendTo;
if (elTo) {
const el = isElement(elTo) ? elTo : document.querySelector(elTo);
el.appendChild(this.render([]));
}
},
/** /**
* Add a new selector to collection if it's not already exists. Class type is a default one * Add a new selector to collection if it's not already exists. Class type is a default one
* @param {String} name Selector name * @param {String} name Selector name

16
src/selector_manager/view/ClassTagsView.js

@ -303,8 +303,10 @@ module.exports = Backbone.View.extend({
}, },
render() { render() {
const ppfx = this.ppfx;
const config = this.config; const config = this.config;
this.$el.html( const $el = this.$el;
$el.html(
this.template({ this.template({
selectedLabel: config.selectedLabel, selectedLabel: config.selectedLabel,
statesLabel: config.statesLabel, statesLabel: config.statesLabel,
@ -313,14 +315,14 @@ module.exports = Backbone.View.extend({
ppfx: this.ppfx ppfx: this.ppfx
}) })
); );
this.$input = this.$el.find('input#' + this.newInputId); this.$input = $el.find('input#' + this.newInputId);
this.$addBtn = this.$el.find('#' + this.addBtnId); this.$addBtn = $el.find('#' + this.addBtnId);
this.$classes = this.$el.find('#' + this.pfx + 'tags-c'); this.$classes = $el.find('#' + this.pfx + 'tags-c');
this.$states = this.$el.find('#' + this.stateInputId); this.$states = $el.find('#' + this.stateInputId);
this.$statesC = this.$el.find('#' + this.stateInputC); this.$statesC = $el.find('#' + this.stateInputC);
this.$states.append(this.getStateOptions()); this.$states.append(this.getStateOptions());
this.renderClasses(); this.renderClasses();
this.$el.attr('class', this.className); $el.attr('class', `${this.className} ${ppfx}one-bg ${ppfx}two-color`);
return this; return this;
} }
}); });

5
src/storage_manager/index.js

@ -193,7 +193,7 @@ module.exports = () => {
for (var i = 0, len = keys.length; i < len; i++) for (var i = 0, len = keys.length; i < len; i++)
keysF.push(c.id + keys[i]); keysF.push(c.id + keys[i]);
st && if (st) {
st.load(keysF, res => { st.load(keysF, res => {
// Restore keys name // Restore keys name
var reg = new RegExp('^' + c.id + ''); var reg = new RegExp('^' + c.id + '');
@ -204,6 +204,9 @@ module.exports = () => {
clb && clb(result); clb && clb(result);
}); });
} else {
clb && clb(result);
}
}, },
/** /**

4
src/style_manager/config/config.js

@ -3,6 +3,10 @@ module.exports = {
sectors: [], sectors: [],
// Specify the element to use as a container, string (query) or HTMLElement
// With the empty value, nothing will be rendered
appendTo: '',
// Text to show in case no element selected // Text to show in case no element selected
textNoElement: 'Select an element before using Style Manager', textNoElement: 'Select an element before using Style Manager',

11
src/style_manager/index.js

@ -38,6 +38,8 @@
* } * }
* ... * ...
*/ */
import { isElement } from 'underscore';
module.exports = () => { module.exports = () => {
var c = {}, var c = {},
defaults = require('./config/config'), defaults = require('./config/config'),
@ -87,6 +89,15 @@ module.exports = () => {
return this; return this;
}, },
postRender() {
const elTo = this.getConfig().appendTo;
if (elTo) {
const el = isElement(elTo) ? elTo : document.querySelector(elTo);
el.appendChild(this.render());
}
},
/** /**
* Add new sector to the collection. If the sector with the same id already exists, * Add new sector to the collection. If the sector with the same id already exists,
* that one will be returned * that one will be returned

17
src/style_manager/model/Property.js

@ -1,3 +1,5 @@
import { isUndefined } from 'underscore';
module.exports = require('backbone').Model.extend({ module.exports = require('backbone').Model.extend({
defaults: { defaults: {
name: '', name: '',
@ -36,6 +38,15 @@ module.exports = require('backbone').Model.extend({
init && init(); init && init();
}, },
/**
* Clear the value
* @return {this}
*/
clearValue(opts = {}) {
this.set({ value: undefined }, opts);
return this;
},
/** /**
* Update value * Update value
* @param {any} value * @param {any} value
@ -117,12 +128,12 @@ module.exports = require('backbone').Model.extend({
*/ */
getFullValue(val) { getFullValue(val) {
const fn = this.get('functionName'); const fn = this.get('functionName');
let value = val || this.get('value'); let value = isUndefined(val) ? this.get('value') : val;
if (fn) { if (fn && !isUndefined(value)) {
value = `${fn}(${value})`; value = `${fn}(${value})`;
} }
return value; return value || '';
} }
}); });

11
src/style_manager/model/PropertyComposite.js

@ -28,11 +28,20 @@ module.exports = Property.extend({
this.listenTo(this, 'change:value', this.updateValues); this.listenTo(this, 'change:value', this.updateValues);
}, },
/**
* Clear the value
* @return {this}
*/
clearValue(opts = {}) {
this.get('properties').each(property => property.clearValue());
return Property.prototype.clearValue.apply(this, arguments);
},
/** /**
* Update property values * Update property values
*/ */
updateValues() { updateValues() {
const values = this.get('value').split(this.get('separator')); const values = this.getFullValue().split(this.get('separator'));
this.get('properties').each((property, i) => { this.get('properties').each((property, i) => {
const len = values.length; const len = values.length;
// Try to get value from a shorthand: // Try to get value from a shorthand:

13
src/style_manager/model/PropertyInteger.js

@ -1,3 +1,5 @@
import { isUndefined } from 'underscore';
const Property = require('./Property'); const Property = require('./Property');
const InputNumber = require('domain_abstract/ui/InputNumber'); const InputNumber = require('domain_abstract/ui/InputNumber');
@ -30,6 +32,11 @@ module.exports = Property.extend({
} }
}, },
clearValue(opts = {}) {
this.set({ value: undefined, unit: undefined }, opts);
return this;
},
parseValue(val) { parseValue(val) {
const parsed = Property.prototype.parseValue.apply(this, arguments); const parsed = Property.prototype.parseValue.apply(this, arguments);
const { value, unit } = this.input.validateInputValue(parsed.value, { const { value, unit } = this.input.validateInputValue(parsed.value, {
@ -41,7 +48,11 @@ module.exports = Property.extend({
}, },
getFullValue() { getFullValue() {
let value = this.get('value') + this.get('unit'); let value = this.get('value');
let unit = this.get('unit');
value = !isUndefined(value) ? value : '';
unit = !isUndefined(unit) && value ? unit : '';
value = `${value}${unit}`;
return Property.prototype.getFullValue.apply(this, [value]); return Property.prototype.getFullValue.apply(this, [value]);
} }
}); });

3
src/style_manager/view/PropertiesView.js

@ -16,6 +16,7 @@ module.exports = Backbone.View.extend({
this.onChange = o.onChange; this.onChange = o.onChange;
this.onInputRender = o.onInputRender || {}; this.onInputRender = o.onInputRender || {};
this.customValue = o.customValue || {}; this.customValue = o.customValue || {};
this.properties = [];
const coll = this.collection; const coll = this.collection;
this.listenTo(coll, 'add', this.addTo); this.listenTo(coll, 'add', this.addTo);
this.listenTo(coll, 'reset', this.render); this.listenTo(coll, 'reset', this.render);
@ -43,6 +44,7 @@ module.exports = Backbone.View.extend({
view.render(); view.render();
const el = view.el; const el = view.el;
this.properties.push(view);
if (frag) { if (frag) {
frag.appendChild(el); frag.appendChild(el);
@ -52,6 +54,7 @@ module.exports = Backbone.View.extend({
}, },
render() { render() {
this.properties = [];
const fragment = document.createDocumentFragment(); const fragment = document.createDocumentFragment();
this.collection.each(model => this.add(model, fragment)); this.collection.each(model => this.add(model, fragment));
this.$el.append(fragment); this.$el.append(fragment);

8
src/style_manager/view/PropertyCompositeView.js

@ -19,6 +19,12 @@ module.exports = PropertyView.extend({
} }
}, },
clear(e) {
const props = this.properties;
props && props.forEach(propView => propView.clear());
PropertyView.prototype.clear.apply(this, arguments);
},
/** /**
* Renders input * Renders input
* */ * */
@ -26,6 +32,7 @@ module.exports = PropertyView.extend({
var model = this.model; var model = this.model;
var props = model.get('properties') || []; var props = model.get('properties') || [];
var self = this; var self = this;
this.properties = [];
if (props.length) { if (props.length) {
if (!this.$input) { if (!this.$input) {
@ -50,6 +57,7 @@ module.exports = PropertyView.extend({
var PropertiesView = require('./PropertiesView'); var PropertiesView = require('./PropertiesView');
var propsView = new PropertiesView(this.getPropsConfig()); var propsView = new PropertiesView(this.getPropsConfig());
this.$props = propsView.render().$el; this.$props = propsView.render().$el;
this.properties = propsView.properties;
this.$el.find(`#${this.pfx}input-holder`).append(this.$props); this.$el.find(`#${this.pfx}input-holder`).append(this.$props);
} }
} }

6
src/style_manager/view/PropertyIntegerView.js

@ -1,7 +1,9 @@
const InputNumber = require('domain_abstract/ui/InputNumber'); const InputNumber = require('domain_abstract/ui/InputNumber');
const PropertyView = require('./PropertyView');
const $ = Backbone.$; const $ = Backbone.$;
let timeout;
module.exports = require('./PropertyView').extend({ module.exports = PropertyView.extend({
templateInput() { templateInput() {
return ''; return '';
}, },
@ -13,6 +15,8 @@ module.exports = require('./PropertyView').extend({
}, },
setValue(value) { setValue(value) {
const parsed = this.model.parseValue(value);
value = `${parsed.value}${parsed.unit}`;
this.inputInst.setValue(value, { silent: 1 }); this.inputInst.setValue(value, { silent: 1 });
}, },

10
src/style_manager/view/PropertySliderView.js

@ -1,9 +1,13 @@
const Property = require('./PropertyIntegerView'); const Property = require('./PropertyIntegerView');
module.exports = Property.extend({ module.exports = Property.extend({
events: { events() {
'change [type=range]': 'inputValueChanged', return {
'input [type=range]': 'inputValueChangedSoft' ...Property.prototype.events,
'change [type=range]': 'inputValueChanged',
'input [type=range]': 'inputValueChangedSoft',
change: ''
};
}, },
templateInput(model) { templateInput(model) {

7
src/style_manager/view/PropertyStackView.js

@ -23,6 +23,13 @@ module.exports = PropertyCompositeView.extend({
this.delegateEvents(); this.delegateEvents();
}, },
clear(e) {
e && e.stopPropagation();
this.model.get('layers').reset();
this.model.clearValue();
this.targetUpdated();
},
/** /**
* Fired when the target is updated. * Fired when the target is updated.
* With detached mode the component will be always empty as its value * With detached mode the component will be always empty as its value

11
src/style_manager/view/PropertyView.js

@ -1,4 +1,4 @@
import { bindAll, isArray } from 'underscore'; import { bindAll, isArray, isUndefined } from 'underscore';
import { camelCase } from 'utils/mixins'; import { camelCase } from 'utils/mixins';
const clearProp = 'data-clear-style'; const clearProp = 'data-clear-style';
@ -66,6 +66,7 @@ module.exports = Backbone.View.extend({
} }
em && em.on(`update:component:style:${this.property}`, this.targetUpdated); em && em.on(`update:component:style:${this.property}`, this.targetUpdated);
//em && em.on(`styleable:change:${this.property}`, this.targetUpdated);
this.listenTo(this.propTarget, 'update', this.targetUpdated); this.listenTo(this.propTarget, 'update', this.targetUpdated);
this.listenTo(model, 'destroy remove', this.remove); this.listenTo(model, 'destroy remove', this.remove);
this.listenTo(model, 'change:value', this.modelValueChanged); this.listenTo(model, 'change:value', this.modelValueChanged);
@ -111,9 +112,9 @@ module.exports = Backbone.View.extend({
/** /**
* Clear the property from the target * Clear the property from the target
*/ */
clear() { clear(e) {
const target = this.getTargetModel(); e && e.stopPropagation();
target.removeStyle(this.model.get('property')); this.model.clearValue();
this.targetUpdated(); this.targetUpdated();
}, },
@ -435,7 +436,7 @@ module.exports = Backbone.View.extend({
* */ * */
setValue(value) { setValue(value) {
const model = this.model; const model = this.model;
let val = value || model.getDefaultValue(); let val = isUndefined(value) ? model.getDefaultValue() : value;
const input = this.getInputEl(); const input = this.getInputEl();
input && (input.value = val); input && (input.value = val);
}, },

25
src/style_manager/view/SectorsView.js

@ -3,10 +3,12 @@ import { extend } from 'underscore';
const SectorView = require('./SectorView'); const SectorView = require('./SectorView');
module.exports = Backbone.View.extend({ module.exports = Backbone.View.extend({
initialize(o) { initialize(o = {}) {
this.config = o.config || {}; const config = o.config || {};
this.pfx = this.config.stylePrefix || ''; this.pfx = config.stylePrefix || '';
this.ppfx = config.pStylePrefix || '';
this.target = o.target || {}; this.target = o.target || {};
this.config = config;
// The target that will emit events for properties // The target that will emit events for properties
const target = {}; const target = {};
@ -117,15 +119,14 @@ module.exports = Backbone.View.extend({
}, },
render() { render() {
var fragment = document.createDocumentFragment(); const frag = document.createDocumentFragment();
this.$el.empty(); const $el = this.$el;
const pfx = this.pfx;
this.collection.each(function(model) { const ppfx = this.ppfx;
this.addToCollection(model, fragment); $el.empty();
}, this); this.collection.each(model => this.addToCollection(model, frag));
$el.append(frag);
this.$el.attr('id', this.pfx + 'sectors'); $el.addClass(`${pfx}sectors ${ppfx}one-bg ${ppfx}two-color`);
this.$el.append(fragment);
return this; return this;
} }
}); });

3
src/styles/scss/_gjs_blocks.scss

@ -35,6 +35,7 @@
cursor: all-scroll; cursor: all-scroll;
font-size: 11px; font-size: 11px;
font-weight: lighter; font-weight: lighter;
text-align: center;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-end; justify-content: flex-end;
@ -51,7 +52,7 @@
} }
.#{$app-prefix}block-svg { .#{$app-prefix}block-svg {
width: 61%; width: 54px;
fill: currentColor; fill: currentColor;
} }

4
src/styles/scss/_gjs_canvas.scss

@ -94,6 +94,10 @@ $canvasTop: 40px;
@extend .#{$app-prefix}no-pointer-events; @extend .#{$app-prefix}no-pointer-events;
position: absolute; position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 9; z-index: 9;
} }

211
src/styles/scss/_gjs_layers.scss

@ -1,140 +1,117 @@
.#{$nv-prefix} {
&selected-parent {
border: 1px solid $colorYell;
}
.#{$nv-prefix}selected-parent { &opac50 {
border: 1px solid $colorYell; @include opacity(0.5);
}
.#{$nv-prefix}opac50{
@include opacity(0.50);
}
.#{$app-prefix}layers {
position:relative;
height: 100%;
##{$nv-prefix}placeholder{
width: 100%;
position: absolute;
##{$nv-prefix}plh-int{
height: 100%;
padding: 1px;
&.#{$nv-prefix}insert{
background-color: $colorGreen;
}
}
} }
.#{$nv-prefix}item {
&layer {
font-weight: lighter; font-weight: lighter;
text-align: left; text-align: left;
position: relative; position: relative;
background-color: rgba(0, 0, 0, 0.1); background-color: rgba(0, 0, 0, 0.1);
} font-size: $fontSizeS;
.#{$nv-prefix}item.#{$nv-prefix}hide {
@include opacity(0.55);
}
.#{$nv-prefix}item ##{$nv-prefix}counter {
font-size: 10px;
position: absolute;
right: 27px;
top: 9px;
}
.#{$nv-prefix}item ##{$nv-prefix}btn-eye{
@extend .btn;
height: auto !important; width: auto !important;
font-size: 13px;
left: 0; top: 0;
padding: 7px 5px 7px 10px;
position: absolute;
cursor:pointer;
z-index: 1;
}
}
.#{$nv-prefix}item ##{$nv-prefix}caret { &-hidden {
font-size: 7px; @include opacity(0.55);
width: 8px; }
padding: 2px;
cursor: pointer;
position: absolute;
left: -9px;
top: 6px;
@include opacity(0.7);
&:hover {
@include opacity(1);
}
}
.#{$nv-prefix}title { &-count {
@extend .#{$app-prefix}category-title; position: absolute;
right: 27px;
top: 9px;
}
padding: 3px 10px 5px 30px; &-vis {
display: flex; height: auto !important;
align-items: center; width: auto !important;
} left: 0;
top: 0;
padding: 7px 5px 7px 10px;
position: absolute;
cursor: pointer;
z-index: 1;
}
.#{$nv-prefix}title-inn { &-caret {
position: relative; font-size: 0.5rem;
} width: 8px;
padding: 2px;
cursor: pointer;
position: absolute;
left: -9px;
top: 6px;
@include opacity(0.7);
&:hover {
@include opacity(1);
}
}
.#{$nv-prefix}item .#{$nv-prefix}children .#{$nv-prefix}title{ &-title {
border-left: 1px solid lighten($mainDkColor,2%); @extend .#{$app-prefix}category-title;
}
.#{$nv-prefix}item > .#{$nv-prefix}children {
display: none;
}
.#{$nv-prefix}item.open > .#{$nv-prefix}children {
display: block;
}
.#{$nv-prefix}item > .#{$nv-prefix}no-chld > ##{$nv-prefix}caret::before{ padding: 3px 10px 5px 30px;
content:''; display: flex;
} align-items: center;
.#{$nv-prefix}no-chld > .#{$nv-prefix}title-inn > ##{$nv-prefix}caret { &-inn {
display:none; position: relative;
} }
}
.#{$nv-prefix}item > ##{$nv-prefix}move { &-name {
position: absolute; padding: 5px;
cursor: move; display: inline-block;
font-size: 12px; box-sizing: content-box;
right: 0; top: 0; @extend .#{$app-prefix}no-user-select;
padding: 7px 10px 7px 5px; }
}
/*
.#{$nv-prefix}item{
&.#{$nv-prefix}selected{
border: 2px solid $colorBlue;
}
}
*/
.#{$nv-prefix}selected .#{$nv-prefix}title {
background-color: rgba(255,255,255,0.1);
}
.#{$nv-prefix}nav-item-edit { > .#{$nv-prefix}layer-children {
visibility: hidden; display: none;
padding: 5px; }
font-size: 9px;
position: absolute;
left: -27px;
top: 1px;
@include opacity(0.7); &.open > .#{$nv-prefix}layer-children {
display: block;
}
&:hover { &-no-chld > .#{$nv-prefix}layer-title-inn > .#{$nv-prefix}layer-caret {
@include opacity(1); display: none;
} }
}
.#{$nv-prefix}title-c:hover { &-move {
padding: 7px 10px 7px 5px;
position: absolute;
font-size: 12px;
cursor: move;
right: 0;
top: 0;
}
.#{$nv-prefix}nav-item-edit { &.#{$nv-prefix}selected .#{$nv-prefix}layer-title {
visibility: visible; background-color: rgba(255, 255, 255, 0.1);
cursor: pointer; }
} }
} }
.#{$app-prefix}nav-comp-name {
padding: 5px; .#{$app-prefix}layers {
box-sizing: content-box; position: relative;
@extend .#{$app-prefix}no-user-select; height: 100%;
##{$nv-prefix}placeholder {
width: 100%;
position: absolute;
##{$nv-prefix}plh-int {
height: 100%;
padding: 1px;
&.#{$nv-prefix}insert {
background-color: $colorGreen;
}
}
}
} }

71
src/styles/scss/_gjs_panels.scss

@ -0,0 +1,71 @@
.#{$pn-prefix} {
&panel {
display: inline-block;
position: absolute;
box-sizing: border-box;
text-align: center;
padding: 5px;
z-index: 3;
.icon-undo,
.icon-redo {
font-size: 20px;
height: 30px;
width: 25px;
}
}
&commands {
width: (100% - $leftWidth);
left: 0;
top: 0;
box-shadow: 0 0 5px $mainDkColor;
}
&options {
right: $leftWidth;
top: 0;
}
&views {
border-bottom: 2px solid $mainDkColor;
right: 0;
width: $leftWidth;
z-index: 4;
&-container {
height: 100%;
padding: 42px 0 0;
right: 0;
width: $leftWidth;
overflow: auto;
box-shadow: 0 0 5px $mainDkColor;
}
}
&buttons {
align-items: center;
display: flex;
justify-content: space-between;
}
&btn {
box-sizing: border-box;
height: 30px;
width: 30px;
line-height: 21px;
background-color: transparent;
border: none;
font-size: 18px;
margin-right: 5px;
border-radius: 2px;
padding: 5px;
position: relative;
cursor: pointer;
&.#{$pn-prefix}active {
background-color: rgba(0, 0, 0, 0.15);
box-shadow: 0 0 3px rgba(0, 0, 0, 0.25) inset;
}
}
}

91
src/styles/scss/_gjs_selectors.scss

@ -0,0 +1,91 @@
.#{$clm-prefix}field {
@extend .#{$sm-prefix}field
}
.#{$clm-prefix}select {
@extend .#{$sm-prefix}field.#{$sm-prefix}select;
}
.#{$clm-prefix}tags {
@extend .#{$sm-prefix}sector;
font-size: $fontSizeS;
padding: 10px 5px;
##{$clm-prefix}label,
##{$clm-prefix}sel {
padding: 7px 0;
float: left;
}
##{$clm-prefix}sel {
font-style: italic;
margin-left: 5px;
}
##{$clm-prefix}status-c {
float: right;
}
##{$clm-prefix}tags-field {
clear: both;
padding: 5px;
margin-bottom: 5px;
}
##{$clm-prefix}tags-c {
display: inline-block;
vertical-align: top;
}
##{$clm-prefix}add-tag {
background-color: rgba(255, 255, 255, 0.15);
border-radius: 2px;
padding: $paddElClm;
box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.2) inset;
border: 1px solid rgba(0, 0, 0, 0.15);
cursor: pointer;
}
##{$clm-prefix}new {
@extend .#{$app-prefix}invis-invis;
color: $fontColor;
padding: $paddElClm;
display: none;
}
.#{$clm-prefix}tag {
display: inline-block;
border-radius: 3px;
margin: 0 3px 3px 0;
padding: 5px;
cursor: default;
}
##{$clm-prefix}close {
@extend .opac50;
font-size: 20px;
line-height: 0;
cursor: pointer;
color: rgba(255, 255, 255, 0.9);
@extend .no-select;
&:hover {
@include opacity(0.7);
}
}
##{$clm-prefix}checkbox {
color: rgba(255, 255, 255, 0.9);
vertical-align: middle;
cursor: pointer;
font-size: 9px;
}
##{$clm-prefix}tag-label {
padding: 0 3px;
cursor: text;
}
}

4
src/styles/scss/_gjs_style_manager.scss

@ -1,19 +1,17 @@
.#{$sm-prefix} { .#{$sm-prefix} {
&clear { &clear {
font-size: 1rem;
line-height: 0; line-height: 0;
cursor: pointer; cursor: pointer;
} }
&header { &header {
font-size: 11px;
font-weight: lighter; font-weight: lighter;
padding: 10px; padding: 10px;
} }
&properties { &properties {
font-size: 11px; font-size: $fontSizeS;
padding: 10px 5px; padding: 10px 5px;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;

29
src/styles/scss/_gjs_traits.scss

@ -0,0 +1,29 @@
.#{$app-prefix} {
&traits-label {
border-bottom: 1px solid $mainDkColor;
font-weight: lighter;
margin-bottom: 5px;
padding: 10px;
text-align: left;
}
}
.#{$trt-prefix}trait {
display: flex;
justify-content: start;
padding: 5px 10px;
font-weight: lighter;
&s {
font-size: $fontSizeS;
}
.#{$app-prefix}label {
width: 30%;
text-align: left;
}
.#{$app-prefix}field {
width: 70%;
}
}

11
src/styles/scss/_gjs_variables.scss

@ -1,7 +1,7 @@
/* Class names prefixes */ /* Class names prefixes */
$app-prefix: 'gjs-' !default; $app-prefix: 'gjs-' !default;
$nv-prefix: $app-prefix + 'nv-' !default; $nv-prefix: $app-prefix !default;
$rte-prefix: $app-prefix + 'rte-' !default; $rte-prefix: $app-prefix + 'rte-' !default;
$comp-prefix: $app-prefix + 'comp-' !default; $comp-prefix: $app-prefix + 'comp-' !default;
$mdl-prefix: $app-prefix + 'mdl-' !default; $mdl-prefix: $app-prefix + 'mdl-' !default;
@ -29,12 +29,6 @@ $mainColor: #444 !default; /* Light: #573454 Dark: #3b2639 -moz-linear-g
$fontColor: #ddd !default; /* l: #d8d7db */ $fontColor: #ddd !default; /* l: #d8d7db */
$fontColorActive: #f8f8f8 !default; $fontColorActive: #f8f8f8 !default;
/* Light theme
$mainColor: #fff;
$fontColor: #9299a3;
$fontColorActive: #4f8ef7;
*/
$mainDkColor: rgba(0, 0, 0, 0.2) !default;/* darken($mainColor, 4%) - #383838 */ $mainDkColor: rgba(0, 0, 0, 0.2) !default;/* darken($mainColor, 4%) - #383838 */
$mainDklColor: rgba(0, 0, 0, 0.1) !default; $mainDklColor: rgba(0, 0, 0, 0.1) !default;
$mainLhColor: rgba(255, 255, 255, 0.1) !default; /* #515151 */ $mainLhColor: rgba(255, 255, 255, 0.1) !default; /* #515151 */
@ -80,4 +74,5 @@ $mainFont: Helvetica, sans-serif !default;
$fontPath: '../fonts' !default; $fontPath: '../fonts' !default;
$fontName: 'main-fonts' !default; $fontName: 'main-fonts' !default;
$fontSize: 0.7rem; $fontSize: 0.7rem;
$fontV: 20 !default;//random(1000) $fontSizeS: 0.75rem;
$fontV: 20 !default;//random(1000)

241
src/styles/scss/main.scss

@ -215,7 +215,7 @@ $prefix: $app-prefix;
.#{$app-prefix}editor { .#{$app-prefix}editor {
font-family: $mainFont; font-family: $mainFont;
font-size: $fontSize; font-size: $fontSizeS;
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
height: 100%; height: 100%;
@ -227,33 +227,7 @@ $prefix: $app-prefix;
pointer-events: none; pointer-events: none;
} }
/************* TRAITS ****************/ @import "gjs_traits";
.#{$app-prefix}traits-label {
border-bottom: 1px solid $mainDkColor;
font-size: 13px;
font-weight: lighter;
margin-bottom: 5px;
padding: 10px;
text-align: left;
}
.#{$trt-prefix}trait {
display: flex;
justify-content: start;
padding: 5px 10px;
font-weight: lighter;
.#{$app-prefix}label {
width: 30%;
text-align: left;
}
.#{$app-prefix}field {
width: 70%;
}
}
/************* CANVAS ****************/
@import "gjs_canvas"; @import "gjs_canvas";
/********* COMMANDS **********/ /********* COMMANDS **********/
@ -330,112 +304,7 @@ $prefix: $app-prefix;
outline: none; outline: none;
} }
/********* PANELS **********/ @import 'gjs_panels';
.#{$pn-prefix}panel {
//@extend .#{$app-prefix}bg-main;
//@extend .#{$app-prefix}color-main;
display: inline-block;
padding: 5px;
position: absolute;
box-sizing: border-box;
text-align: center;
z-index:3;
&##{$pn-prefix}commands{
width: (100% - $leftWidth);
left:0; top: 0;
box-shadow: 0 0 5px $mainDkColor;
}
&##{$pn-prefix}options{
right: $leftWidth;
top: 0;
}
&##{$pn-prefix}options2{
@extend ##{$pn-prefix}commands;
bottom: 150px;
height: auto;
}
.icon-undo, .icon-redo{
font-size: 20px;
height: 30px;
width: 25px;
}
&##{$pn-prefix}views{
border-bottom: 2px solid $mainDkColor;
right: 0;
width: $leftWidth;
z-index: 4;
}
&##{$pn-prefix}views-container{
height: 100%;
padding: 42px 0 0;
right: 0;
width: $leftWidth;
overflow: auto;
box-shadow: 0 0 5px $mainDkColor;
}
}
.#{$pn-prefix}buttons {
align-items: center;
display: flex;
justify-content: space-between;
}
.#{$pn-prefix}btn, .#{$app-prefix}btnt {
box-sizing: border-box;
height: 30px; width: 30px;
line-height: 21px;
background-color: transparent;
border:none;
font-size: 18px;
margin-right: 5px;
border-radius: 2px;
cursor: pointer;
padding: 5px;
position: relative;
&.#{$pn-prefix}active {
background-color: rgba(0, 0, 0, 0.15);
box-shadow: 0 0 3px rgba(0, 0, 0, 0.25) inset;
}
> .#{$pn-prefix}arrow-rd {
border-bottom: 5px solid $mainLhlColor;
border-left: 5px solid transparent;
bottom: 2px; right: 2px;
position: absolute;
}
> .#{$pn-prefix}buttons{
background-color: $mainColor;
border-radius: 2px;
position: absolute;
display: none;
left: 50px;
top: 0;
padding: 5px;
&.#{$pn-prefix}visible{ display: block; }
> .#{$pn-prefix}arrow-l {
border-bottom: 5px solid transparent;
border-right: 5px solid $mainColor;
border-top: 5px solid transparent;
left: -5px; top: 15px;
position: absolute;
}
}
}
/* pa-refresh pa-rocket pa-trash pa-columns pa-rotate-left/right */
.btn.expand{ background-image: none;}
/*********** Components *************/ /*********** Components *************/
@ -474,7 +343,6 @@ $prefix: $app-prefix;
font-weight: lighter; font-weight: lighter;
background-color: $mainDklColor; background-color: $mainDklColor;
font-size: 13px;
letter-spacing: 1px; letter-spacing: 1px;
padding: 9px 10px 9px 20px; padding: 9px 10px 9px 20px;
border-bottom: 1px solid rgba(0, 0, 0, 0.25); border-bottom: 1px solid rgba(0, 0, 0, 0.25);
@ -483,108 +351,11 @@ $prefix: $app-prefix;
cursor: pointer; cursor: pointer;
} }
/********* Style Manager **********/
@import "gjs_style_manager"; @import "gjs_style_manager";
/********* Blocks **********/
@import "gjs_blocks"; @import "gjs_blocks";
/************* Navigator *************/
@import "gjs_layers"; @import "gjs_layers";
@import "gjs_selectors";
/********* Class manager **********/
.#{$clm-prefix}field{
@extend .#{$sm-prefix}field
}
.#{$clm-prefix}select{
@extend .#{$sm-prefix}field.#{$sm-prefix}select;
}
.#{$clm-prefix}tags{
@extend .#{$sm-prefix}sector;
font-size: 11px;
padding: 10px 5px;
##{$clm-prefix}label, ##{$clm-prefix}sel{
padding: 7px 0;
float:left;
}
##{$clm-prefix}sel{
font-style: italic;
margin-left: 5px;
}
##{$clm-prefix}status-c{
float:right;
}
##{$clm-prefix}tags-field{
clear:both;
padding: 5px;
margin-bottom: 5px;
}
##{$clm-prefix}tags-c{
display: inline-block;
vertical-align: top;
}
##{$clm-prefix}add-tag{
background-color: rgba(255, 255, 255, 0.15);
border-radius: 2px;
padding: $paddElClm;
box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.2) inset;
border: 1px solid rgba(0, 0, 0, 0.15);
cursor: pointer;
}
##{$clm-prefix}new {
@extend .#{$app-prefix}invis-invis;
color: $fontColor;
padding: $paddElClm;
display:none;
}
.#{$clm-prefix}tag {
display: inline-block;
border-radius:3px;
margin: 0 3px 3px 0;
padding: 5px;
cursor: default;
}
##{$clm-prefix}close {
@extend .opac50;
font-size: 20px;
line-height: 0;
cursor:pointer;
color: rgba(255, 255, 255, 0.9);
@extend .no-select;
&:hover{
@include opacity(0.7);
}
}
##{$clm-prefix}checkbox {
color: rgba(255, 255, 255, 0.9);
vertical-align: middle;
cursor: pointer;
font-size: 9px;
}
##{$clm-prefix}tag-label {
padding: 0 3px;
cursor: text;
}
}
/********* END Class manager **********/
/********* Modal dialog **********/
@import "gjs_modal"; @import "gjs_modal";
/********* Assets Manager **********/
@import "gjs_assets"; @import "gjs_assets";
/********* File uploader **********/ /********* File uploader **********/
@ -752,3 +523,7 @@ $prefix: $app-prefix;
opacity: 0; opacity: 0;
} }
} }
.cm-s-hopscotch span.cm-error {
color: #ffffff;
}

4
src/trait_manager/config/config.js

@ -1,6 +1,10 @@
module.exports = { module.exports = {
stylePrefix: 'trt-', stylePrefix: 'trt-',
// Specify the element to use as a container, string (query) or HTMLElement
// With the empty value, nothing will be rendered
appendTo: '',
labelContainer: 'Component settings', labelContainer: 'Component settings',
// Placeholder label for text input types // Placeholder label for text input types

20
src/trait_manager/index.js

@ -1,9 +1,10 @@
import { defaults } from 'underscore'; import { defaults, isElement } from 'underscore';
const defaultOpts = require('./config/config');
const TraitsView = require('./view/TraitsView');
module.exports = () => { module.exports = () => {
let c = {}; let c = {};
const defaultOpts = require('./config/config');
const TraitsView = require('./view/TraitsView');
let TraitsViewer; let TraitsViewer;
return { return {
@ -42,6 +43,15 @@ module.exports = () => {
return this; return this;
}, },
postRender() {
const elTo = this.getConfig().appendTo;
if (elTo) {
const el = isElement(elTo) ? elTo : document.querySelector(elTo);
el.appendChild(this.render());
}
},
/** /**
* *
* Get Traits viewer * Get Traits viewer
@ -68,6 +78,10 @@ module.exports = () => {
*/ */
getType(name) { getType(name) {
return TraitsViewer.itemsView[name]; return TraitsViewer.itemsView[name];
},
render() {
return TraitsViewer.render().el;
} }
}; };
}; };

11
src/trait_manager/view/TraitsView.js

@ -16,10 +16,12 @@ module.exports = DomainViews.extend({
color: TraitColorView color: TraitColorView
}, },
initialize(o) { initialize(o = {}) {
this.config = o.config || {}; const config = o.config || {};
this.config = config;
this.em = o.editor; this.em = o.editor;
this.pfx = this.config.stylePrefix || ''; this.pfx = config.stylePrefix || '';
this.ppfx = config.pStylePrefix || '';
this.className = this.pfx + 'traits'; this.className = this.pfx + 'traits';
this.listenTo(this.em, 'change:selectedComponent', this.updatedCollection); this.listenTo(this.em, 'change:selectedComponent', this.updatedCollection);
this.updatedCollection(); this.updatedCollection();
@ -30,7 +32,8 @@ module.exports = DomainViews.extend({
* @private * @private
*/ */
updatedCollection() { updatedCollection() {
this.el.className = this.className; const ppfx = this.ppfx;
this.el.className = `${this.className} ${ppfx}one-bg ${ppfx}two-color`;
var comp = this.em.get('selectedComponent'); var comp = this.em.get('selectedComponent');
if (comp) { if (comp) {
this.collection = comp.get('traits'); this.collection = comp.get('traits');

73
src/utils/Resizer.js

@ -1,4 +1,4 @@
import { bindAll, defaults, isFunction } from 'underscore'; import { bindAll, defaults, isFunction, each } from 'underscore';
import { on, off, normalizeFloat } from 'utils/mixins'; import { on, off, normalizeFloat } from 'utils/mixins';
var defaultOpts = { var defaultOpts = {
@ -38,6 +38,13 @@ var defaultOpts = {
// from the current focused element (currently used only in SelectComponent) // from the current focused element (currently used only in SelectComponent)
currentUnit: 1, currentUnit: 1,
// With this option active the mousemove event won't be altered when
// the pointer comes over iframes
silentFrames: 0,
// If true the container of handlers won't be updated
avoidContainerUpdate: 0,
// Handlers // Handlers
tl: 1, // Top left tl: 1, // Top left
tc: 1, // Top center tc: 1, // Top center
@ -137,6 +144,17 @@ class Resizer {
this.onEnd = opts.onEnd; this.onEnd = opts.onEnd;
} }
/**
* Toggle iframes pointer event
* @param {Boolean} silent If true, iframes will be silented
*/
toggleFrames(silent) {
if (this.opts.silentFrames) {
const frames = document.querySelectorAll('iframe');
each(frames, frame => (frame.style.pointerEvents = silent ? 'none' : ''));
}
}
/** /**
* Detects if the passed element is a resize handler * Detects if the passed element is a resize handler
* @param {HTMLElement} el * @param {HTMLElement} el
@ -170,11 +188,12 @@ class Resizer {
/** /**
* Return element position * Return element position
* @param {HTMLElement} el * @param {HTMLElement} el
* @param {Object} opts Custom options
* @return {Object} * @return {Object}
*/ */
getElementPos(el) { getElementPos(el, opts = {}) {
var posFetcher = this.posFetcher || ''; var posFetcher = this.posFetcher || '';
return posFetcher ? posFetcher(el) : getBoundingRect(el); return posFetcher ? posFetcher(el, opts) : getBoundingRect(el);
} }
/** /**
@ -189,15 +208,19 @@ class Resizer {
// Show the handlers // Show the handlers
this.el = el; this.el = el;
var unit = 'px'; const config = this.opts;
var rect = this.getElementPos(el); const unit = 'px';
var container = this.container; const rect = this.getElementPos(el, { target: 'container' });
var contStyle = container.style; const container = this.container;
contStyle.left = rect.left + unit; const contStyle = container.style;
contStyle.top = rect.top + unit;
contStyle.width = rect.width + unit; if (!config.avoidContainerUpdate) {
contStyle.height = rect.height + unit; contStyle.left = rect.left + unit;
container.style.display = 'block'; contStyle.top = rect.top + unit;
contStyle.width = rect.width + unit;
contStyle.height = rect.height + unit;
contStyle.display = 'block';
}
on(this.getDocumentEl(), 'mousedown', this.handleMouseDown); on(this.getDocumentEl(), 'mousedown', this.handleMouseDown);
} }
@ -220,16 +243,14 @@ class Resizer {
*/ */
start(e) { start(e) {
//Right or middel click //Right or middel click
if (e.button !== 0) { if (e.button !== 0) return;
return;
}
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const el = this.el; const el = this.el;
const resizer = this; const resizer = this;
const config = this.opts || {}; const config = this.opts || {};
var attrName = 'data-' + config.prefix + 'handler'; var attrName = 'data-' + config.prefix + 'handler';
var rect = this.getElementPos(el); var rect = this.getElementPos(el, { target: 'el' });
this.handlerAttr = e.target.getAttribute(attrName); this.handlerAttr = e.target.getAttribute(attrName);
this.clickedHandler = e.target; this.clickedHandler = e.target;
this.startDim = { this.startDim = {
@ -256,6 +277,7 @@ class Resizer {
on(doc, 'mouseup', this.stop); on(doc, 'mouseup', this.stop);
isFunction(this.onStart) && isFunction(this.onStart) &&
this.onStart(e, { docs: doc, config, el, resizer }); this.onStart(e, { docs: doc, config, el, resizer });
this.toggleFrames(1);
this.move(e); this.move(e);
} }
@ -307,6 +329,7 @@ class Resizer {
off(doc, 'keydown', this.handleKeyDown); off(doc, 'keydown', this.handleKeyDown);
off(doc, 'mouseup', this.stop); off(doc, 'mouseup', this.stop);
this.updateRect(1); this.updateRect(1);
this.toggleFrames();
isFunction(this.onEnd) && this.onEnd(e, { docs: doc, config }); isFunction(this.onEnd) && this.onEnd(e, { docs: doc, config });
} }
@ -321,7 +344,7 @@ class Resizer {
const conStyle = this.container.style; const conStyle = this.container.style;
const updateTarget = this.updateTarget; const updateTarget = this.updateTarget;
const selectedHandler = this.getSelectedHandler(); const selectedHandler = this.getSelectedHandler();
const { unitHeight, unitWidth } = config; const { unitHeight, unitWidth, keyWidth, keyHeight } = config;
// Use custom updating strategy if requested // Use custom updating strategy if requested
if (isFunction(updateTarget)) { if (isFunction(updateTarget)) {
@ -333,16 +356,18 @@ class Resizer {
}); });
} else { } else {
const elStyle = el.style; const elStyle = el.style;
elStyle.width = rect.w + unitWidth; elStyle[keyWidth] = rect.w + unitWidth;
elStyle.height = rect.h + unitHeight; elStyle[keyHeight] = rect.h + unitHeight;
} }
const unitRect = 'px'; const unitRect = 'px';
const rectEl = this.getElementPos(el); const rectEl = this.getElementPos(el, { target: 'container' });
conStyle.left = rectEl.left + unitRect; if (!config.avoidContainerUpdate) {
conStyle.top = rectEl.top + unitRect; conStyle.left = rectEl.left + unitRect;
conStyle.width = rectEl.width + unitRect; conStyle.top = rectEl.top + unitRect;
conStyle.height = rectEl.height + unitRect; conStyle.width = rectEl.width + unitRect;
conStyle.height = rectEl.height + unitRect;
}
} }
/** /**

17
src/utils/Sorter.js

@ -1,4 +1,4 @@
import { isString } from 'underscore'; import { isString, isFunction } from 'underscore';
import { on, off, matches } from 'utils/mixins'; import { on, off, matches } from 'utils/mixins';
const $ = Backbone.$; const $ = Backbone.$;
@ -670,7 +670,6 @@ module.exports = Backbone.View.extend({
const width = rect.width; const width = rect.width;
const height = rect.height; const height = rect.height;
//console.log(pos, {top, left});
if ( if (
y < top + off || // near top edge y < top + off || // near top edge
y > top + height - off || // near bottom edge y > top + height - off || // near bottom edge
@ -719,8 +718,6 @@ module.exports = Backbone.View.extend({
width = el.offsetWidth; width = el.offsetWidth;
} }
//console.log('get dim', top, left, this.canvasRelative);
return [top, left, height, width]; return [top, left, height, width];
}, },
@ -918,12 +915,11 @@ module.exports = Backbone.View.extend({
var clsReg = new RegExp('(?:^|\\s)' + this.freezeClass + '(?!\\S)', 'gi'); var clsReg = new RegExp('(?:^|\\s)' + this.freezeClass + '(?!\\S)', 'gi');
let src = this.eV; let src = this.eV;
if (src) { if (src && this.selectOnEnd) {
var srcModel = this.getSourceModel(); var srcModel = this.getSourceModel();
if (srcModel && srcModel.set) { if (srcModel && srcModel.set) {
srcModel.set('status', ''); srcModel.set('status', '');
srcModel.set('status', 'selected'); srcModel.set('status', 'selected');
//this.selectOnEnd && srcModel.set('status', 'selected');
} }
} }
@ -932,9 +928,7 @@ module.exports = Backbone.View.extend({
} }
if (this.plh) this.plh.style.display = 'none'; if (this.plh) this.plh.style.display = 'none';
if (isFunction(this.onEndMove)) this.onEndMove(created, this);
if (typeof this.onEndMove === 'function') this.onEndMove(created);
var dragHelper = this.dragHelper; var dragHelper = this.dragHelper;
if (dragHelper) { if (dragHelper) {
@ -974,7 +968,8 @@ module.exports = Backbone.View.extend({
var opts = { at: index, noIncrement: 1 }; var opts = { at: index, noIncrement: 1 };
if (!dropContent) { if (!dropContent) {
modelTemp = targetCollection.add({}, { ...opts, avoidStore: 1 }); // Putting `avoidStore` here will make the UndoManager behave wrong
modelTemp = targetCollection.add({}, { ...opts });
if (model) { if (model) {
modelToDrop = model.collection.remove(model); modelToDrop = model.collection.remove(model);
@ -988,7 +983,7 @@ module.exports = Backbone.View.extend({
created = targetCollection.add(modelToDrop, opts); created = targetCollection.add(modelToDrop, opts);
if (!dropContent) { if (!dropContent) {
targetCollection.remove(modelTemp, { avoidStore: 1 }); targetCollection.remove(modelTemp);
} else { } else {
this.dropContent = null; this.dropContent = null;
} }

8
test/specs/style_manager/view/PropertyCompositeView.js

@ -89,13 +89,13 @@ module.exports = {
}); });
it('Input value is empty', () => { it('Input value is empty', () => {
expect(model.getFullValue()).toEqual('0% val2'); expect(model.getFullValue()).toEqual('0 val2');
}); });
it('Update input on value change', () => { it('Update input on value change', () => {
view.model.set('value', propValue); view.model.set('value', propValue);
// Fetch always values from properties // Fetch always values from properties
expect(view.getInputValue()).toEqual('0% val2'); expect(view.getInputValue()).toEqual('0 val2');
}); });
describe('With target setted', () => { describe('With target setted', () => {
@ -123,7 +123,7 @@ module.exports = {
prop2Val = properties[1].defaults; prop2Val = properties[1].defaults;
prop2Unit = properties[1].units[0]; prop2Unit = properties[1].units[0];
prop3Val = properties[2].list[2].value; prop3Val = properties[2].list[2].value;
finalResult = propValue + ' ' + prop2Val + prop2Unit + ' ' + prop3Val; finalResult = propValue + ' ' + prop2Val + ' ' + prop3Val;
$prop1 = view.$props.find('#' + properties[0].property + ' input'); $prop1 = view.$props.find('#' + properties[0].property + ' input');
$prop2 = view.$props.find('#' + properties[1].property + ' input'); $prop2 = view.$props.find('#' + properties[1].property + ' input');
$prop3 = view.$props.find('#' + properties[2].property + ' select'); $prop3 = view.$props.find('#' + properties[2].property + ' select');
@ -151,7 +151,7 @@ module.exports = {
$prop1.val(propValue).trigger('change'); $prop1.val(propValue).trigger('change');
var compStyle = view.getTarget().get('style'); var compStyle = view.getTarget().get('style');
var assertStyle = {}; var assertStyle = {};
assertStyle[propName] = propValue + ' 0% val2'; assertStyle[propName] = propValue + ' 0 val2';
expect(compStyle).toEqual(assertStyle); expect(compStyle).toEqual(assertStyle);
}); });

Loading…
Cancel
Save