Browse Source

Start refactoring property views

up-style-manager
Artur Arseniev 5 years ago
parent
commit
5fcd868991
  1. 88
      src/commands/view/SelectComponent.js
  2. 4
      src/domain_abstract/ui/InputNumber.js
  3. 3
      src/style_manager/index.js
  4. 2
      src/style_manager/model/Property.js
  5. 3
      src/style_manager/view/PropertyNumberView.js
  6. 249
      src/style_manager/view/PropertyView.js
  7. 8
      src/style_manager/view/SectorsView.js

88
src/commands/view/SelectComponent.js

@ -1,13 +1,6 @@
import Backbone from 'backbone';
import { bindAll, isElement, isUndefined, debounce } from 'underscore';
import {
on,
off,
getUnitFromValue,
isTaggableNode,
getViewEl,
hasWin
} from 'utils/mixins';
import { on, off, getUnitFromValue, isTaggableNode, getViewEl, hasWin } from 'utils/mixins';
import { isVisible, isDoc } from 'utils/dom';
import ToolbarView from 'dom_components/view/ToolbarView';
import Toolbar from 'dom_components/model/Toolbar';
@ -36,15 +29,7 @@ let showOffsets;
*/
export default {
init(o) {
bindAll(
this,
'onHover',
'onOut',
'onClick',
'onFrameScroll',
'onFrameUpdated',
'onContainerChange'
);
bindAll(this, 'onHover', 'onOut', 'onClick', 'onFrameScroll', 'onFrameUpdated', 'onContainerChange');
},
enable() {
@ -92,7 +77,7 @@ export default {
em[method]('component:toggled component:update', this.onSelect, this);
em[method]('change:componentHovered', this.onHovered, this);
em[method](
'component:resize component:styleUpdate component:input',
'component:resize styleable:change component:input', // component:styleUpdate
this.updateGlobalPos,
this
);
@ -177,7 +162,7 @@ export default {
* @param {Object} el
* @private
* */
onSelect: debounce(function() {
onSelect: debounce(function () {
const { em } = this;
const component = em.getSelected();
const currentFrame = em.get('currentFrame') || {};
@ -242,7 +227,7 @@ export default {
view: opts.view,
force: 1,
top: 0,
left: 0
left: 0,
});
},
@ -253,7 +238,7 @@ export default {
*/
hideElementOffset(view) {
this.editor.stopCommand('show-offset', {
view
view,
});
},
@ -266,7 +251,7 @@ export default {
this.editor.runCommand('show-offset', {
el,
elPos: pos,
state: 'Fixed'
state: 'Fixed',
});
},
@ -347,9 +332,7 @@ export default {
const ppfx = config.pStylePrefix || '';
const clsBadge = `${ppfx}badge`;
const customeLabel = config.customBadgeLabel;
const badgeLabel = `${
icon ? `<div class="${clsBadge}__icon">${icon}</div>` : ''
}
const badgeLabel = `${icon ? `<div class="${clsBadge}__icon">${icon}</div>` : ''}
<div class="${clsBadge}__name">${model.getName()}</div>`;
badge.innerHTML = customeLabel ? customeLabel(model) : badgeLabel;
}
@ -359,7 +342,7 @@ export default {
bStyle.display = 'block';
const targetToElem = canvas.getTargetToElementFixed(el, badge, {
pos: pos
pos: pos,
});
const top = targetToElem.top; //opts.topOff - badgeH < 0 ? -opts.topOff : posTop;
@ -390,8 +373,7 @@ export default {
const config = em ? em.get('Config') : '';
const pfx = config.stylePrefix || '';
const resizeClass = `${pfx}resizing`;
const model =
!isElement(elem) && isTaggableNode(elem) ? elem : em.getSelected();
const model = !isElement(elem) && isTaggableNode(elem) ? elem : em.getSelected();
const resizable = model && model.get('resizable');
let options = {};
let modelToStyle;
@ -402,10 +384,7 @@ export default {
docs.forEach(doc => {
const body = doc.body;
const cls = body.className || '';
body.className = (method == 'add'
? `${cls} ${resizeClass}`
: cls.replace(resizeClass, '')
).trim();
body.className = (method == 'add' ? `${cls} ${resizeClass}` : cls.replace(resizeClass, '')).trim();
});
};
@ -415,13 +394,7 @@ export default {
// Here the resizer is updated with the current element height and width
onStart(e, opts = {}) {
const { el, config, resizer } = opts;
const {
keyHeight,
keyWidth,
currentUnit,
keepAutoHeight,
keepAutoWidth
} = config;
const { keyHeight, keyWidth, currentUnit, keepAutoHeight, keepAutoWidth } = config;
toggleBodyClass('add', e, opts);
modelToStyle = em.get('StyleManager').getModelToStyle(model);
canvas.toggleFramesEvents();
@ -468,14 +441,7 @@ export default {
}
const { store, selectedHandler, config } = options;
const {
keyHeight,
keyWidth,
autoHeight,
autoWidth,
unitWidth,
unitHeight
} = config;
const { keyHeight, keyWidth, autoHeight, autoWidth, unitWidth, unitHeight } = config;
const onlyHeight = ['tc', 'bc'].indexOf(selectedHandler) >= 0;
const onlyWidth = ['cl', 'cr'].indexOf(selectedHandler) >= 0;
const style = {};
@ -495,7 +461,7 @@ export default {
const updateEvent = `update:component:style`;
const eventToListen = `${updateEvent}:${keyHeight} ${updateEvent}:${keyWidth}`;
em && em.trigger(eventToListen, null, null, { noEmit: 1 });
}
},
};
if (typeof resizable == 'object') {
@ -529,7 +495,7 @@ export default {
const toolbarView = new ToolbarView({
collection: this.toolbar,
editor: this.editor,
em
em,
});
toolbarEl.appendChild(toolbarView.render().el);
}
@ -628,7 +594,7 @@ export default {
...badgeOpts,
view,
topOff,
leftOff
leftOff,
});
style.top = topOff + unit;
@ -642,18 +608,18 @@ export default {
top: topOff,
left: leftOff,
width: pos.width,
height: pos.height
height: pos.height,
});
},
_upToolbar: debounce(function() {
_upToolbar: debounce(function () {
this.updateToolsGlobal({ force: 1 });
}),
_trgToolUp(type, opts = {}) {
this.em.trigger('canvas:tools:update', {
type,
...opts
...opts,
});
},
@ -677,11 +643,7 @@ export default {
const unit = 'px';
const toolsEl = this.toggleToolsEl(1);
const { style } = toolsEl;
const targetToElem = canvas.getTargetToElementFixed(
el,
canvas.getToolbarEl(),
{ pos }
);
const targetToElem = canvas.getTargetToElementFixed(el, canvas.getToolbarEl(), { pos });
const topOff = targetToElem.canvasOffsetTop;
const leftOff = targetToElem.canvasOffsetLeft;
style.top = topOff + unit;
@ -696,18 +658,18 @@ export default {
top: topOff,
left: leftOff,
width: pos.width,
height: pos.height
height: pos.height,
});
},
/**
* Update attached elements, eg. component toolbar
*/
updateAttached: debounce(function() {
updateAttached: debounce(function () {
this.updateGlobalPos();
}),
onContainerChange: debounce(function() {
onContainerChange: debounce(function () {
this.em.refreshCanvas();
}, 150),
@ -738,7 +700,7 @@ export default {
model &&
model.set({
status: '',
state: ''
state: '',
});
},
@ -764,5 +726,5 @@ export default {
!opts.preserveSelected && em.setSelected(null);
this.toggleToolsEl();
editor && editor.stopCommand('resize');
}
},
};

4
src/domain_abstract/ui/InputNumber.js

@ -124,7 +124,7 @@ export default Input.extend({
const units = model.get('units') || [];
if (units.length) {
const options = [];
const options = ['<option value="" disabled hidden>-</option>'];
units.forEach(unit => {
const selected = unit == model.get('unit') ? 'selected' : '';
@ -255,6 +255,8 @@ export default Input.extend({
if (opt.deepCheck) {
var fixed = model.get('fixedValues') || [];
if (val === '') unit = '';
if (val) {
// If the value is one of the fixed values I leave it as it is
var regFixed = new RegExp('^' + fixed.join('|'), 'g');

3
src/style_manager/index.js

@ -629,7 +629,8 @@ export default () => {
__upProps(opts) {
const lastTarget = this.getLastSelected();
if (!lastTarget || !this.getConfig().custom) return;
// if (!lastTarget || !this.getConfig().custom) return;
if (!lastTarget) return;
const lastTargetParents = this.getSelectedParents();
const style = lastTarget.getStyle();

2
src/style_manager/model/Property.js

@ -32,7 +32,7 @@ export default class Property extends Model {
}
__upTargets(p, opts = {}) {
if (!this.__hasCustom()) return;
// if (!this.__hasCustom()) return;
const { em } = this;
const sm = em.get('StyleManager');
const name = this.getName();

3
src/style_manager/view/PropertyNumberView.js

@ -10,8 +10,7 @@ export default PropertyView.extend({
init() {
const model = this.model;
this.listenTo(model, 'change:unit', this.modelValueChanged);
this.listenTo(model, 'el:change', this.elementUpdated);
this.listenTo(model, 'change:unit', this.onValueChange);
this.listenTo(model, 'change:units', this.render);
},

249
src/style_manager/view/PropertyView.js

@ -39,7 +39,7 @@ export default Backbone.View.extend({
events: {
change: 'inputValueChanged',
[`click [${clearProp}]`]: 'clear'
[`click [${clearProp}]`]: 'clear',
},
initialize(o = {}) {
@ -68,36 +68,28 @@ export default Backbone.View.extend({
}
if (em) {
this.listenTo(
em,
`update:component:style:${this.property}`,
this.targetUpdated
);
this.listenTo(em, `update:component:style:${this.property}`, this.targetUpdated);
//this.listenTo(em, `styleable:change:${this.property}`, this.targetUpdated);
// Listening to changes of properties in this.requires, so that styleable
// changes based on other properties are propagated
const requires = model.get('requires') || {};
Object.keys(requires).forEach(property => {
this.listenTo(
em,
`component:styleUpdate:${property}`,
this.targetUpdated
);
this.listenTo(em, `component:styleUpdate:${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, 'change:value', this.modelValueChanged);
// this.listenTo(model, 'change:value', this.modelValueChanged);
this.listenTo(model, 'targetUpdated', this.targetUpdated);
this.listenTo(model, 'change:visible', this.updateVisibility);
this.listenTo(model, 'change:status', this.updateStatus);
this.listenTo(
model,
'change:name change:className change:full',
this.render
);
// this.listenTo(model, 'change:status', this.updateStatus);
this.listenTo(model, 'change:name change:className change:full', this.render);
// this.listenTo(this.propTarget, 'update', this.onValueChange);
this.onValueChange = debounce(this.onValueChange.bind(this));
this.listenTo(model, 'change:value', this.onValueChange);
const init = this.init && this.init.bind(this);
init && init();
@ -105,9 +97,7 @@ export default Backbone.View.extend({
remove() {
Backbone.View.prototype.remove.apply(this, arguments);
['em', 'target', 'input', '$input', 'propTarget', 'sector'].forEach(
i => (this[i] = {})
);
['em', 'target', 'input', '$input', 'propTarget', 'sector'].forEach(i => (this[i] = {}));
this.__destroyFn(this._getClbOpts());
},
@ -118,8 +108,8 @@ export default Backbone.View.extend({
*/
updateStatus() {
const { model } = this;
const status = model.get('status');
const parent = model.parent;
// const status = model.get('status');
// const parent = model.parent;
const pfx = this.pfx;
const ppfx = this.ppfx;
const config = this.config;
@ -131,18 +121,25 @@ export default Backbone.View.extend({
labelEl.removeClass(`${updatedCls} ${computedCls}`);
clearStyle.display = 'none';
switch (status) {
case 'updated':
!parent && labelEl.addClass(updatedCls);
if (config.clearProperties) {
clearStyle.display = 'inline';
}
break;
case 'computed':
labelEl.addClass(computedCls);
break;
if (model.hasValue({ noParent: true })) {
labelEl.addClass(updatedCls);
config.clearProperties && (clearStyle.display = '');
} else if (model.hasValue()) {
labelEl.addClass(computedCls);
}
// switch (status) {
// case 'updated':
// !parent && labelEl.addClass(updatedCls);
// if (config.clearProperties) {
// clearStyle.display = 'inline';
// }
// break;
// case 'computed':
// labelEl.addClass(computedCls);
// break;
// }
},
/**
@ -150,10 +147,11 @@ export default Backbone.View.extend({
*/
clear(ev) {
ev && ev.stopPropagation();
this.model.clearValue();
this.__unset();
// Skip one stack with setTimeout to avoid inconsistencies (eg. visible on padding composite clear)
setTimeout(() => this.targetUpdated());
this.model.clear();
// this.model.clearValue();
// this.__unset();
// // Skip one stack with setTimeout to avoid inconsistencies (eg. visible on padding composite clear)
// setTimeout(() => this.targetUpdated());
},
/**
@ -207,9 +205,11 @@ export default Backbone.View.extend({
*/
inputValueChanged(ev) {
ev && ev.stopPropagation();
// Skip the default update in case a custom emit method is defined
if (this.emit) return;
this.model.setValueFromInput(this.getInputValue());
this.elementUpdated();
this.model.upValue(ev.target.value);
// this.model.setValueFromInput(this.getInputValue());
// this.elementUpdated();
},
/**
@ -225,7 +225,7 @@ export default Backbone.View.extend({
parent && value == 'updated' && parent.set('status', value);
},
emitUpdateTarget: debounce(function() {
emitUpdateTarget: debounce(function () {
const em = this.config.em;
em && em.trigger('styleManager:update:target', this.getFirstTarget());
}),
@ -244,11 +244,7 @@ export default Backbone.View.extend({
if (config.highlightChanged) {
status = 'updated';
}
} else if (
computedValue &&
config.showComputed &&
computedValue != defaultValue
) {
} else if (computedValue && config.showComputed && computedValue != defaultValue) {
value = computedValue;
if (config.highlightComputed) {
@ -264,7 +260,7 @@ export default Backbone.View.extend({
status,
targetValue,
defaultValue,
computedValue
computedValue,
};
},
@ -273,36 +269,30 @@ export default Backbone.View.extend({
* */
targetUpdated(mod, val, opts = {}) {
// Skip properties rendered in Stack Layers
if (this.config.fromLayer) return;
this.emitUpdateTarget();
if (!this.checkVisibility()) {
return;
}
const config = this.config;
const em = config.em;
const { model } = this;
const property = model.get('property');
const { status, value, ...targetData } = this._getTargetData();
const data = {
status,
value,
...targetData
};
this.setStatus(status);
model.setValue(value, 0, { fromTarget: 1, ...opts });
this.__update(value);
if (em) {
em.trigger('styleManager:change', this, property, value, data);
em.trigger(`styleManager:change:${property}`, this, value, data);
this._emitUpdate(data);
}
return data;
// if (this.config.fromLayer) return;
// this.emitUpdateTarget();
// if (!this.checkVisibility()) {
// return;
// }
// const config = this.config;
// const em = config.em;
// const { model } = this;
// const property = model.get('property');
// const { status, value, ...targetData } = this._getTargetData();
// const data = {
// status,
// value,
// ...targetData
// };
// this.setStatus(status);
// model.setValue(value, 0, { fromTarget: 1, ...opts });
// this.__update(value);
// if (em) {
// em.trigger('styleManager:change', this, property, value, data);
// em.trigger(`styleManager:change:${property}`, this, value, data);
// this._emitUpdate(data);
// }
// return data;
},
_emitUpdate(addData = {}) {
@ -326,7 +316,7 @@ export default Backbone.View.extend({
value: model.getFullValue(),
property: model,
id: model.get('id'),
name: model.get('property')
name: model.get('property'),
};
},
@ -412,6 +402,13 @@ export default Backbone.View.extend({
return input ? input.value : '';
},
onValueChange(m, val, opt = {}) {
const value = this.model.getFullValue();
this.setValue(value);
this.updateStatus();
console.log('onValueChange', this.model.getName(), { value }, opt);
},
/**
* Triggers when the `value` of the model changes, so the target and
* the input element should be updated
@ -420,31 +417,28 @@ export default Backbone.View.extend({
* @param {Object} opt Options
* */
modelValueChanged(e, val, opt = {}) {
const { model } = this;
const value = model.getFullValue();
// Avoid element update if the change comes from it
if (!opt.fromInput) {
this.setValue(value);
}
// Avoid target update if the changes comes from it
if (!opt.fromTarget) {
this.getTargets().forEach(target => this.__updateTarget(target, opt));
// Update the editor and selected components about the change
const { em } = this.config;
if (!em) return;
const prop = model.get('property');
const updated = { [prop]: value };
em.getSelectedAll().forEach(component => {
!opt.noEmit && em.trigger('component:update', component, updated, 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);
});
}
// const { model } = this;
// const value = model.getFullValue();
// // Avoid element update if the change comes from it
// if (!opt.fromInput) {
// this.setValue(value);
// }
// // Avoid target update if the changes comes from it
// if (!opt.fromTarget) {
// this.getTargets().forEach(target => this.__updateTarget(target, opt));
// // Update the editor and selected components about the change
// const { em } = this.config;
// if (!em) return;
// const prop = model.get('property');
// const updated = { [prop]: value };
// em.getSelectedAll().forEach(component => {
// !opt.noEmit && em.trigger('component:update', component, updated, 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);
// });
// }
},
__updateTarget(target, opt = {}) {
@ -534,10 +528,7 @@ export default Backbone.View.extend({
// Check if the property is available only if requested
if (toRequire) {
stylable =
!target ||
(stylableReq &&
(stylableReq.indexOf(id) >= 0 || stylableReq.indexOf(property) >= 0));
stylable = !target || (stylableReq && (stylableReq.indexOf(id) >= 0 || stylableReq.indexOf(property) >= 0));
}
// Check if the property is available based on other property's values
@ -560,8 +551,7 @@ export default Backbone.View.extend({
if (parentEl) {
const styles = window.getComputedStyle(parentEl);
each(requiresParent, (values, property) => {
stylable =
stylable && styles[property] && includes(values, styles[property]);
stylable = stylable && styles[property] && includes(values, styles[property]);
});
} else {
stylable = false;
@ -605,11 +595,11 @@ export default Backbone.View.extend({
* @param {String} value The value from the model
* */
setValue(value) {
const model = this.model;
let val = isUndefined(value) ? model.getDefaultValue() : value;
if (this.update) return this.__update(val);
const { model } = this;
const result = isUndefined(value) ? model.getDefaultValue() : value;
if (this.update) return this.__update(result);
const input = this.getInputEl();
input && (input.value = val);
input && (input.value = result);
},
getInputEl() {
@ -633,8 +623,8 @@ export default Backbone.View.extend({
},
/**
* Clean input
* */
* @deprecated
*/
cleanValue() {
this.setValue('');
},
@ -655,7 +645,7 @@ export default Backbone.View.extend({
update &&
update({
...this._getClbOpts(),
value
value,
});
},
@ -664,10 +654,10 @@ export default Backbone.View.extend({
emit && emit(this._getClbOpts(), ...args);
},
__updateStyle(value, { complete, ...opts } = {}) {
__updateStyle(value, { complete, partial, ...opts } = {}) {
const { em, model } = this;
const prop = model.get('property');
const final = complete !== false;
const final = complete !== false && partial !== true;
if (isObject(value)) {
this.getTargets().forEach(target => {
@ -675,7 +665,7 @@ export default Backbone.View.extend({
em && em.trigger(evStyleUp, target, prop, opts);
});
} else {
model.setValueFromInput(value, complete, opts);
model.setValueFromInput(value, final, opts);
}
final && this.elementUpdated();
@ -698,7 +688,7 @@ export default Backbone.View.extend({
target: this.getFirstTarget(), // Used to update custom UI
computed,
parentRules, // All parent rules
parentRule // First parent rule containing the same property
parentRule, // First parent rule containing the same property
};
},
@ -706,27 +696,26 @@ export default Backbone.View.extend({
this.clearCached();
const { pfx, model, el, $el } = this;
const property = model.get('property');
const type = model.get('type');
const full = model.get('full');
const cls = model.get('className') || '';
const className = `${pfx}property`;
// Support old integer classname
const clsType = type === 'number' ? `${pfx}${type} ${pfx}integer` : `${pfx}${type}`;
this.createdEl && this.__destroyFn(this._getClbOpts());
$el.empty().append(this.template(model));
$el.find('[data-sm-label]').append(this.templateLabel(model));
const create = this.create && this.create.bind(this);
this.createdEl = create && create(this._getClbOpts());
$el
.find('[data-sm-fields]')
.append(this.createdEl || this.templateInput(model));
$el.find('[data-sm-fields]').append(this.createdEl || this.templateInput(model));
el.className = `${className} ${pfx}${model.get(
'type'
)} ${className}__${property} ${cls}`.trim();
el.className = `${className} ${clsType} ${className}__${property} ${cls}`.trim();
el.className += full ? ` ${className}--full` : '';
this.updateStatus();
// this.updateStatus();
const onRender = this.onRender && this.onRender.bind(this);
onRender && onRender();
this.setValue(model.get('value'), { fromTarget: 1 });
}
// this.setValue(model.get('value'), { fromTarget: 1 });
},
});

8
src/style_manager/view/SectorsView.js

@ -1,5 +1,5 @@
import Backbone from 'backbone';
import { extend, isString, isArray } from 'underscore';
import { extend, isString, isArray, debounce } from 'underscore';
import { isTaggableNode } from 'utils/mixins';
import { appendAtIndex } from 'utils/dom';
import SectorView from './SectorView';
@ -30,8 +30,14 @@ export default Backbone.View.extend({
this.listenTo(coll, 'add', this.addTo);
this.listenTo(coll, 'reset', this.render);
this.listenTo(em, module.events.target, this.targetUpdated);
// Check local/parent value on input change
this.listenTo(em, 'styleable:change', this.emitUpdate);
},
emitUpdate: debounce(function () {
this.propTarget.trigger('update');
}),
remove() {
Backbone.View.prototype.remove.apply(this, arguments);
['target', 'config', 'propTarget'].forEach(i => (this[i] = {}));

Loading…
Cancel
Save