Browse Source

Refactor for headless feature

pull/3671/head
Artur Arseniev 5 years ago
parent
commit
0a12930eb3
  1. 41
      src/asset_manager/index.js
  2. 9
      src/canvas/index.js
  3. 7
      src/commands/view/OpenAssets.js
  4. 3
      src/commands/view/OpenTraitManager.js
  5. 11
      src/css_composer/index.js
  6. 12
      src/device_manager/index.js
  7. 17
      src/editor/index.js
  8. 3
      src/i18n/index.js
  9. 9
      src/index.js
  10. 11
      src/modal_dialog/index.js
  11. 19
      src/navigator/index.js
  12. 13
      src/panels/index.js
  13. 3
      src/rich_text_editor/index.js
  14. 26
      src/selector_manager/index.js
  15. 10
      src/selector_manager/view/ClassTagsView.js
  16. 13
      src/style_manager/index.js
  17. 3
      src/style_manager/model/PropertyInteger.js
  18. 1
      src/style_manager/view/SectorsView.js
  19. 40
      src/trait_manager/index.js
  20. 14
      src/trait_manager/view/TraitsView.js
  21. 3
      test/specs/grapesjs/headless.js

41
src/asset_manager/index.js

@ -37,7 +37,7 @@ import FileUpload from './view/FileUploader';
export default () => {
let c = {};
let assets, am, fu;
let assets, assetsVis, am, fu;
return {
/**
@ -79,15 +79,7 @@ export default () => {
// Global assets collection
assets = new Assets([]);
const obj = {
// Collection visible in asset manager
collection: new Assets([]),
globalCollection: assets,
config: c
};
fu = new FileUpload(obj);
obj.fu = fu;
am = new AssetsView(obj);
assetsVis = new Assets([]);
// Setup the sync between the global and public collections
assets.listenTo(assets, 'add', model => {
@ -159,7 +151,7 @@ export default () => {
* @return {Collection}
*/
getAllVisible() {
return am.collection;
return assetsVis;
},
/**
@ -251,12 +243,25 @@ export default () => {
*/
render(assets) {
const toRender = assets || this.getAll().models;
fu && fu.remove();
am && am.remove();
if (!am) {
const obj = {
collection: assetsVis, // Collection visible in asset manager
globalCollection: assets,
config: c
};
fu = new FileUpload(obj);
obj.fu = fu;
am = new AssetsView(obj);
}
if (!am.rendered) {
am.render();
}
am.collection.reset(toRender);
assetsVis.reset(toRender);
return this.getContainer();
},
@ -310,7 +315,7 @@ export default () => {
},
postRender(editorView) {
c.dropzone && fu.initDropzone(editorView);
c.dropzone && fu && fu.initDropzone(editorView);
},
/**
@ -319,7 +324,7 @@ export default () => {
* @private
* */
setTarget(m) {
am.collection.target = m;
assetsVis.target = m;
},
/**
@ -328,7 +333,7 @@ export default () => {
* @private
* */
onSelect(f) {
am.collection.onSelect = f;
assetsVis.onSelect = f;
},
/**
@ -351,9 +356,9 @@ export default () => {
destroy() {
assets.reset();
fu.collection.reset();
fu.remove();
am.remove();
assetsVis.reset();
fu && fu.remove();
am && am.remove();
[assets, am, fu].forEach(i => (i = null));
c = {};
}

9
src/canvas/index.js

@ -80,10 +80,6 @@ export default () => {
onLoad() {
this.model.init();
CanvasView = new canvasView({
model: canvas,
config: c
});
},
getModel() {
@ -260,6 +256,11 @@ export default () => {
* @private
* */
render() {
CanvasView && CanvasView.remove();
CanvasView = new canvasView({
model: canvas,
config: c
});
return CanvasView.render().el;
},

7
src/commands/view/OpenAssets.js

@ -3,7 +3,6 @@ export default {
const modal = editor.Modal;
const am = editor.AssetManager;
const config = am.getConfig();
const amContainer = am.getContainer();
const title = opts.modalTitle || editor.t('assetManager.modalTitle') || '';
const types = opts.types;
const accept = opts.accept;
@ -21,11 +20,11 @@ export default {
}
am.render(assets);
this.rendered = 1;
this.rendered = am.getContainer();
}
if (accept) {
const uploadEl = amContainer.querySelector(
const uploadEl = this.rendered.querySelector(
`input#${config.stylePrefix}uploadFile`
);
uploadEl && uploadEl.setAttribute('accept', accept);
@ -34,7 +33,7 @@ export default {
modal
.open({
title,
content: amContainer
content: this.rendered
})
.getModel()
.once('change:open', () => editor.stopCommand(this.id));

3
src/commands/view/OpenTraitManager.js

@ -13,7 +13,6 @@ export default {
var panelC;
if (!this.$cn) {
var tmView = tm.getTraitsViewer();
var confTm = tm.getConfig();
this.$cn = $('<div></div>');
this.$cn2 = $('<div></div>');
@ -27,7 +26,7 @@ export default {
this.$cn2.append(
`<div class="${pfx}traits-label">${em.t('traitManager.label')}</div>`
);
this.$cn2.append(tmView.render().el);
this.$cn2.append(tm.render());
var panels = editor.Panels;
if (!panels.getPanel('views-container'))

11
src/css_composer/index.js

@ -86,10 +86,6 @@ export default () => {
em = c.em;
rules = new CssRules([], c);
rulesView = new CssRulesView({
collection: rules,
config: c
});
return this;
},
@ -479,13 +475,18 @@ export default () => {
* @private
*/
render() {
rulesView && rulesView.remove();
rulesView = new CssRulesView({
collection: rules,
config: c
});
return rulesView.render().el;
},
destroy() {
rules.reset();
rules.stopListening();
rulesView.remove();
rulesView && rulesView.remove();
[em, rules, rulesView].forEach(i => (i = null));
c = {};
}

12
src/device_manager/index.js

@ -60,10 +60,7 @@ export default () => {
devices = new Devices();
(c.devices || []).forEach(dv => this.add(dv.id || dv.name, dv.width, dv));
view = new DevicesView({
collection: devices,
config: c
});
return this;
},
@ -123,13 +120,18 @@ export default () => {
* @private
*/
render() {
view && view.remove();
view = new DevicesView({
collection: devices,
config: c
});
return view.render().el;
},
destroy() {
devices.reset();
devices.stopListening();
view.remove();
view && view.remove();
[devices, view].forEach(i => (i = null));
c = {};
}

17
src/editor/index.js

@ -123,11 +123,8 @@ export default (config = {}) => {
};
c.pStylePrefix = c.stylePrefix;
var em = new EditorModel(c);
var editorView = new EditorView({
model: em,
config: c
});
let em = new EditorModel(c);
let editorView;
return {
$,
@ -691,7 +688,7 @@ export default (config = {}) => {
* @private
*/
getEl() {
return editorView.el;
return editorView && editorView.el;
},
/**
@ -708,8 +705,12 @@ export default (config = {}) => {
* @return {HTMLElement}
*/
render() {
editorView.render();
return editorView.el;
editorView && editorView.remove();
editorView = new EditorView({
model: em,
config: c
});
return editorView.render().el;
},
/**

3
src/i18n/index.js

@ -27,6 +27,7 @@
* @module I18n
*/
import { isUndefined, isString } from 'underscore';
import { hasWin } from 'utils/mixins';
import config from './config';
const isObj = el => !Array.isArray(el) && el !== null && typeof el === 'object';
@ -210,7 +211,7 @@ export default () => {
},
_localLang() {
const nav = window.navigator || {};
const nav = (hasWin() && window.navigator) || {};
const lang = nav.language || nav.userLanguage;
return lang ? lang.split('-')[0] : 'en';
},

9
src/index.js

@ -36,6 +36,7 @@ export default {
* @param {Boolean} [config.autorender=true] If true, auto-render the content
* @param {Array} [config.plugins=[]] Array of plugins to execute on start
* @param {Object} [config.pluginsOpts={}] Custom options for plugins
* @param {Boolean} [config.headless=false] Init headless editor
* @return {Editor} Editor instance
* @example
* var editor = grapesjs.init({
@ -45,10 +46,12 @@ export default {
* })
*/
init(config = {}) {
const { headless } = config;
const els = config.container;
if (!els) throw new Error("'container' is required");
if (!els && !headless) throw new Error("'container' is required");
config = { ...defaultConfig, ...config, grapesjs: this };
config.el = isElement(els) ? els : document.querySelector(els);
config.el =
!headless && (isElement(els) ? els : document.querySelector(els));
const editor = new Editor(config).init();
const em = editor.getModel();
@ -79,7 +82,7 @@ export default {
// A plugin might have extended/added some custom type so this
// is a good point to load stuff like components, css rules, etc.
em.loadOnStart();
config.autorender && editor.render();
config.autorender && !headless && editor.render();
editors.push(editor);
return editor;

11
src/modal_dialog/index.js

@ -69,10 +69,6 @@ export default () => {
model = new ModalM(c);
model.on('change:open', (m, enb) => triggerEvent(enb, em));
modal = new ModalView({
model,
config: c
});
return this;
},
@ -201,11 +197,16 @@ export default () => {
* @private
*/
render() {
modal && modal.remove();
modal = new ModalView({
model,
config: c
});
return modal.render().$el;
},
destroy() {
modal.remove();
modal && modal.remove();
[c, model, modal].forEach(i => (i = {}));
this.em = {};
}

19
src/navigator/index.js

@ -22,14 +22,6 @@ export default () => {
},
onLoad() {
const ItemView = View.extend(config.extend);
layers = new ItemView({
ItemView,
level: 0,
config,
opened: config.opened || {},
model: em.get('DomComponents').getWrapper()
});
em && em.on('component:selected', this.componentChanged);
this.componentChanged();
},
@ -60,7 +52,7 @@ export default () => {
* @return {Component}
*/
getRoot() {
return layers.model;
return layers && layers.model;
},
/**
@ -96,6 +88,15 @@ export default () => {
},
render() {
const ItemView = View.extend(config.extend);
layers && layers.remove();
layers = new ItemView({
ItemView,
level: 0,
config,
opened: config.opened || {},
model: em.get('DomComponents').getWrapper()
});
return layers.render().el;
},

13
src/panels/index.js

@ -57,10 +57,6 @@ export default () => {
if (ppfx) c.stylePrefix = ppfx + c.stylePrefix;
panels = new Panels(c.defaults);
PanelsViewObj = new PanelsView({
collection: panels,
config: c
});
return this;
},
@ -77,7 +73,7 @@ export default () => {
* @return {HTMLElement}
*/
getPanelsEl() {
return PanelsViewObj.el;
return PanelsViewObj && PanelsViewObj.el;
},
/**
@ -205,6 +201,11 @@ export default () => {
* @private
*/
render() {
PanelsViewObj && PanelsViewObj.remove();
PanelsViewObj = new PanelsView({
collection: panels,
config: c
});
return PanelsViewObj.render().el;
},
@ -235,7 +236,7 @@ export default () => {
destroy() {
panels.reset();
panels.stopListening();
PanelsViewObj.remove();
PanelsViewObj && PanelsViewObj.remove();
[c, panels, PanelsViewObj].forEach(i => (i = {}));
},

3
src/rich_text_editor/index.js

@ -27,7 +27,7 @@
*/
import RichTextEditor from './model/RichTextEditor';
import { on, off } from 'utils/mixins';
import { on, hasWin } from 'utils/mixins';
import defaults from './config/config';
export default () => {
@ -75,6 +75,7 @@ export default () => {
this.pfx = config.stylePrefix;
actions = config.actions || [];
if (!hasWin()) return this;
toolbar = document.createElement('div');
toolbar.className = `${ppfx}rte-toolbar ${ppfx}one-bg`;
globalRte = this.initRte(document.createElement('div'));

26
src/selector_manager/index.js

@ -99,11 +99,6 @@ export default config => {
c.stylePrefix = ppfx + c.stylePrefix;
}
this.selectorTags = new ClassTagsView({
collection: new Selectors([], { em, config: c }),
config: c
});
// Global selectors container
selectors = new Selectors(c.selectors);
selectors.on('add', model => em.trigger('selector:add', model));
@ -133,6 +128,7 @@ export default config => {
select(value, opts = {}) {
const targets = Array.isArray(value) ? value : [value];
const toSelect = this.em.get('StyleManager').setTarget(targets, opts);
const selTags = this.selectorTags;
const res = toSelect
.filter(i => i)
.map(sel =>
@ -142,7 +138,7 @@ export default config => {
? sel
: sel.getSelectorsString()
);
this.selectorTags.componentChanged({ targets: res });
selTags && selTags.componentChanged({ targets: res });
return this;
},
@ -305,19 +301,21 @@ export default config => {
* @private
*/
render(selectors) {
if (selectors) {
this.selectorTags = new ClassTagsView({
collection: new Selectors(selectors),
config: c
});
return this.selectorTags.render().el;
} else return this.selectorTags.render().el;
const { em, selectorTags } = this;
selectorTags && selectorTags.remove();
this.selectorTags = new ClassTagsView({
collection: new Selectors(selectors || [], { em, config: c }),
config: c
});
return this.selectorTags.render().el;
},
destroy() {
const { selectorTags } = this;
selectors.reset();
selectors.stopListening();
this.selectorTags.remove();
selectorTags && selectorTags.remove();
[c, selectors].forEach(i => (i = {}));
this.em = {};
this.selectorTags = {};

10
src/selector_manager/view/ClassTagsView.js

@ -67,11 +67,10 @@ export default Backbone.View.extend({
const coll = this.collection;
this.target = this.config.em;
this.em = em;
const emitter = this.getStyleEmitter();
const toList = 'component:toggled component:update:classes';
const toListCls = 'component:update:classes change:state';
this.listenTo(em, toList, this.componentChanged);
this.listenTo(emitter, 'update', this.componentChanged);
this.listenTo(em, 'styleManager:update', this.componentChanged);
this.listenTo(em, toListCls, this.__handleStateChange);
this.listenTo(em, 'styleable:change change:device', this.checkSync); // component:styleUpdate
this.listenTo(coll, 'add', this.addNew);
@ -116,13 +115,6 @@ export default Backbone.View.extend({
});
},
getStyleEmitter() {
const { em } = this;
const sm = em && em.get('StyleManager');
const emitter = sm && sm.getEmitter();
return emitter || {};
},
/**
* Triggered when a tag is removed from collection
* @param {Object} model Removed model

13
src/style_manager/index.js

@ -75,11 +75,6 @@ export default () => {
if (ppfx) c.stylePrefix = ppfx + c.stylePrefix;
properties = new Properties();
sectors = new Sectors([], c);
SectView = new SectorsView({
collection: sectors,
target: c.em,
config: c
});
return this;
},
@ -427,6 +422,12 @@ export default () => {
* @private
* */
render() {
SectView && SectView.remove();
SectView = new SectorsView({
collection: sectors,
target: c.em,
config: c
});
return SectView.render().el;
},
@ -440,7 +441,7 @@ export default () => {
coll.reset();
coll.stopListening();
});
SectView.remove();
SectView && SectView.remove();
[c, properties, sectors, SectView].forEach(i => (i = {}));
this.em = {};
}

3
src/style_manager/model/PropertyInteger.js

@ -1,6 +1,7 @@
import { isUndefined } from 'underscore';
import Property from './Property';
import InputNumber from 'domain_abstract/ui/InputNumber';
import { hasWin } from 'utils/mixins';
export default Property.extend({
defaults: {
@ -25,7 +26,7 @@ export default Property.extend({
Property.callParentInit(Property, this, props, opts);
const unit = this.get('unit');
const units = this.get('units');
this.input = new InputNumber({ model: this });
this.input = hasWin() && new InputNumber({ model: this });
if (units.length && !unit) {
this.set('unit', units[0]);

1
src/style_manager/view/SectorsView.js

@ -114,6 +114,7 @@ export default Backbone.View.extend({
pt.targets = targets.map(t => sm.getModelToStyle(t)).filter(Boolean);
}
pt.trigger('update');
em.trigger('styleManager:update');
},
/**

40
src/trait_manager/index.js

@ -1,14 +1,31 @@
import { defaults, isElement } from 'underscore';
import defaultOpts from './config/config';
import TraitsView from './view/TraitsView';
import TraitView from './view/TraitView';
import TraitSelectView from './view/TraitSelectView';
import TraitCheckboxView from './view/TraitCheckboxView';
import TraitNumberView from './view/TraitNumberView';
import TraitColorView from './view/TraitColorView';
import TraitButtonView from './view/TraitButtonView';
export default () => {
let c = {};
let types = {};
let TraitsViewer;
const typesDef = {
text: TraitView,
number: TraitNumberView,
select: TraitSelectView,
checkbox: TraitCheckboxView,
color: TraitColorView,
button: TraitButtonView
};
return {
TraitsView,
types,
/**
* Name of the module
* @type {String}
@ -33,12 +50,8 @@ export default () => {
c = config;
defaults(c, defaultOpts);
const ppfx = c.pStylePrefix;
types = { ...typesDef };
ppfx && (c.stylePrefix = `${ppfx}${c.stylePrefix}`);
TraitsViewer = new TraitsView({
collection: [],
editor: c.em,
config: c
});
return this;
},
@ -66,8 +79,8 @@ export default () => {
* @param {Object} methods Object representing the trait
*/
addType(name, trait) {
var itemView = TraitsViewer.itemView;
TraitsViewer.itemsView[name] = itemView.extend(trait);
const baseView = types.text;
types[name] = baseView.extend(trait);
},
/**
@ -76,16 +89,23 @@ export default () => {
* @return {Object}
*/
getType(name) {
return TraitsViewer.itemsView[name];
return types[name];
},
render() {
TraitsViewer && TraitsViewer.remove();
TraitsViewer = new TraitsView({
collection: [],
editor: c.em,
config: c
});
TraitsViewer.itemsView = types;
return TraitsViewer.render().el;
},
destroy() {
TraitsViewer.remove();
[c, TraitsViewer].forEach(i => (i = {}));
TraitsViewer && TraitsViewer.remove();
[c, types, TraitsViewer].forEach(i => (i = {}));
}
};
};

14
src/trait_manager/view/TraitsView.js

@ -1,25 +1,11 @@
import DomainViews from 'domain_abstract/view/DomainViews';
import TraitView from './TraitView';
import TraitSelectView from './TraitSelectView';
import TraitCheckboxView from './TraitCheckboxView';
import TraitNumberView from './TraitNumberView';
import TraitColorView from './TraitColorView';
import TraitButtonView from './TraitButtonView';
export default DomainViews.extend({
ns: 'Traits',
itemView: TraitView,
reuseView: 1,
itemsView: {
text: TraitView,
number: TraitNumberView,
select: TraitSelectView,
checkbox: TraitCheckboxView,
color: TraitColorView,
button: TraitButtonView
},
initialize(o = {}) {
const config = o.config || {};
this.config = config;

3
test/specs/grapesjs/headless.js

@ -4,6 +4,7 @@
describe('GrapesJS Headless', () => {
test('Can init editor', () => {
// const editor = grapesjs.init({ headless: true });
const editor = grapesjs.init({ headless: true });
expect(editor).toBeTruthy();
});
});

Loading…
Cancel
Save