Browse Source

Refactor StyleManager model properties

pull/487/head
Artur Arseniev 8 years ago
parent
commit
7839ac7985
  1. 2
      dist/css/grapes.min.css
  2. 21
      src/domain_abstract/ui/Input.js
  3. 19
      src/domain_abstract/ui/InputColor.js
  4. 11
      src/domain_abstract/ui/InputNumber.js
  5. 2
      src/style_manager/index.js
  6. 2
      src/style_manager/model/Layers.js
  7. 23
      src/style_manager/model/Property.js
  8. 17
      src/style_manager/model/PropertyInteger.js
  9. 2
      src/style_manager/model/Sectors.js
  10. 2
      src/style_manager/view/PropertyCompositeView.js
  11. 8
      src/style_manager/view/PropertyIntegerView.js
  12. 37
      src/style_manager/view/PropertyView.js
  13. 48
      src/styles/scss/_gjs_inputs.scss
  14. 55
      test/specs/style_manager/model/Models.js
  15. 9
      test/specs/style_manager/view/PropertyIntegerView.js

2
dist/css/grapes.min.css

File diff suppressed because one or more lines are too long

21
src/domain_abstract/ui/Input.js

@ -8,16 +8,24 @@ module.exports = Backbone.View.extend({
template() {
return `<span class="${this.holderClass}"></span>`;
return `<span class="${this.holderClass()}"></span>`;
},
inputClass() {
return `${this.ppfx}field`;
},
holderClass() {
return `${this.ppfx}input-holder`;
},
initialize(opts = {}) {
const ppfx = opts.ppfx || '';
this.opts = opts;
this.ppfx = ppfx;
this.target = opts.target || {};
this.inputClass = `${ppfx}field`;
this.holderClass = `${ppfx}input-holder`;
this.listenTo(this.model, 'change:value', this.handleModelChange);
},
@ -67,8 +75,7 @@ module.exports = Backbone.View.extend({
getInputEl() {
if (!this.inputEl) {
const plh = this.model.get('defaults');
const cls = this.inputCls;
this.inputEl = $(`<input type="text" class="${cls}" placeholder="${plh}">`);
this.inputEl = $(`<input type="text" placeholder="${plh}">`);
}
return this.inputEl.get(0);
@ -77,9 +84,9 @@ module.exports = Backbone.View.extend({
render() {
const el = this.$el;
el.addClass(this.inputClass);
el.addClass(this.inputClass());
el.html(this.template());
el.find(`.${this.holderClass}`).append(this.getInputEl());
el.find(`.${this.holderClass()}`).append(this.getInputEl());
return this;
}

19
src/domain_abstract/ui/InputColor.js

@ -7,21 +7,22 @@ module.exports = Input.extend({
template() {
const ppfx = this.ppfx;
return `
<div class="${ppfx}input-holder"></div>
<div class="${this.holderClass()}"></div>
<div class="${ppfx}field-colorp">
<div class="${ppfx}field-colorp-c">
<div class="${ppfx}field-colorp-c" data-colorp-c>
<div class="${ppfx}checker-bg"></div>
</div>
</div>
`;
},
initialize() {
Input.prototype.initialize.apply(this, arguments);
inputClass() {
const ppfx = this.ppfx;
this.colorCls = `${ppfx}field-color-picker`;
this.inputClass = `${ppfx}field ${ppfx}field-color`;
this.colorHolderClass = `${ppfx}field-colorp-c`;
return `${ppfx}field ${ppfx}field-color`;
},
holderClass() {
return `${this.ppfx}input-holder`;
},
/**
@ -53,7 +54,7 @@ module.exports = Input.extend({
const self = this;
var model = this.model;
var colorEl = $(`<div class="${this.colorCls}"></div>`);
var colorEl = $(`<div class="${this.ppfx}field-color-picker"></div>`);
var cpStyle = colorEl.get(0).style;
var elToAppend = this.target && this.target.config ? this.target.config.el : '';
const getColor = color => {
@ -63,7 +64,7 @@ module.exports = Input.extend({
let changed = 0;
let previousСolor;
this.$el.find(`.${this.colorHolderClass}`).append(colorEl);
this.$el.find(`[data-colorp-c]`).append(colorEl);
colorEl.spectrum({
appendTo: elToAppend || 'body',

11
src/domain_abstract/ui/InputNumber.js

@ -27,15 +27,16 @@ module.exports = Input.extend({
`;
},
inputClass() {
const ppfx = this.ppfx;
return this.opts.contClass || `${ppfx}field ${ppfx}field-integer`;
},
initialize(opts = {}) {
Input.prototype.initialize.apply(this, arguments);
bindAll(this, 'moveIncrement', 'upIncrement');
const ppfx = this.ppfx;
this.doc = document;
this.inputCls = `${ppfx}field-number`;
this.unitCls = `${ppfx}input-unit`;
this.inputClass = opts.contClass || `${ppfx}field ${ppfx}field-integer`;;
this.listenTo(this.model, 'change:unit', this.handleModelChange);
},
@ -123,7 +124,7 @@ module.exports = Input.extend({
});
const temp = document.createElement('div');
temp.innerHTML = `<select class="${this.unitCls}">${options.join('')}</select>`;
temp.innerHTML = `<select class="${this.ppfx}input-unit">${options.join('')}</select>`;
this.unitEl = temp.firstChild;
}
}

2
src/style_manager/index.js

@ -97,7 +97,7 @@ module.exports = () => {
c.stylePrefix = ppfx + c.stylePrefix;
properties = new Properties();
sectors = new Sectors(c.sectors);
sectors = new Sectors(c.sectors, c);
SectView = new SectorsView({
collection: sectors,
target: c.em,

2
src/style_manager/model/Layers.js

@ -64,7 +64,7 @@ module.exports = Backbone.Collection.extend({
const style = styleObj[propModel.get('property')];
const values = style ? style.split(', ') : [];
values.forEach((value, i) => {
value = propModel.parseValue(value.trim());
value = propModel.parseValue(value.trim()).value;
const layer = layers[i];
const propertyObj = Object.assign({}, propModel.attributes, {value});

23
src/style_manager/model/Property.js

@ -35,29 +35,37 @@ module.exports = require('backbone').Model.extend({
* @param {Object} [opts={}] Options
*/
setValue(value, complete = 1, opts = {}) {
this.set('value', value, { ...opts, avoidStore: 1});
const parsed = this.parseValue(value);
this.set(parsed, { ...opts, avoidStore: 1});
// It's important to set an empty value, otherwise the
// UndoManager won't see the change
if (complete) {
this.set('value', '', opts);
this.set('value', value, opts);
this.set(parsed, opts);
}
},
/**
* Parse a raw value, generally fetched from the target, for this property
* @param {string} value
* @return {string}
* @param {string} value Raw value string
* @return {Object}
* @example
* // example with an Input type
* prop.parseValue('translateX(10deg)');
* // -> { value: 10, unit: 'deg', functionName: 'translateX' }
*
*/
parseValue(value) {
const result = { value };
if (!this.get('functionName')) {
return value;
return result;
}
const args = [];
let valueStr = value + '';
let valueStr = `${value}`;
let start = valueStr.indexOf('(') + 1;
let end = valueStr.lastIndexOf(')');
args.push(start);
@ -67,7 +75,8 @@ module.exports = require('backbone').Model.extend({
args.push(end);
}
return String.prototype.substring.apply(valueStr, args);
result.value = String.prototype.substring.apply(valueStr, args);
return result;
},

17
src/style_manager/model/PropertyInteger.js

@ -1,8 +1,9 @@
const Property = require('./Property');
const InputNumber = require('domain_abstract/ui/InputNumber');
module.exports = Property.extend({
defaults: Object.assign({}, Property.prototype.defaults, {
defaults: { ...Property.prototype.defaults,
// Array of units, eg. ['px', '%']
units: [],
@ -17,17 +18,29 @@ module.exports = Property.extend({
// Maximum value
max: '',
}),
},
init() {
const unit = this.get('unit');
const units = this.get('units');
this.input = new InputNumber({ model: this });
if (units.length && !unit) {
this.set('unit', units[0]);
}
},
parseValue(val) {
const parsed = Property.prototype.parseValue.apply(this, arguments);
const { value, unit } = this.input.validateInputValue(parsed.value, {deepCheck: 1});
parsed.value = value;
parsed.unit = unit;
return parsed;
},
getFullValue() {
let value = this.get('value') + this.get('unit');
return Property.prototype.getFullValue.apply(this, [value]);

2
src/style_manager/model/Sectors.js

@ -1,5 +1,5 @@
const Sector = require('./Sector');
module.exports = require('backbone').Collection.extend({
model: Sector,
model: Sector
});

2
src/style_manager/view/PropertyCompositeView.js

@ -107,7 +107,7 @@ module.exports = PropertyView.extend({
}
if (view) {
value = view.model.parseValue(value);
value = view.model.parseValue(value).value;
}
return value;

8
src/style_manager/view/PropertyIntegerView.js

@ -21,11 +21,9 @@ module.exports = require('./PropertyView').extend({
const ppfx = this.ppfx;
if (!this.input) {
const inputNumber = new InputNumber({
model: this.model,
ppfx: this.ppfx
});
const input = inputNumber.render();
const input = this.model.input;
input.ppfx = ppfx;
input.render();
const fields = this.el.querySelector(`.${ppfx}fields`);
fields.appendChild(input.el);
this.$input = input.inputEl;

37
src/style_manager/view/PropertyView.js

@ -56,6 +56,7 @@ module.exports = Backbone.View.extend({
const pfx = this.pfx;
this.inputHolderId = '#' + pfx + 'input-holder';
this.sector = model.collection && model.collection.sector;
model.view = this;
if (!model.get('value')) {
model.set('value', model.getDefaultValue());
@ -199,8 +200,7 @@ module.exports = Backbone.View.extend({
status = '';
}
model.set('value', value, {silent: 1});
this.setValue(value, {targetUpdate: 1});
model.setValue(value, 0, { fromTarget: 1 });
model.set('status', status);
if (em) {
@ -249,11 +249,6 @@ module.exports = Backbone.View.extend({
result = target.getStyle()[model.get('property')];
// TODO when stack type asks the sub-property (in valueOnIndex method)
// to provide its target value and its detached, I should avoid parsing
// (at least is wrong applying 'functionName' cleaning)
result = model.parseValue(result);
if (!result && !opts.ignoreDefault) {
result = model.getDefaultValue();
}
@ -305,9 +300,9 @@ module.exports = Backbone.View.extend({
const target = this.getTarget();
const onChange = this.onChange;
// I don't need to update the input if the change comes from it
// Avoid element update if the change comes from it
if (!opt.fromInput) {
this.setRawValue(value);
this.setValue(value);
}
// Check if component is allowed to be styled
@ -315,10 +310,13 @@ module.exports = Backbone.View.extend({
return;
}
if (onChange) {
onChange(target, this, opt);
} else {
this.updateTargetStyle(value, null, opt);
// Avoid target update if the changes comes from it
if (!opt.fromTarget) {
if (onChange) {
onChange(target, this, opt);
} else {
this.updateTargetStyle(value, null, opt);
}
}
if (em) {
@ -401,19 +399,20 @@ module.exports = Backbone.View.extend({
this.setValue(this.model.parseValue(value));
},
/**
* Set the value to property input
* @param {String} value
* @param {Boolean} force
* @private
* Update the element input.
* Usually the value is a result of `model.getFullValue()`
* @param {String} value The value from the model
* */
setValue(value, opts = {}) {
setValue(value) {
const model = this.model;
let val = value || model.get('value') || model.getDefaultValue();
let val = value || model.getDefaultValue();
const input = this.getInputEl();
input && (input.value = val);
},
getInputEl() {
if (!this.input) {
this.input = this.el.querySelector('input');

48
src/styles/scss/_gjs_inputs.scss

@ -49,9 +49,34 @@
}
&field {
input,
select,
textarea {
@include appearance(none);
color: inherit;
border: none;
background-color: transparent;
box-sizing: border-box;
width: 100%;
position: relative;
padding: $inputPadding;
z-index: 1;
&:focus {
outline: none;
}
}
&-range {
flex: 9 1 auto;
}
&-integer {
input {
padding-right: 30px;
}
}
}
}
@ -72,25 +97,6 @@
position: relative;
color: $inputFontColor;
input,
select,
textarea {
@include appearance(none);
color: inherit;
border: none;
background-color: transparent;
box-sizing: border-box;
width: 100%;
position: relative;
padding: $inputPadding;
z-index: 1;
&:focus {
outline: none;
}
}
textarea {
resize: vertical;
}
@ -122,10 +128,6 @@
cursor: pointer;
}
.#{$app-prefix}field-number {
padding-right: 30px;
}
&-arrows {
position: absolute;
cursor: ns-resize;

55
test/specs/style_manager/model/Models.js

@ -1,6 +1,7 @@
const Sector = require('style_manager/model/Sector');
const Sectors = require('style_manager/model/Sectors');
const Property = require('style_manager/model/Property');
const PropertyInteger = require('style_manager/model/PropertyInteger');
const Properties = require('style_manager/model/Properties');
const Layer = require('style_manager/model/Layer');
const Layers = require('style_manager/model/Layers');
@ -125,7 +126,6 @@ module.exports = {
});
describe('Property', () => {
var obj;
beforeEach(() => {
@ -140,6 +140,59 @@ module.exports = {
expect(obj.has('property')).toEqual(true);
});
it('parseValue', () => {
const result = { value: 'testValue' };
expect(obj.parseValue('testValue')).toEqual(result);
});
it('parseValue with function but without functionName', () => {
const result = { value: 'fn(testValue)' };
expect(obj.parseValue('fn(testValue)')).toEqual(result);
});
it('parseValue with function and functionName', () => {
obj = new Property({ functionName: 'fn' });
const result = { value: 'testValue' };
expect(obj.parseValue('fn(testValue)')).toEqual(result);
expect(obj.parseValue('fn(testValue')).toEqual(result);
});
});
describe('PropertyInteger', () => {
var obj;
beforeEach(() => {
obj = new PropertyInteger({units: ['px', 'deg']});
});
afterEach(() => {
obj = null;
});
it('parseValue with units', () => {
const result = { value: 20, unit: 'px' };
expect(obj.parseValue('20px')).toEqual(result);
});
it('parse input value with function', () => {
obj = new PropertyInteger({units: ['px', 'deg'], functionName: 'test'});
const result = { value: 55, unit: 'deg' };
expect(obj.parseValue('test(55deg)')).toEqual(result);
});
it('parse input value with min', () => {
obj = new PropertyInteger({units: ['px'], min: 10});
const result = { value: 10, unit: 'px' };
expect(obj.parseValue('1px')).toEqual(result);
expect(obj.parseValue('15px')).toEqual({ value: 15, unit: 'px' });
});
it('parse input value with max', () => {
obj = new PropertyInteger({units: ['px'], max: 100});
const result = { value: 100, unit: 'px' };
expect(obj.parseValue('200px')).toEqual(result);
expect(obj.parseValue('95px')).toEqual({ value: 95, unit: 'px' });
});
});
describe('Properties', () => {

9
test/specs/style_manager/view/PropertyIntegerView.js

@ -1,11 +1,12 @@
const PropertyIntegerView = require('style_manager/view/PropertyIntegerView');
const Property = require('style_manager/model/Property');
const PropertyInteger = require('style_manager/model/PropertyInteger');
const Component = require('dom_components/model/Component');
module.exports = {
run() {
describe('PropertyIntegerView', () => {
describe.only('PropertyIntegerView', () => {
var component;
var fixtures;
@ -26,8 +27,7 @@ module.exports = {
beforeEach(() => {
target = new Component();
component = new Component();
model = new Property({
type: 'integer',
model = new PropertyInteger({
units,
property: propName
});
@ -161,8 +161,7 @@ module.exports = {
beforeEach(() => {
component = new Component();
model = new Property({
type: 'integer',
model = new PropertyInteger({
units,
property: propName,
defaults: intValue,

Loading…
Cancel
Save