diff --git a/src/css_composer/index.js b/src/css_composer/index.js index 4ab15f10b..939c7ae2e 100644 --- a/src/css_composer/index.js +++ b/src/css_composer/index.js @@ -225,14 +225,10 @@ export default () => { if (isString(selectors)) { const sm = em.get('SelectorManager'); const singleSel = selectors.split(',')[0].trim(); - const node = em - .get('Parser') - .parserCss.checkNode({ selectors: singleSel })[0]; + const node = em.get('Parser').parserCss.checkNode({ selectors: singleSel })[0]; slc = sm.get(node.selectors); } - return ( - rules.find(rule => rule.compare(slc, state, width, ruleProps)) || null - ); + return rules.find(rule => rule.compare(slc, state, width, ruleProps)) || null; }, getAll() { @@ -279,9 +275,7 @@ export default () => { isObject(props) && model.set(props, opts); if (updateStyle) { - let styleUpdate = opts.extend - ? { ...model.get('style'), ...style } - : style; + let styleUpdate = opts.extend ? { ...model.get('style'), ...style } : style; model.set('style', styleUpdate, opts); } @@ -330,14 +324,14 @@ export default () => { const { atRuleType, atRuleParams } = opts; const node = em.get('Parser').parserCss.checkNode({ selectors, - style + style, })[0]; const { state, selectorsAdd } = node; const sm = em.get('SelectorManager'); const selector = sm.add(node.selectors); const rule = this.add(selector, state, atRuleParams, { selectorsAdd, - atRule: atRuleType + atRule: atRuleType, }); rule.setStyle(style, opts); return rule; @@ -368,7 +362,7 @@ export default () => { selector && this.get(selector, state, atRuleParams, { selectorsAdd, - atRule: atRuleType + atRule: atRuleType, }) ); }, @@ -388,12 +382,8 @@ export default () => { getRules(selector) { const rules = this.getAll(); if (!selector) return [...rules.models]; - const sels = isString(selector) - ? selector.split(',').map(s => s.trim()) - : selector; - const result = rules.filter( - r => sels.indexOf(r.getSelectors().getFullString()) >= 0 - ); + const sels = isString(selector) ? selector.split(',').map(s => s.trim()) : selector; + const result = rules.filter(r => sels.indexOf(r.getSelectors().getFullString()) >= 0); return result; }, @@ -492,9 +482,9 @@ export default () => { * // Remove by selector * css.remove('.my-cls-2'); */ - remove(rule) { + remove(rule, opts) { const toRemove = isString(rule) ? this.getRules(rule) : rule; - const result = this.getAll().remove(toRemove); + const result = this.getAll().remove(toRemove, opts); return isArray(result) ? result : [result]; }, @@ -531,7 +521,7 @@ export default () => { rulesView && rulesView.remove(); rulesView = new CssRulesView({ collection: rules, - config: c + config: c, }); return rulesView.render().el; }, @@ -542,6 +532,6 @@ export default () => { rulesView && rulesView.remove(); [em, rules, rulesView].forEach(i => (i = null)); c = {}; - } + }, }; }; diff --git a/src/domain_abstract/model/Styleable.js b/src/domain_abstract/model/Styleable.js index 80a5e636d..675cc6806 100644 --- a/src/domain_abstract/model/Styleable.js +++ b/src/domain_abstract/model/Styleable.js @@ -44,6 +44,7 @@ export default { const diff = shallowDiff(propOrig, propNew); keys(diff).forEach(pr => { const em = this.em; + if (opts.noEvent) return; this.trigger(`change:style:${pr}`); if (em) { em.trigger(`styleable:change`, this, pr, opts); @@ -65,7 +66,7 @@ export default { addStyle(prop, value = '', opts = {}) { if (typeof prop == 'string') { prop = { - prop: value + prop: value, }; } else { opts = value || {}; @@ -110,9 +111,7 @@ export default { }, getSelectorsString(opts) { - return this.selectorsToString - ? this.selectorsToString(opts) - : this.getSelectors().getFullString(); + return this.selectorsToString ? this.selectorsToString(opts) : this.getSelectors().getFullString(); }, _validate(attr, opts) { @@ -133,5 +132,5 @@ export default { } return true; - } + }, }; diff --git a/src/editor/model/Editor.js b/src/editor/model/Editor.js index 8c5c5188b..a5c54e77e 100644 --- a/src/editor/model/Editor.js +++ b/src/editor/model/Editor.js @@ -1,12 +1,4 @@ -import { - isUndefined, - isFunction, - isArray, - contains, - toArray, - keys, - bindAll -} from 'underscore'; +import { isUndefined, isFunction, isArray, contains, toArray, keys, bindAll } from 'underscore'; import Backbone from 'backbone'; import $ from 'utils/cash-dom'; import Extender from 'utils/extender'; @@ -37,7 +29,7 @@ const deps = [ require('navigator'), require('canvas'), require('commands'), - require('block_manager') + require('block_manager'), ]; let timedInterval; @@ -45,14 +37,14 @@ let updateItr; Extender({ Backbone: Backbone, - $: Backbone.$ + $: Backbone.$, }); const logs = { debug: console.log, info: console.info, warning: console.warn, - error: console.error + error: console.error, }; export default Backbone.Model.extend({ @@ -69,7 +61,7 @@ export default Backbone.Model.extend({ modules: [], toLoad: [], opened: {}, - device: '' + device: '', }; }, @@ -103,26 +95,18 @@ export default Backbone.Model.extend({ 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') - ) { + if (this.get('readyLoad') && this.get('readyCanvas') && !this.get('ready')) { this.set('ready', true); } }, @@ -206,9 +190,7 @@ export default Backbone.Model.extend({ 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 || {}; const sm = this.get('StorageManager'); cfg.pStylePrefix = config.pStylePrefix || ''; @@ -262,7 +244,7 @@ export default Backbone.Model.extend({ * */ handleUpdates(model, val, opt = {}) { // Component has been added temporarily - do not update storage or record changes - if (opt.temporary || opt.noCount || opt.avoidStore || !this.get('ready')) { + if (this.__skip || opt.temporary || opt.noCount || opt.avoidStore || !this.get('ready')) { return; } @@ -538,7 +520,7 @@ export default Backbone.Model.extend({ exportWrapper, wrapperIsBody, ...optsHtml, - ...opts + ...opts, }) : ''; html += js ? `` : ''; @@ -555,9 +537,7 @@ export default Backbone.Model.extend({ const config = this.config; const { optsCss, wrapperIsBody } = config; const avoidProt = opts.avoidProtected; - const keepUnusedStyles = !isUndefined(opts.keepUnusedStyles) - ? opts.keepUnusedStyles - : config.keepUnusedStyles; + 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 : ''; @@ -568,7 +548,7 @@ export default Backbone.Model.extend({ wrapperIsBody, keepUnusedStyles, ...optsCss, - ...opts + ...opts, }); return wrp ? (opts.json ? css : protCss + css) : ''; }, @@ -580,11 +560,7 @@ export default Backbone.Model.extend({ */ getJs(opts = {}) { var wrp = opts.component || this.get('DomComponents').getWrapper(); - return wrp - ? this.get('CodeManager') - .getCode(wrp, 'js') - .trim() - : ''; + return wrp ? this.get('CodeManager').getCode(wrp, 'js').trim() : ''; }, /** @@ -810,14 +786,9 @@ export default Backbone.Model.extend({ this.stopListening(); this.clear({ silent: true }); this.destroyed = 1; - ['config', 'view', '_previousAttributes', '_events', '_listeners'].forEach( - i => (this[i] = {}) - ); + ['config', 'view', '_previousAttributes', '_events', '_listeners'].forEach(i => (this[i] = {})); editors.splice(editors.indexOf(editor), 1); - hasWin() && - $(config.el) - .empty() - .attr(this.attrsOrig); + hasWin() && $(config.el).empty().attr(this.attrsOrig); }, getEditing() { @@ -874,10 +845,22 @@ export default Backbone.Model.extend({ chooseText: 'Ok', cancelText: 'тип', ...opts, - ...colorPicker + ...colorPicker, }); }, + /** + * Execute actions without triggering the storage and undo manager. + * @param {Function} clb + * @private + */ + skip(clb) { + this.__skip = true; + const um = this.get('UndoManager'); + um ? um.skip(clb) : clb(); + this.__skip = false; + }, + /** * Set/get data from the HTMLElement * @param {HTMLElement} el @@ -898,5 +881,5 @@ export default Backbone.Model.extend({ } else { el[varName][name] = value; } - } + }, }); diff --git a/src/selector_manager/index.js b/src/selector_manager/index.js index 9768096da..bfded716d 100644 --- a/src/selector_manager/index.js +++ b/src/selector_manager/index.js @@ -111,7 +111,7 @@ export default () => { remove: evRemove, removeBefore: evRemoveBefore, state: evState, - custom: evCustom + custom: evCustom, }, /** @@ -138,12 +138,10 @@ export default () => { this.model = new Model({ cFirst: config.componentFirst, _undo: true }); this.__initListen({ collections: [this.states, this.selected], - propagate: [{ entity: this.states, event: this.events.state }] + propagate: [{ entity: this.states, event: this.events.state }], }); - em.on('change:state', (m, value) => em.trigger('selector:state', 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'; this.model.listenTo(em, listenTo, () => this.__update()); @@ -151,7 +149,7 @@ export default () => { return this; }, - __update: debounce(function() { + __update: debounce(function () { this.__trgCustom(); }), @@ -164,7 +162,7 @@ export default () => { return { states: this.getStates(), selected: this.getSelected(), - container + container, }; }, @@ -188,11 +186,7 @@ export default () => { const res = toSelect .filter(i => i) .map(sel => - isComponent(sel) - ? sel - : isRule(sel) && !sel.get('selectorsAdd') - ? sel - : sel.getSelectorsString() + isComponent(sel) ? sel : isRule(sel) && !sel.get('selectorsAdd') ? sel : sel.getSelectorsString() ); selTags && selTags.componentChanged({ targets: res }); return this; @@ -221,9 +215,7 @@ export default () => { const cname = props.name; const config = this.getConfig(); const all = this.getAll(); - const selector = cname - ? this.get(cname, props.type) - : all.where(props)[0]; + const selector = cname ? this.get(cname, props.type) : all.where(props)[0]; if (!selector) { return all.add(props, { ...cOpts, config }); @@ -301,12 +293,8 @@ export default () => { // Keep support for arrays but avoid it in docs if (isArray(name)) { const result = []; - 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; @@ -402,9 +390,7 @@ export default () => { */ removeSelected(selector) { this.em.getSelectedAll().forEach(trg => { - !selector.get('protected') && - trg && - trg.getSelectors().remove(selector); + !selector.get('protected') && trg && trg.getSelectors().remove(selector); }); }, @@ -471,7 +457,7 @@ export default () => { el, collection: this.selected, module: this, - config + config, }); return this.selectorTags.render().el; @@ -495,21 +481,16 @@ export default () => { }, __getCommonSelectors(components, opts = {}) { - const selectors = components - .map(cmp => cmp.getSelectors && cmp.getSelectors().getValid(opts)) - .filter(Boolean); + const selectors = components.map(cmp => cmp.getSelectors && cmp.getSelectors().getValid(opts)).filter(Boolean); return this.__common(...selectors); }, __common(...args) { if (!args.length) return []; if (args.length === 1) return args[0]; - if (args.length === 2) - return args[0].filter(item => args[1].indexOf(item) >= 0); + if (args.length === 2) return args[0].filter(item => args[1].indexOf(item) >= 0); - return args - .slice(1) - .reduce((acc, item) => this.__common(acc, item), args[0]); - } + return args.slice(1).reduce((acc, item) => this.__common(acc, item), args[0]); + }, }; }; diff --git a/src/style_manager/index.js b/src/style_manager/index.js index 0d59bcde1..d24e1535f 100644 --- a/src/style_manager/index.js +++ b/src/style_manager/index.js @@ -339,7 +339,23 @@ export default () => { targets = targets.map(t => this.getModelToStyle(t)); const lastTarget = targets.slice().reverse()[0]; const lastTargetParents = this.getParentRules(lastTarget, em.getState()); - this.model.set({ targets, lastTarget, lastTargetParents }); + let stateTarget = this.__getStateTarget(); + + em.skip(() => { + if (em.getState() && lastTarget?.getState?.()) { + const style = lastTarget.getStyle(); + if (!stateTarget) { + stateTarget = cssc.getAll().add({ selectors: 'gjs-selected', style, important: true }); + } else { + stateTarget.setStyle(style); + } + } else if (stateTarget) { + cssc.remove(stateTarget); + stateTarget = null; + } + }); + + this.model.set({ targets, lastTarget, lastTargetParents, stateTarget }); this.__upProps(opts); return targets; @@ -370,6 +386,10 @@ export default () => { return this.model.get('lastTargetParents') || []; }, + __getStateTarget() { + return this.model.get('stateTarget') || null; + }, + /** * Update selected targets with a custom style. * @param {Object} style Style object @@ -379,6 +399,11 @@ export default () => { */ addStyleTargets(style, opts) { this.getSelectedAll().map(t => t.addStyle(style, opts)); + + // Update state rule + const target = this.getSelected(); + const targetState = this.__getStateTarget(); + target && targetState?.setStyle(target.getStyle(), opts); }, /** diff --git a/src/undo_manager/index.js b/src/undo_manager/index.js index 6fc3eaba2..388216fda 100644 --- a/src/undo_manager/index.js +++ b/src/undo_manager/index.js @@ -34,7 +34,7 @@ export default () => { let beforeCache; const configDef = { maximumStackLength: 500, - trackSelection: 1 + trackSelection: 1, }; const hasSkip = opts => opts.avoidStore || opts.noUndo; const getChanged = obj => Object.keys(obj.changedAttributes()); @@ -59,13 +59,11 @@ export default () => { if (hasUndo) { const undoExc = object.get('_undoexc'); if (isArray(undoExc)) { - if (getChanged(object).some(chn => undoExc.indexOf(chn) >= 0)) - return false; + if (getChanged(object).some(chn => undoExc.indexOf(chn) >= 0)) return false; } if (isBoolean(hasUndo)) return true; if (isArray(hasUndo)) { - if (getChanged(object).some(chn => hasUndo.indexOf(chn) >= 0)) - return true; + if (getChanged(object).some(chn => hasUndo.indexOf(chn) >= 0)) return true; } } return false; @@ -84,7 +82,7 @@ export default () => { const result = { object, before: beforeCache, - after + after, }; beforeCache = null; // Skip undo in case of empty changes @@ -92,7 +90,7 @@ export default () => { return result; } - } + }, }); um.changeUndoType('add', { on: (model, collection, options = {}) => { @@ -101,9 +99,9 @@ export default () => { object: collection, before: undefined, after: model, - options: { ...options, fromUndo } + options: { ...options, fromUndo }, }; - } + }, }); um.changeUndoType('remove', { on: (model, collection, options = {}) => { @@ -112,9 +110,9 @@ export default () => { object: collection, before: model, after: undefined, - options: { ...options, fromUndo } + options: { ...options, fromUndo }, }; - } + }, }); um.on('undo redo', () => { @@ -309,6 +307,12 @@ export default () => { return result; }, + skip(clb) { + this.stop(); + clb(); + this.start(); + }, + __getStackRead() { const result = {}; const createItem = item => { @@ -317,7 +321,7 @@ export default () => { type, after, before, - object + object, }; }; this.getStack().forEach(item => { @@ -352,6 +356,6 @@ export default () => { this.clear().removeAll(); [em, um, config, beforeCache].forEach(i => (i = {})); this.em = {}; - } + }, }; };