From ee17647182646eef23fe48c8fe16523e279a205f Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 5 Jun 2021 19:01:43 +0200 Subject: [PATCH] Improve stuff for custom traits --- src/code_manager/model/CssGenerator.js | 13 ++++++++++- src/style_manager/index.js | 18 +++++++++++++++ src/style_manager/view/PropertyView.js | 32 ++++++++++++++++++-------- src/style_manager/view/SectorsView.js | 7 +++--- src/utils/mixins.js | 6 +++++ 5 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/code_manager/model/CssGenerator.js b/src/code_manager/model/CssGenerator.js index a52900edb..51bb25fe9 100644 --- a/src/code_manager/model/CssGenerator.js +++ b/src/code_manager/model/CssGenerator.js @@ -1,10 +1,11 @@ import Backbone from 'backbone'; -import { isUndefined, each } from 'underscore'; +import { bindAll, isUndefined, each } from 'underscore'; const maxValue = Number.MAX_VALUE; export default Backbone.Model.extend({ initialize() { + bindAll(this, 'sortRules'); this.compCls = []; this.ids = []; }, @@ -159,5 +160,15 @@ export default Backbone.Model.extend({ const right = isMobFirst ? b.key : a.key; return this.getQueryLength(left) - this.getQueryLength(right); }); + }, + + sortRules(a, b) { + const getKey = rule => rule.get('mediaText'); + const isMobFirst = [getKey(a), getKey(b)].every( + q => q.indexOf('min-width') !== -1 + ); + const left = isMobFirst ? getKey(a) : getKey(b); + const right = isMobFirst ? getKey(b) : getKey(a); + return this.getQueryLength(left) - this.getQueryLength(right); } }); diff --git a/src/style_manager/index.js b/src/style_manager/index.js index 55e817fa7..35dc688fd 100644 --- a/src/style_manager/index.js +++ b/src/style_manager/index.js @@ -309,6 +309,24 @@ export default () => { return model; }, + getParentRules(target, state) { + const { em } = c; + let result = []; + + if (em) { + const cssC = em.get('CssComposer'); + const cssGen = em.get('CodeManager').getGenerator('css'); + const all = cssC + .getRules(target.getSelectors().getFullString()) + .filter(rule => (state ? rule.get('state') === state : 1)) + .sort(cssGen.sortRules) + .reverse(); + result = all.slice(all.indexOf(target) + 1); + } + + return result; + }, + /** * Add new property type * @param {string} id Type ID diff --git a/src/style_manager/view/PropertyView.js b/src/style_manager/view/PropertyView.js index d693b6246..5d6ee7348 100644 --- a/src/style_manager/view/PropertyView.js +++ b/src/style_manager/view/PropertyView.js @@ -1,9 +1,10 @@ import Backbone from 'backbone'; import { bindAll, isArray, isUndefined, debounce } from 'underscore'; -import { camelCase, isObject } from 'utils/mixins'; +import { camelCase, isObject, find } from 'utils/mixins'; import { includes, each } from 'underscore'; const clearProp = 'data-clear-style'; +const evStyleUp = 'component:styleUpdate'; export default Backbone.View.extend({ template() { @@ -292,6 +293,7 @@ export default Backbone.View.extend({ this.setStatus(status); model.setValue(value, 0, { fromTarget: 1, ...opts }); + this.__update(value); if (em) { em.trigger('styleManager:change', this, property, value, data); @@ -436,8 +438,8 @@ export default Backbone.View.extend({ const updated = { [prop]: value }; em.getSelectedAll().forEach(component => { !opt.noEmit && em.trigger('component:update', component, updated, opt); - em.trigger('component:styleUpdate', component, prop, opt); - em.trigger(`component:styleUpdate:${prop}`, component, value, opt); + em.trigger(evStyleUp, component, prop, opt); + em.trigger(`${evStyleUp}:${prop}`, component, value, opt); component.trigger(`change:style`, component, updated, opt); component.trigger(`change:style:${prop}`, component, value, opt); }); @@ -657,28 +659,40 @@ export default Backbone.View.extend({ }, __updateStyle(value, { complete, ...opts } = {}) { + const { em, model } = this; + const prop = model.get('property'); const final = complete !== false; if (isObject(value)) { - this.getTargets().forEach(target => - target.addStyle(value, { avoidStore: !final }) - ); + this.getTargets().forEach(target => { + target.addStyle(value, { avoidStore: !final }); + em && em.trigger(evStyleUp, target, prop, opts); + }); } else { - this.model.setValueFromInput(value, complete, opts); + model.setValueFromInput(value, complete, opts); } final && this.elementUpdated(); }, _getClbOpts() { - const { model, el } = this; + const { model, el, createdEl, propTarget } = this; + const prop = model.get('property'); + const computed = propTarget.computed || {}; + const parentRules = propTarget.parentRules || []; + const parentRule = find(parentRules, rule => !!rule.getStyle()[prop]); return { el, + createdEl, props: model.attributes, setProps: (...args) => model.set(...args), change: this.__change, updateStyle: this.__updateStyle, - targets: this.getTargets() + targets: this.getTargets(), // Used to update selected targets + target: this.getFirstTarget(), // Used to update custom UI + computed, + parentRules, // All parent rules + parentRule // First parent rule containing the same property }; }, diff --git a/src/style_manager/view/SectorsView.js b/src/style_manager/view/SectorsView.js index a47cf3a70..96f0c3a66 100644 --- a/src/style_manager/view/SectorsView.js +++ b/src/style_manager/view/SectorsView.js @@ -101,14 +101,15 @@ export default Backbone.View.extend({ }; const sm = em.get('StyleManager'); - model = sm.getModelToStyle(model); + const target = sm.getModelToStyle(model); if (state) { - appendStateRule(model.getStyle()); + appendStateRule(target.getStyle()); this.toggleStateCls(targets, 1); } - pt.model = model; + pt.model = target; + pt.parentRules = sm.getParentRules(target, state); if (componentFirst) { pt.targets = targets.map(t => sm.getModelToStyle(t)).filter(Boolean); } diff --git a/src/utils/mixins.js b/src/utils/mixins.js index 8621d341e..1a2a06aaa 100644 --- a/src/utils/mixins.js +++ b/src/utils/mixins.js @@ -161,6 +161,12 @@ export const isCommentNode = el => el && el.nodeType === 8; */ export const isTaggableNode = el => el && !isTextNode(el) && !isCommentNode(el); +export const find = (arr, test) => { + let result = null; + arr.some((el, i) => (test(el, i, arr) ? ((result = el), 1) : 0)); + return result; +}; + /** * Ensure to fetch the model from the input argument * @param {HTMLElement|Component} el Component or HTML element