diff --git a/src/dom_components/model/Component.js b/src/dom_components/model/Component.js index d496537bc..1c6feac5f 100644 --- a/src/dom_components/model/Component.js +++ b/src/dom_components/model/Component.js @@ -12,7 +12,7 @@ import { keys, } from 'underscore'; import { shallowDiff, capitalize, isEmptyObj, isObject, toLowerCase } from 'utils/mixins'; -import StyleableModel from 'domain_abstract/model/StyleableModel'; +import StyleableModel from '../../domain_abstract/model/StyleableModel'; import { Model } from 'backbone'; import Components from './Components'; import Selector from 'selector_manager/model/Selector'; @@ -49,7 +49,6 @@ export const keyUpdateInside = `${keyUpdate}-inside`; * * [Component]: component.html * - * @typedef Component * @property {String} [type=''] Component type, eg. `text`, `image`, `video`, etc. * @property {String} [tagName='div'] HTML tag of the component, eg. `span`. Default: `div` * @property {Object} [attributes={}] Key-value object of the component's attributes, eg. `{ title: 'Hello' }` Default: `{}` diff --git a/src/domain_abstract/model/StyleableModel.js b/src/domain_abstract/model/StyleableModel.js index e6004a288..e3270a393 100644 --- a/src/domain_abstract/model/StyleableModel.js +++ b/src/domain_abstract/model/StyleableModel.js @@ -1,12 +1,10 @@ import { isString, isArray, keys, isUndefined } from 'underscore'; import { shallowDiff } from '../../utils/mixins'; import ParserHtml from '../../parser/model/ParserHtml'; -import { Model } from 'common'; - -const parseStyle = ParserHtml().parseStyle; +import { Model } from '../../common'; export default class StyleableModel extends Model { - parseStyle; + parseStyle = ParserHtml().parseStyle; /** * To trigger the style change event on models I have to @@ -36,7 +34,7 @@ export default class StyleableModel extends Model { */ setStyle(prop = {}, opts = {}) { if (isString(prop)) { - prop = parseStyle(prop); + prop = this.parseStyle(prop); } const propOrig = this.getStyle(opts); diff --git a/src/editor/model/Editor.ts b/src/editor/model/Editor.ts index 728412349..c64c074ab 100644 --- a/src/editor/model/Editor.ts +++ b/src/editor/model/Editor.ts @@ -1,48 +1,41 @@ -import { - isUndefined, - isArray, - contains, - toArray, - keys, - bindAll, -} from "underscore"; -import Backbone from "backbone"; -import $ from "../../utils/cash-dom"; -import Extender from "../../utils/extender"; -import { getModel, hasWin, isEmptyObj } from "../../utils/mixins"; -import { Model } from "../../common"; -import Selected from "./Selected"; -import FrameView from "../../canvas/view/FrameView"; -import EditorModule from ".."; -import EditorView from "../view/EditorView"; -import { IModule } from "../../abstract/Module"; +import { isUndefined, isArray, contains, toArray, keys, bindAll } from 'underscore'; +import Backbone from 'backbone'; +import $ from '../../utils/cash-dom'; +import Extender from '../../utils/extender'; +import { getModel, hasWin, isEmptyObj } from '../../utils/mixins'; +import { Model } from '../../common'; +import Selected from './Selected'; +import FrameView from '../../canvas/view/FrameView'; +import EditorModule from '..'; +import EditorView from '../view/EditorView'; +import { IModule } from '../../abstract/Module'; //@ts-ignore Backbone.$ = $; const deps = [ - require("utils"), - require("i18n"), - require("keymaps"), - require("undo_manager"), - require("storage_manager"), - require("device_manager"), - require("parser"), - require("style_manager"), - require("selector_manager"), - require("modal_dialog"), - require("code_manager"), - require("panels"), - require("rich_text_editor"), - require("asset_manager"), - require("css_composer"), - require("pages"), - require("trait_manager"), - require("dom_components"), - require("navigator"), - require("canvas"), - require("commands"), - require("block_manager"), + require('utils'), + require('i18n'), + require('keymaps'), + require('undo_manager'), + require('storage_manager'), + require('device_manager'), + require('parser'), + require('style_manager'), + require('selector_manager'), + require('modal_dialog'), + require('code_manager'), + require('panels'), + require('rich_text_editor'), + require('asset_manager'), + require('css_composer'), + require('pages'), + require('trait_manager'), + require('dom_components'), + require('navigator'), + require('canvas'), + require('commands'), + require('block_manager'), ]; const ts_deps: any[] = []; @@ -74,7 +67,7 @@ export default class EditorModel extends Model { modules: [], toLoad: [], opened: {}, - device: "", + device: '', }; } @@ -88,30 +81,33 @@ export default class EditorModel extends Model { view?: EditorView; get storables(): any[] { - return this.get("storables"); + return this.get('storables'); } get modules(): IModule[] { - return this.get("modules"); + return this.get('modules'); } get toLoad(): any[] { - return this.get("toLoad"); + return this.get('toLoad'); + } + get selected(): Selected { + return this.get('selected'); } constructor(conf = {}) { super(); this._config = conf; const { config } = this; - this.set("Config", conf); - this.set("modules", []); - this.set("toLoad", []); - this.set("storables", []); - this.set("selected", new Selected()); - this.set("dmode", config.dragMode); + this.set('Config', conf); + this.set('modules', []); + this.set('toLoad', []); + this.set('storables', []); + this.set('selected', new Selected()); + this.set('dmode', config.dragMode); const { el, log } = config; const toLog = log === true ? keys(logs) : isArray(log) ? log : []; - bindAll(this, "initBaseColorPicker"); + bindAll(this, 'initBaseColorPicker'); if (el && config.fromElement) { config.components = el.innerHTML; @@ -122,7 +118,7 @@ export default class EditorModel extends Model { res[next.nodeName] = next.nodeValue; return res; }, {}) - : ""; + : ''; // Move components to pages if (config.components && !config.pageManager) { @@ -130,35 +126,27 @@ export default class EditorModel extends Model { } // Load modules - deps.forEach((name) => this.loadModule(name)); - ts_deps.forEach((name) => this.tsLoadModule(name)); - this.on("change:componentHovered", this.componentHovered, this); - this.on("change:changesCount", this.updateChanges, this); - this.on("change:readyLoad change:readyCanvas", this._checkReady, this); - toLog.forEach((e) => this.listenLog(e)); + deps.forEach(name => this.loadModule(name)); + ts_deps.forEach(name => this.tsLoadModule(name)); + this.on('change:componentHovered', this.componentHovered, this); + this.on('change:changesCount', this.updateChanges, this); + this.on('change:readyLoad change:readyCanvas', this._checkReady, this); + toLog.forEach(e => this.listenLog(e)); // Deprecations - [{ from: "change:selectedComponent", to: "component:toggled" }].forEach( - (event) => { - const eventFrom = event.from; - const eventTo = event.to; - this.listenTo(this, eventFrom, (...args) => { - this.trigger(eventTo, ...args); - this.logWarning( - `The event '${eventFrom}' is deprecated, replace it with '${eventTo}'` - ); - }); - } - ); + [{ from: 'change:selectedComponent', to: 'component:toggled' }].forEach(event => { + const eventFrom = event.from; + const eventTo = event.to; + this.listenTo(this, eventFrom, (...args) => { + this.trigger(eventTo, ...args); + this.logWarning(`The event '${eventFrom}' is deprecated, replace it with '${eventTo}'`); + }); + }); } _checkReady() { - if ( - this.get("readyLoad") && - this.get("readyCanvas") && - !this.get("ready") - ) { - this.set("ready", true); + if (this.get('readyLoad') && this.get('readyCanvas') && !this.get('ready')) { + this.set('ready', true); } } @@ -192,15 +180,15 @@ export default class EditorModel extends Model { */ loadOnStart() { const { projectData, headless } = this.config; - const sm = this.get("StorageManager"); + const sm = this.get('StorageManager'); // In `onLoad`, the module will try to load the data from its configurations. - this.toLoad.forEach((mdl) => mdl.onLoad()); + this.toLoad.forEach(mdl => mdl.onLoad()); // Stuff to do post load const postLoad = () => { - this.modules.forEach((mdl) => mdl.postLoad && mdl.postLoad(this)); - this.set("readyLoad", 1); + this.modules.forEach(mdl => mdl.postLoad && mdl.postLoad(this)); + this.set('readyLoad', 1); }; if (headless) { @@ -230,8 +218,8 @@ export default class EditorModel extends Model { undoManager: false, }); // We only need to load a few modules - ["PageManager", "Canvas"].forEach((key) => shallow.get(key).onLoad()); - this.set("shallow", shallow); + ['PageManager', 'Canvas'].forEach(key => shallow.get(key).onLoad()); + this.set('shallow', shallow); } /** @@ -240,18 +228,18 @@ export default class EditorModel extends Model { * @private */ updateChanges() { - const stm = this.get("StorageManager"); + const stm = this.get('StorageManager'); const changes = this.getDirtyCount(); this.updateItr && clearTimeout(this.updateItr); //@ts-ignore - this.updateItr = setTimeout(() => this.trigger("update")); + this.updateItr = setTimeout(() => this.trigger('update')); if (this.config.noticeOnUnload) { window.onbeforeunload = changes ? () => true : null; } if (stm.isAutosave() && changes >= stm.getStepsBeforeSave()) { - this.store().catch((err) => this.logError(err)); + this.store().catch(err => this.logError(err)); } } @@ -266,11 +254,9 @@ export default class EditorModel extends Model { const Module = moduleName.default || moduleName; const Mod = new Module(); const name = Mod.name.charAt(0).toLowerCase() + Mod.name.slice(1); - const cfgParent = !isUndefined(config[name]) - ? config[name] - : config[Mod.name]; + const cfgParent = !isUndefined(config[name]) ? config[name] : config[Mod.name]; const cfg = cfgParent === true ? {} : cfgParent || {}; - cfg.pStylePrefix = config.pStylePrefix || ""; + cfg.pStylePrefix = config.pStylePrefix || ''; if (!isUndefined(cfgParent) && !cfgParent) { cfg._disable = 1; @@ -321,11 +307,11 @@ export default class EditorModel extends Model { this.initialize(opts); this.destroyed = false; } - this.set("Editor", editor); + this.set('Editor', editor); } getEditor() { - return this.get("Editor"); + return this.get('Editor'); } /** @@ -338,13 +324,7 @@ export default class EditorModel extends Model { * */ handleUpdates(model: any, val: any, opt: any = {}) { // Component has been added temporarily - do not update storage or record changes - if ( - this.__skip || - opt.temporary || - opt.noCount || - opt.avoidStore || - !this.get("ready") - ) { + if (this.__skip || opt.temporary || opt.noCount || opt.avoidStore || !this.get('ready')) { return; } @@ -353,7 +333,7 @@ export default class EditorModel extends Model { this.timedInterval = setTimeout(() => { const curr = this.getDirtyCount() || 0; const { unset, ...opts } = opt; - this.set("changesCount", curr + 1, opts); + this.set('changesCount', curr + 1, opts); }, 0); } @@ -369,9 +349,9 @@ export default class EditorModel extends Model { * @private * */ componentHovered(editor: any, component: any, options: any) { - const prev = this.previous("componentHovered"); - prev && this.trigger("component:unhovered", prev, options); - component && this.trigger("component:hovered", component, options); + const prev = this.previous('componentHovered'); + prev && this.trigger('component:unhovered', prev, options); + component && this.trigger('component:hovered', component, options); } /** @@ -380,7 +360,7 @@ export default class EditorModel extends Model { * @public */ getSelected() { - return this.get("selected").lastComponent(); + return this.selected.lastComponent(); } /** @@ -388,8 +368,8 @@ export default class EditorModel extends Model { * @return {Array} * @public */ - getSelectedAll(): any[] { - return this.get("selected").allComponents(); + getSelectedAll() { + return this.selected.allComponents(); } /** @@ -402,7 +382,7 @@ export default class EditorModel extends Model { const { event } = opts; const ctrlKey = event && (event.ctrlKey || event.metaKey); const { shiftKey } = event || {}; - const els = (isArray(el) ? el : [el]).map((el) => getModel(el, $)); + const els = (isArray(el) ? el : [el]).map(el => getModel(el, $)); const selected = this.getSelectedAll(); const mltSel = this.getConfig().multipleSelection; let added; @@ -410,20 +390,19 @@ export default class EditorModel extends Model { // If an array is passed remove all selected // expect those yet to be selected const multiple = isArray(el); - multiple && this.removeSelected(selected.filter((s) => !contains(els, s))); + multiple && this.removeSelected(selected.filter(s => !contains(els, s))); - els.forEach((el) => { + els.forEach(el => { let model = getModel(el, undefined); if (model) { - this.trigger("component:select:before", model, opts); + this.trigger('component:select:before', model, opts); // Check for valid selectable - if (!model.get("selectable") || opts.abort) { + if (!model.get('selectable') || opts.abort) { if (opts.useValid) { let parent = model.parent(); - while (parent && !parent.get("selectable")) - parent = parent.parent(); + while (parent && !parent.get('selectable')) parent = parent.parent(); model = parent; } else { return; @@ -435,13 +414,13 @@ export default class EditorModel extends Model { if (ctrlKey && mltSel) { return this.toggleSelected(model); } else if (shiftKey && mltSel) { - this.clearSelection(this.get("Canvas").getWindow()); + this.clearSelection(this.get('Canvas').getWindow()); const coll = model.collection; const index = model.index(); let min: number | undefined, max: number | undefined; // Fin min and max siblings - this.getSelectedAll().forEach((sel) => { + this.getSelectedAll().forEach(sel => { const selColl = sel.collection; const selIndex = sel.index(); if (selColl === coll) { @@ -472,7 +451,7 @@ export default class EditorModel extends Model { return this.addSelected(model); } - !multiple && this.removeSelected(selected.filter((s) => s !== model)); + !multiple && this.removeSelected(selected.filter(s => s !== model)); this.addSelected(model, opts); added = model; }); @@ -488,12 +467,12 @@ export default class EditorModel extends Model { const model = getModel(el, $); const models = isArray(model) ? model : [model]; - models.forEach((model) => { - if (model && !model.get("selectable")) return; - const selected = this.get("selected"); + models.forEach(model => { + if (model && !model.get('selectable')) return; + const { selected } = this; opts.forceChange && this.removeSelected(model, opts); selected.addComponent(model, opts); - model && this.trigger("component:select", model, opts); + model && this.trigger('component:select', model, opts); }); } @@ -504,7 +483,7 @@ export default class EditorModel extends Model { * @public */ removeSelected(el: any, opts = {}) { - this.get("selected").removeComponent(getModel(el, $), opts); + this.selected.removeComponent(getModel(el, $), opts); } /** @@ -517,8 +496,8 @@ export default class EditorModel extends Model { const model = getModel(el, $); const models = isArray(model) ? model : [model]; - models.forEach((model) => { - if (this.get("selected").hasComponent(model)) { + models.forEach(model => { + if (this.selected.hasComponent(model)) { this.removeSelected(model, opts); } else { this.addSelected(model, opts); @@ -533,21 +512,21 @@ export default class EditorModel extends Model { * @private */ setHovered(el: any, opts: any = {}) { - if (!el) return this.set("componentHovered", ""); + if (!el) return this.set('componentHovered', ''); - const ev = "component:hover"; + const ev = 'component:hover'; let model = getModel(el, undefined); if (!model) return; - opts.forceChange && this.set("componentHovered", ""); + opts.forceChange && this.set('componentHovered', ''); this.trigger(`${ev}:before`, model, opts); // Check for valid hoverable - if (!model.get("hoverable")) { + if (!model.get('hoverable')) { if (opts.useValid && !opts.abort) { let parent = model && model.parent(); - while (parent && !parent.get("hoverable")) parent = parent.parent(); + while (parent && !parent.get('hoverable')) parent = parent.parent(); model = parent; } else { return; @@ -555,13 +534,13 @@ export default class EditorModel extends Model { } if (!opts.abort) { - this.set("componentHovered", model, opts); + this.set('componentHovered', model, opts); this.trigger(ev, model, opts); } } getHovered() { - return this.get("componentHovered"); + return this.get('componentHovered'); } /** @@ -572,7 +551,7 @@ export default class EditorModel extends Model { * @public */ setComponents(components: any, opt = {}) { - return this.get("DomComponents").setComponents(components, opt); + return this.get('DomComponents').setComponents(components, opt); } /** @@ -581,13 +560,13 @@ export default class EditorModel extends Model { * @private */ getComponents() { - var cmp = this.get("DomComponents"); - var cm = this.get("CodeManager"); + var cmp = this.get('DomComponents'); + var cm = this.get('CodeManager'); if (!cmp || !cm) return; var wrp = cmp.getComponents(); - return cm.getCode(wrp, "json"); + return cm.getCode(wrp, 'json'); } /** @@ -598,7 +577,7 @@ export default class EditorModel extends Model { * @public */ setStyle(style: any, opt = {}) { - const cssc = this.get("CssComposer"); + const cssc = this.get('CssComposer'); cssc.clear(opt); cssc.getAll().add(style, opt); return this; @@ -621,7 +600,7 @@ export default class EditorModel extends Model { * @private */ getStyle() { - return this.get("CssComposer").getAll(); + return this.get('CssComposer').getAll(); } /** @@ -630,7 +609,7 @@ export default class EditorModel extends Model { * @returns {this} */ setState(value: string) { - this.set("state", value); + this.set('state', value); return this; } @@ -639,7 +618,7 @@ export default class EditorModel extends Model { * @returns {String} */ getState() { - return this.get("state") || ""; + return this.get('state') || ''; } /** @@ -651,15 +630,15 @@ export default class EditorModel extends Model { getHtml(opts: any = {}) { const { config } = this; const { optsHtml } = config; - const js = config.jsInHtml ? this.getJs(opts) : ""; - const cmp = opts.component || this.get("DomComponents").getComponent(); + const js = config.jsInHtml ? this.getJs(opts) : ''; + const cmp = opts.component || this.get('DomComponents').getComponent(); let html = cmp - ? this.get("CodeManager").getCode(cmp, "html", { + ? this.get('CodeManager').getCode(cmp, 'html', { ...optsHtml, ...opts, }) - : ""; - html += js ? `` : ""; + : ''; + html += js ? `` : ''; return html; } @@ -673,21 +652,19 @@ export default class EditorModel extends Model { const config = this.config; const { optsCss } = config; const avoidProt = opts.avoidProtected; - const keepUnusedStyles = !isUndefined(opts.keepUnusedStyles) - ? opts.keepUnusedStyles - : config.keepUnusedStyles; - const cssc = this.get("CssComposer"); - const wrp = opts.component || this.get("DomComponents").getComponent(); - const protCss = !avoidProt ? config.protectedCss : ""; + const keepUnusedStyles = !isUndefined(opts.keepUnusedStyles) ? opts.keepUnusedStyles : config.keepUnusedStyles; + const cssc = this.get('CssComposer'); + const wrp = opts.component || this.get('DomComponents').getComponent(); + const protCss = !avoidProt ? config.protectedCss : ''; const css = wrp && - this.get("CodeManager").getCode(wrp, "css", { + this.get('CodeManager').getCode(wrp, 'css', { cssc, keepUnusedStyles, ...optsCss, ...opts, }); - return wrp ? (opts.json ? css : protCss + css) : ""; + return wrp ? (opts.json ? css : protCss + css) : ''; } /** @@ -696,8 +673,8 @@ export default class EditorModel extends Model { * @public */ getJs(opts: any = {}) { - var wrp = opts.component || this.get("DomComponents").getWrapper(); - return wrp ? this.get("CodeManager").getCode(wrp, "js").trim() : ""; + var wrp = opts.component || this.get('DomComponents').getWrapper(); + return wrp ? this.get('CodeManager').getCode(wrp, 'js').trim() : ''; } /** @@ -706,7 +683,7 @@ export default class EditorModel extends Model { */ async store(options?: any) { const data = this.storeData(); - await this.get("StorageManager").store(data, options); + await this.get('StorageManager').store(data, options); this.clearDirtyCount(); return data; } @@ -716,7 +693,7 @@ export default class EditorModel extends Model { * @public */ async load(options?: any) { - const result = await this.get("StorageManager").load(options); + const result = await this.get('StorageManager').load(options); this.loadData(result); return result; } @@ -725,9 +702,9 @@ export default class EditorModel extends Model { let result = {}; // Sync content if there is an active RTE const editingCmp = this.getEditing(); - editingCmp && editingCmp.trigger("sync:content", { noCount: true }); + editingCmp && editingCmp.trigger('sync:content', { noCount: true }); - this.storables.forEach((m) => { + this.storables.forEach(m => { result = { ...result, ...m.store(1) }; }); return JSON.parse(JSON.stringify(result)); @@ -735,8 +712,8 @@ export default class EditorModel extends Model { loadData(data = {}) { if (!isEmptyObj(data)) { - this.storables.forEach((module) => module.clear()); - this.storables.forEach((module) => module.load(data)); + this.storables.forEach(module => module.clear()); + this.storables.forEach(module => module.load(data)); } return data; } @@ -747,8 +724,8 @@ export default class EditorModel extends Model { * @private */ getDeviceModel() { - var name = this.get("device"); - return this.get("DeviceManager").get(name); + var name = this.get('device'); + return this.get('DeviceManager').get(name); } /** @@ -757,7 +734,7 @@ export default class EditorModel extends Model { * @private */ runDefault(opts = {}) { - var command = this.get("Commands").get(this.config.defaultCommand); + var command = this.get('Commands').get(this.config.defaultCommand); if (!command || this.defaultRunning) return; command.stop(this, this, opts); command.run(this, this, opts); @@ -770,7 +747,7 @@ export default class EditorModel extends Model { * @private */ stopDefault(opts = {}) { - const commands = this.get("Commands"); + const commands = this.get('Commands'); const command = commands.get(this.config.defaultCommand); if (!command || !this.defaultRunning) return; command.stop(this, this, opts); @@ -782,9 +759,9 @@ export default class EditorModel extends Model { * @public */ refreshCanvas(opts: any = {}) { - this.set("canvasOffset", null); - this.set("canvasOffset", this.get("Canvas").getOffset()); - opts.tools && this.trigger("canvas:updateTools"); + this.set('canvasOffset', null); + this.set('canvasOffset', this.get('Canvas').getOffset()); + opts.tools && this.trigger('canvas:updateTools'); } /** @@ -807,8 +784,8 @@ export default class EditorModel extends Model { const device = this.getDeviceModel(); const condition = config.mediaCondition; const preview = config.devicePreviewMode; - const width = device && device.get("widthMedia"); - return device && width && !preview ? `(${condition}: ${width})` : ""; + const width = device && device.get('widthMedia'); + return device && width && !preview ? `(${condition}: ${width})` : ''; } /** @@ -816,15 +793,15 @@ export default class EditorModel extends Model { * @return {Component} */ getWrapper() { - return this.get("DomComponents").getWrapper(); + return this.get('DomComponents').getWrapper(); } setCurrentFrame(frameView: FrameView) { - return this.set("currentFrame", frameView); + return this.set('currentFrame', frameView); } getCurrentFrame(): FrameView { - return this.get("currentFrame"); + return this.get('currentFrame'); } getCurrentFrameModel() { @@ -833,7 +810,7 @@ export default class EditorModel extends Model { getIcon(icon: string) { const icons = this.config.icons || {}; - return icons[icon] || ""; + return icons[icon] || ''; } /** @@ -842,27 +819,27 @@ export default class EditorModel extends Model { * @return {number} */ getDirtyCount(): number { - return this.get("changesCount"); + return this.get('changesCount'); } clearDirtyCount() { - return this.set("changesCount", 0); + return this.set('changesCount', 0); } getZoomDecimal() { - return this.get("Canvas").getZoomDecimal(); + return this.get('Canvas').getZoomDecimal(); } getZoomMultiplier() { - return this.get("Canvas").getZoomMultiplier(); + return this.get('Canvas').getZoomMultiplier(); } setDragMode(value: string) { - return this.set("dmode", value); + return this.set('dmode', value); } t(...args: any[]) { - const i18n = this.get("I18n"); + const i18n = this.get('I18n'); return i18n?.t(...args); } @@ -871,7 +848,7 @@ export default class EditorModel extends Model { * @returns {Boolean} */ inAbsoluteMode() { - return this.get("dmode") === "absolute"; + return this.get('dmode') === 'absolute'; } /** @@ -881,20 +858,20 @@ export default class EditorModel extends Model { const { config, view } = this; const editor = this.getEditor(); const { editors = [] } = config.grapesjs || {}; - const shallow = this.get("shallow"); + const shallow = this.get('shallow'); shallow?.destroyAll(); this.stopListening(); this.stopDefault(); this.modules .slice() .reverse() - .forEach((mod) => mod.destroy()); + .forEach(mod => mod.destroy()); view && view.remove(); this.clear({ silent: true }); this.destroyed = true; - ["_config", "view", "_previousAttributes", "_events", "_listeners"].forEach( + ['_config', 'view', '_previousAttributes', '_events', '_listeners'].forEach( //@ts-ignore - (i) => (this[i] = {}) + i => (this[i] = {}) ); editors.splice(editors.indexOf(editor), 1); //@ts-ignore @@ -902,22 +879,22 @@ export default class EditorModel extends Model { } getEditing() { - const res = this.get("editing"); + const res = this.get('editing'); return (res && res.model) || null; } setEditing(value: boolean) { - this.set("editing", value); + this.set('editing', value); return this; } isEditing() { - return !!this.get("editing"); + return !!this.get('editing'); } log(msg: string, opts: any = {}) { - const { ns, level = "debug" } = opts; - this.trigger("log", msg, opts); + const { ns, level = 'debug' } = opts; + this.trigger('log', msg, opts); level && this.trigger(`log:${level}`, msg, opts); if (ns) { @@ -928,15 +905,15 @@ export default class EditorModel extends Model { } logInfo(msg: string, opts?: any) { - this.log(msg, { ...opts, level: "info" }); + this.log(msg, { ...opts, level: 'info' }); } logWarning(msg: string, opts?: any) { - this.log(msg, { ...opts, level: "warning" }); + this.log(msg, { ...opts, level: 'warning' }); } logError(msg: string, opts?: any) { - this.log(msg, { ...opts, level: "error" }); + this.log(msg, { ...opts, level: 'error' }); } initBaseColorPicker(el: any, opts = {}) { @@ -948,13 +925,13 @@ export default class EditorModel extends Model { //@ts-ignore return $(el).spectrum({ containerClassName: `${ppfx}one-bg ${ppfx}two-color`, - appendTo: elToAppend || "body", + appendTo: elToAppend || 'body', maxSelectionSize: 8, showPalette: true, palette: [], showAlpha: true, - chooseText: "Ok", - cancelText: "⨯", + chooseText: 'Ok', + cancelText: '⨯', ...opts, ...colorPicker, }); @@ -967,7 +944,7 @@ export default class EditorModel extends Model { */ skip(clb: Function) { this.__skip = true; - const um = this.get("UndoManager"); + const um = this.get('UndoManager'); um ? um.skip(clb) : clb(); this.__skip = false; } @@ -981,7 +958,7 @@ export default class EditorModel extends Model { * @private */ data(el: any, name: string, value: any) { - const varName = "_gjs-data"; + const varName = '_gjs-data'; if (!el[varName]) { el[varName] = {}; diff --git a/src/editor/model/Selected.ts b/src/editor/model/Selected.ts index e05e4ef77..067f90a52 100644 --- a/src/editor/model/Selected.ts +++ b/src/editor/model/Selected.ts @@ -1,6 +1,6 @@ import { isArray } from 'underscore'; import { Collection, Model } from '../../common'; -import { Component } from '../../dom_components/model/Component'; +import Component from '../../dom_components/model/Component'; export class Selectable extends Model {} @@ -16,7 +16,7 @@ export default class Selected extends Collection { return this.push(toAdd, opts); } - getComponent(model: Selectable) { + getComponent(model: Selectable): Component { return model.get('component'); } @@ -34,7 +34,7 @@ export default class Selected extends Collection { return this.map(s => this.getComponent(s)).filter(i => i); } - removeComponent(component: Component, opts: any) { + removeComponent(component: Component | Component[], opts: any) { const toRemove = (isArray(component) ? component : [component]).map(c => this.getByComponent(c)); return this.remove(toRemove, opts); } diff --git a/src/selector_manager/config/config.js b/src/selector_manager/config/config.ts similarity index 96% rename from src/selector_manager/config/config.js rename to src/selector_manager/config/config.ts index 6df172400..2464fe1e4 100644 --- a/src/selector_manager/config/config.js +++ b/src/selector_manager/config/config.ts @@ -23,8 +23,7 @@ export default { selectedName: 0, // Icon used to add new selector - iconAdd: - '', + iconAdd: '', // Icon used to sync styles iconSync: @@ -98,8 +97,8 @@ export default { // With this option enabled, also in the second case, the Component will be passed. // This method allows to avoid styling classes directly and make, for example, some // unintended changes below the visible canvas area (when components share same classes) - componentFirst: 0, + componentFirst: false, // Avoid rendering the default Selector Manager UI. - custom: false + custom: false, }; diff --git a/src/selector_manager/index.ts b/src/selector_manager/index.ts index c1a4d3228..9d37f10e3 100644 --- a/src/selector_manager/index.ts +++ b/src/selector_manager/index.ts @@ -72,21 +72,22 @@ * @module SelectorManager */ -import { isString, debounce, isObject, isArray } from "underscore"; -import { isComponent, isRule } from "../utils/mixins"; -import Module from "../abstract/moduleLegacy"; -import { Model, Collection } from "../common"; -import defaults from "./config/config"; -import Selector from "./model/Selector"; -import Selectors from "./model/Selectors"; -import State from "./model/State"; -import ClassTagsView from "./view/ClassTagsView"; -import EditorModel from "../editor/model/Editor"; - -const isId = (str: string) => isString(str) && str[0] == "#"; -const isClass = (str: string) => isString(str) && str[0] == "."; - -export const evAll = "selector"; +import { isString, debounce, isObject, isArray } from 'underscore'; +import { isComponent, isRule } from '../utils/mixins'; +import Module from '../abstract/moduleLegacy'; +import { Model, Collection } from '../common'; +import defaults from './config/config'; +import Selector from './model/Selector'; +import Selectors from './model/Selectors'; +import State from './model/State'; +import ClassTagsView from './view/ClassTagsView'; +import EditorModel from '../editor/model/Editor'; +import Component from '../dom_components/model/Component'; + +const isId = (str: string) => isString(str) && str[0] == '#'; +const isClass = (str: string) => isString(str) && str[0] == '.'; + +export const evAll = 'selector'; export const evPfx = `${evAll}:`; export const evAdd = `${evPfx}add`; export const evUpdate = `${evPfx}update`; @@ -96,14 +97,14 @@ export const evCustom = `${evPfx}custom`; export const evState = `${evPfx}state`; export default class SelectorManager extends Module { - name = "SelectorManager"; + name = 'SelectorManager'; Selector = Selector; Selectors = Selectors; model!: Model; - states!: Collection; + states!: Collection; selectorTags?: ClassTagsView; selected!: Selectors; em!: EditorModel; @@ -139,8 +140,8 @@ export default class SelectorManager extends Module { // Global selectors container this.all = new Selectors(config.selectors); this.selected = new Selectors([], { em, config }); - this.states = new Collection( - config.states.map((state) => new State(state)), + this.states = new Collection( + config.states.map(state => new State(state)), { model: State } ); this.model = new Model({ cFirst: config.componentFirst, _undo: true }); @@ -148,12 +149,10 @@ export default class SelectorManager extends Module { collections: [this.states, this.selected], propagate: [{ entity: this.states, event: this.events.state }], }); - em.on("change:state", (m, value) => em.trigger(evState, value)); - this.model.on("change:cFirst", (m, value) => - em.trigger("selector:type", value) - ); + em.on('change:state', (m, value) => em.trigger(evState, value)); + this.model.on('change:cFirst', (m, value) => em.trigger('selector:type', value)); const listenTo = - "component:toggled component:update:classes change:device styleManager:update selector:state selector:type"; + 'component:toggled component:update:classes change:device styleManager:update selector:state selector:type'; this.model.listenTo(em, listenTo, () => this.__update()); return this; @@ -191,26 +190,16 @@ export default class SelectorManager extends Module { select(value: any, opts = {}) { const targets = Array.isArray(value) ? value : [value]; - const toSelect: any[] = this.em.get("StyleManager").select(targets, opts); + const toSelect: any[] = this.em.get('StyleManager').select(targets, opts); const selTags = this.selectorTags; const res = toSelect - .filter((i) => i) - .map((sel) => - isComponent(sel) - ? sel - : isRule(sel) && !sel.get("selectorsAdd") - ? sel - : sel.getSelectorsString() - ); + .filter(i => i) + .map(sel => (isComponent(sel) ? sel : isRule(sel) && !sel.get('selectorsAdd') ? sel : sel.getSelectorsString())); selTags && selTags.componentChanged({ targets: res }); return this; } - addSelector( - name: string | { name: string; label?: string }, - opts = {}, - cOpts = {} - ): Selector { + addSelector(name: string | { name?: string; label?: string }, opts = {}, cOpts = {}): Selector { let props: any = { ...opts }; if (isObject(name)) { @@ -267,11 +256,11 @@ export default class SelectorManager extends Module { * const selector = selectorManager.add('.my-class'); * console.log(selector.toString()) // `.my-class` * */ - add(props: string | { name: string; label?: string }, opts = {}) { + add(props: string | { name?: string; label?: string }, opts = {}) { const cOpts = isString(props) ? {} : opts; // Keep support for arrays but avoid it in docs if (isArray(props)) { - return props.map((item) => this.addSelector(item, opts, cOpts)); + return props.map(item => this.addSelector(item, opts, cOpts)); } else { return this.addSelector(props, opts, cOpts); } @@ -292,10 +281,10 @@ export default class SelectorManager extends Module { const added: any = []; if (isString(classes)) { - classes = classes.trim().split(" "); + classes = classes.trim().split(' '); } - classes.forEach((name) => added.push(this.addSelector(name))); + classes.forEach(name => added.push(this.addSelector(name))); return added; } @@ -312,12 +301,8 @@ export default class SelectorManager extends Module { // Keep support for arrays but avoid it in docs if (isArray(name)) { const result: Selector[] = []; - const selectors = name - .map((item) => this.getSelector(item)) - .filter((item) => item); - selectors.forEach( - (item) => result.indexOf(item) < 0 && result.push(item) - ); + const selectors = name.map(item => this.getSelector(item)).filter(item => item); + selectors.forEach(item => result.indexOf(item) < 0 && result.push(item)); return result; } else { return this.getSelector(name, type) || null; @@ -377,7 +362,7 @@ export default class SelectorManager extends Module { */ setStates(states: State[], opts?: any) { return this.states.reset( - states.map((state) => new State(state)), + states.map(state => new State(state)), opts ); } @@ -399,10 +384,10 @@ export default class SelectorManager extends Module { * @example * selectorManager.addSelected('.new-class'); */ - addSelected(props: string) { + addSelected(props: string | { name?: string; label?: string }) { const added = this.add(props); // TODO: target should be the one from StyleManager - this.em.getSelectedAll().forEach((target) => { + this.em.getSelectedAll().forEach(target => { target.getSelectors().add(added); }); // TODO: update selected collection @@ -415,8 +400,8 @@ export default class SelectorManager extends Module { * selectorManager.removeSelected('.myclass'); */ removeSelected(selector: any) { - this.em.getSelectedAll().forEach((trg) => { - !selector.get("protected") && trg && trg.getSelectors().remove(selector); + this.em.getSelectedAll().forEach(trg => { + !selector.get('protected') && trg && trg.getSelectors().remove(selector); }); } @@ -428,7 +413,7 @@ export default class SelectorManager extends Module { * console.log(targetsToStyle.map(target => target.getSelectorsString())) */ getSelectedTargets() { - return this.em.get("StyleManager").getSelectedAll(); + return this.em.get('StyleManager').getSelectedAll(); } /** @@ -507,18 +492,15 @@ export default class SelectorManager extends Module { return this.__getCommonSelectors(this.em.getSelectedAll()); } - __getCommonSelectors(components: any[], opts = {}) { - const selectors = components - .map((cmp) => cmp.getSelectors && cmp.getSelectors().getValid(opts)) - .filter(Boolean); + __getCommonSelectors(components: Component[], opts = {}) { + const selectors = components.map(cmp => cmp.getSelectors && cmp.getSelectors().getValid(opts)).filter(Boolean); return this.__common(...selectors); } - __common(...args: any) { + __common(...args: any): Selector[] { if (!args.length) return []; if (args.length === 1) return args[0]; - if (args.length === 2) - return args[0].filter((item: any) => args[1].indexOf(item) >= 0); + if (args.length === 2) return args[0].filter((item: any) => args[1].indexOf(item) >= 0); return ( args diff --git a/src/selector_manager/view/ClassTagsView.js b/src/selector_manager/view/ClassTagsView.ts similarity index 83% rename from src/selector_manager/view/ClassTagsView.js rename to src/selector_manager/view/ClassTagsView.ts index a83f29875..2239bc560 100644 --- a/src/selector_manager/view/ClassTagsView.js +++ b/src/selector_manager/view/ClassTagsView.ts @@ -2,9 +2,15 @@ import { isEmpty, isArray, isString, debounce } from 'underscore'; import { View } from '../../common'; import ClassTagView from './ClassTagView'; import html from 'utils/html'; - -export default class ClassTagsView extends View { - template({ labelInfo, labelHead, iconSync, iconAdd, pfx, ppfx }) { +import EditorModel from '../../editor/model/Editor'; +import SelectorManager from '..'; +import State from '../model/State'; +import Component from '../../dom_components/model/Component'; +import Selector from '../model/Selector'; +import Selectors from '../model/Selectors'; + +export default class ClassTagsView extends View { + template({ labelInfo, labelHead, iconSync, iconAdd, pfx, ppfx }: any) { return `
${labelHead}
@@ -47,7 +53,25 @@ export default class ClassTagsView extends View { }; } - initialize(o = {}) { + $input?: JQuery; + $addBtn?: JQuery; + $classes?: JQuery; + $btnSyncEl?: JQuery; + $states?: JQuery; + $statesC?: JQuery; + em: EditorModel; + target: EditorModel; + module: SelectorManager; + + pfx: string; + ppfx: string; + stateInputId: string; + stateInputC: string; + config: any; + states: State[]; + + constructor(o: any = {}) { + super(o); this.config = o.config || {}; this.pfx = this.config.stylePrefix || ''; this.ppfx = this.config.pStylePrefix || ''; @@ -57,12 +81,12 @@ export default class ClassTagsView extends View { this.states = this.config.states || []; const { em } = this.config; const coll = this.collection; - this.target = this.config.em; - const md = o.module; + this.target = em; + const md = em.get('SelectorManager'); this.module = md; this.em = em; - this.componentChanged = debounce(this.componentChanged.bind(this)); - this.checkSync = debounce(this.checkSync.bind(this)); + this.componentChanged = debounce(this.componentChanged.bind(this), 0); + this.checkSync = debounce(this.checkSync.bind(this), 0); const toList = 'component:toggled component:update:classes'; const toListCls = 'component:update:classes change:state'; this.listenTo(em, toList, this.componentChanged); @@ -75,7 +99,7 @@ export default class ClassTagsView extends View { this.listenTo( md.getAll(), md.events.state, - debounce(() => this.renderStates()) + debounce(() => this.renderStates(), 0) ); this.delegateEvents(); } @@ -88,7 +112,7 @@ export default class ClassTagsView extends View { const selectors = this.getCommonSelectors({ opts }); const state = em.get('state'); const mediaText = em.getCurrentMedia(); - const ruleComponents = []; + const ruleComponents: CSSRule[] = []; const rule = cssC.get(selectors, state, mediaText) || cssC.add(selectors, state, mediaText); let style; @@ -119,7 +143,7 @@ export default class ClassTagsView extends View { * @param {Object} model Removed model * @private */ - tagRemoved(model) { + tagRemoved(model?: State) { this.updateStateVis(); } @@ -128,7 +152,7 @@ export default class ClassTagsView extends View { * @param {Object} model * @private */ - addNew(model) { + addNew(model: State) { this.addToClasses(model); } @@ -138,8 +162,8 @@ export default class ClassTagsView extends View { * @private */ startNewTag() { - this.$addBtn.css({ display: 'none' }); - this.$input.show().focus(); + this.$addBtn?.css({ display: 'none' }); + this.$input?.show().focus(); } /** @@ -148,8 +172,8 @@ export default class ClassTagsView extends View { * @private */ endNewTag() { - this.$addBtn.css({ display: '' }); - this.$input.hide().val(''); + this.$addBtn?.css({ display: '' }); + this.$input?.hide().val(''); } /** @@ -157,10 +181,10 @@ export default class ClassTagsView extends View { * @param {Object} e * @private */ - onInputKeyUp(e) { + onInputKeyUp(e: KeyboardEvent) { if (e.keyCode === 13) { e.preventDefault(); - this.addNewTag(this.$input.val()); + this.addNewTag(this.$input?.val()); } else if (e.keyCode === 27) { this.endNewTag(); } @@ -177,17 +201,18 @@ export default class ClassTagsView extends View { * @param {Object} e * @public */ - componentChanged({ targets } = {}) { + componentChanged({ targets }: any = {}) { this.updateSelection(targets); } - updateSelection(targets) { + updateSelection(targets: Component | Component[]) { let trgs = targets || this.getTargets(); trgs = isArray(trgs) ? trgs : [trgs]; - let selectors = []; + let selectors: Selector[] = []; if (trgs && trgs.length) { selectors = this.getCommonSelectors({ targets: trgs }); + //@ts-ignore TODO This parameters are not in use why do we have them? this.checkSync({ validSelectors: selectors }); } @@ -197,12 +222,12 @@ export default class ClassTagsView extends View { return selectors; } - getCommonSelectors({ targets, opts = {} } = {}) { + getCommonSelectors({ targets, opts = {} }: any = {}) { const trgs = targets || this.getTargets(); return this.module.__getCommonSelectors(trgs, opts); } - _commonSelectors(...args) { + _commonSelectors(...args: any) { return this.module.__common(...args); } @@ -232,12 +257,12 @@ export default class ClassTagsView extends View { * inside collection * @private */ - updateStateVis(target) { + updateStateVis(targets?: Component[] | Component) { const em = this.em; const avoidInline = em && em.getConfig().avoidInlineStyle; const display = this.collection.length || avoidInline ? '' : 'none'; this.getStatesC().css('display', display); - this.updateSelector(target); + this.updateSelector(targets); } __handleStateChange() { @@ -249,9 +274,9 @@ export default class ClassTagsView extends View { * @return {this} * @private */ - updateSelector(targets) { + updateSelector(targets?: Component[] | Component) { const elSel = this.el.querySelector('[data-selected]'); - const result = []; + const result: string[] = []; let trgs = targets || this.getTargets(); trgs = isArray(trgs) ? trgs : [trgs]; @@ -260,7 +285,7 @@ export default class ClassTagsView extends View { this.checkStates(); } - __getName(target) { + __getName(target: Component): string { const { pfx, config, em } = this; const { selectedName, componentFirst } = config; let result; @@ -268,15 +293,15 @@ export default class ClassTagsView extends View { if (isString(target)) { result = html`${target}`; } else { - const sel = target && target.get && target.getSelectors(); - if (!sel) return; + const sel = target?.getSelectors(); + if (!sel) return ''; const selectors = sel.getStyleable(); const state = em.get('state'); const idRes = target.getId ? html`${target.getName()} #${target.getId()}` : ''; - result = this.collection.getFullString(selectors); + result = (this.collection as Selectors).getFullString(selectors); result = result ? html`${result}` : target.get('selectorsAdd') || idRes; result = componentFirst && idRes ? idRes : result; result += state ? html`:${state}` : ''; @@ -291,7 +316,7 @@ export default class ClassTagsView extends View { * @param {Object} e * @private */ - stateChanged(ev) { + stateChanged(ev: any) { const { em } = this; const { value } = ev.target; em.set('state', value); @@ -302,7 +327,7 @@ export default class ClassTagsView extends View { * @param {Object} e * @private */ - addNewTag(value) { + addNewTag(value: any) { const label = value.trim(); if (!label) return; this.module.addSelected({ label }); @@ -317,7 +342,7 @@ export default class ClassTagsView extends View { * @return {Object} Object created * @private * */ - addToClasses(model, fragmentEl = null) { + addToClasses(model: State, fragmentEl?: DocumentFragment) { const fragment = fragmentEl; const classes = this.getClasses(); const rendered = new ClassTagView({