From 49264becd61fa6570d02b5a9074854a9d1fe8ecc Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 6 May 2017 15:17:40 +0200 Subject: [PATCH] Fix checkVisibility for detached properties (eg. background) --- src/demo.js | 22 - src/style_manager/view/PropertiesView.js | 112 ++--- src/style_manager/view/PropertyStackView.js | 522 ++++++++++---------- src/style_manager/view/PropertyView.js | 25 +- src/style_manager/view/SectorView.js | 3 +- 5 files changed, 336 insertions(+), 348 deletions(-) diff --git a/src/demo.js b/src/demo.js index d998f49ea..415610407 100644 --- a/src/demo.js +++ b/src/demo.js @@ -158,28 +158,6 @@ require(['config/require-config'], function() { open: false, buildProps: ['transition', 'perspective', 'transform'], },{ - name: 'Dimension', - open: false, - buildProps: ['margin'], - properties:[{ - name: 'Marginnnn', - property: 'margin', - type: 'composite', - properties:[{ - name: 'Top', - property: 'margin-top', - },{ - name: 'Right', - property: 'margin-right', - },{ - name: 'Bottom', - property: 'margin-bottom', - },{ - name: 'Left', - property: 'margin-left', - },], - }], - },{ name: 'Flex', open: false, properties: [{ diff --git a/src/style_manager/view/PropertiesView.js b/src/style_manager/view/PropertiesView.js index 2735adff7..463846533 100644 --- a/src/style_manager/view/PropertiesView.js +++ b/src/style_manager/view/PropertiesView.js @@ -1,67 +1,67 @@ define(['backbone','./PropertyView', './PropertyIntegerView', './PropertyRadioView', './PropertySelectView', './PropertyColorView', './PropertyFileView', './PropertyCompositeView', './PropertyStackView'], - function (Backbone, PropertyView, PropertyIntegerView, PropertyRadioView, PropertySelectView, - PropertyColorView, PropertyFileView, PropertyCompositeView, PropertyStackView) { - /** - * @class PropertiesView - * */ - return Backbone.View.extend({ + function (Backbone, PropertyView, PropertyIntegerView, PropertyRadioView, PropertySelectView, + PropertyColorView, PropertyFileView, PropertyCompositeView, PropertyStackView) { + /** + * @class PropertiesView + * */ + return Backbone.View.extend({ - initialize: function(o) { - this.config = o.config || {}; - this.pfx = this.config.stylePrefix || ''; - this.target = o.target || {}; - this.propTarget = o.propTarget || {}; - this.onChange = o.onChange || {}; - this.onInputRender = o.onInputRender || {}; - this.customValue = o.customValue || {}; - }, + initialize: function(o) { + this.config = o.config || {}; + this.pfx = this.config.stylePrefix || ''; + this.target = o.target || {}; + this.propTarget = o.propTarget || {}; + this.onChange = o.onChange || {}; + this.onInputRender = o.onInputRender || {}; + this.customValue = o.customValue || {}; + }, - render: function() { - var fragment = document.createDocumentFragment(); + render: function() { + var fragment = document.createDocumentFragment(); - this.collection.each(function(model){ - var objView = PropertyView; + this.collection.each(function(model){ + var objView = PropertyView; - switch(model.get('type')){ - case 'integer': - objView = PropertyIntegerView; break; - case 'radio': - objView = PropertyRadioView; break; - case 'select': - objView = PropertySelectView; break; - case 'color': - objView = PropertyColorView; break; - case 'file': - objView = PropertyFileView; break; - case 'composite': - objView = PropertyCompositeView;break; - case 'stack': - objView = PropertyStackView; break; - } + switch(model.get('type')){ + case 'integer': + objView = PropertyIntegerView; break; + case 'radio': + objView = PropertyRadioView; break; + case 'select': + objView = PropertySelectView; break; + case 'color': + objView = PropertyColorView; break; + case 'file': + objView = PropertyFileView; break; + case 'composite': + objView = PropertyCompositeView;break; + case 'stack': + objView = PropertyStackView; break; + } - var view = new objView({ - model: model, - name: model.get('name'), - id: this.pfx + model.get('property'), - target: this.target, - propTarget: this.propTarget, - onChange: this.onChange, - onInputRender: this.onInputRender, - config: this.config, - }); + var view = new objView({ + model: model, + name: model.get('name'), + id: this.pfx + model.get('property'), + target: this.target, + propTarget: this.propTarget, + onChange: this.onChange, + onInputRender: this.onInputRender, + config: this.config, + }); - if(model.get('type') != 'composite'){ - view.customValue = this.customValue; - } + if(model.get('type') != 'composite'){ + view.customValue = this.customValue; + } - fragment.appendChild(view.render().el); - },this); + fragment.appendChild(view.render().el); + },this); - this.$el.append(fragment); - this.$el.append($('
', {class: "clear"})); - this.$el.attr('class', this.pfx + 'properties'); - return this; - } - }); + this.$el.append(fragment); + this.$el.append($('
', {class: "clear"})); + this.$el.attr('class', this.pfx + 'properties'); + return this; + } + }); }); diff --git a/src/style_manager/view/PropertyStackView.js b/src/style_manager/view/PropertyStackView.js index 4921e4f86..b33723085 100644 --- a/src/style_manager/view/PropertyStackView.js +++ b/src/style_manager/view/PropertyStackView.js @@ -1,290 +1,292 @@ define(['backbone','./PropertyCompositeView', 'text!./../templates/propertyStack.html','./../model/Layers','./LayersView'], - function (Backbone, PropertyCompositeView, propertyTemplate, Layers, LayersView) { - /** - * @class PropertyStackView - * */ - return PropertyCompositeView.extend({ + function (Backbone, PropertyCompositeView, propertyTemplate, Layers, LayersView) { + /** + * @class PropertyStackView + * */ + return PropertyCompositeView.extend({ - template: _.template(propertyTemplate), + template: _.template(propertyTemplate), - initialize: function(o) { - PropertyCompositeView.prototype.initialize.apply(this, arguments); - this.model.set('stackIndex', null); - this.className = this.pfx + 'property '+ this.pfx +'stack'; - this.events['click #'+this.pfx+'add'] = 'addLayer'; - this.listenTo( this.model ,'change:stackIndex', this.indexChanged); - this.listenTo( this.model ,'updateValue', this.valueUpdated); - this.delegateEvents(); - }, + initialize: function(o) { + PropertyCompositeView.prototype.initialize.apply(this, arguments); + this.model.set('stackIndex', null); + this.className = this.pfx + 'property '+ this.pfx +'stack'; + this.events['click #'+this.pfx+'add'] = 'addLayer'; + this.listenTo( this.model ,'change:stackIndex', this.indexChanged); + this.listenTo( this.model ,'updateValue', this.valueUpdated); + this.delegateEvents(); + }, - /** - * Fired when the target is updated. - * With detached mode the component will be always empty as its value - * so we gonna check all props and fine if there is some differences. - * */ - targetUpdated: function(){ - if(!this.model.get('detached')) - PropertyCompositeView.prototype.targetUpdated.apply(this, arguments); - else - this.refreshLayers(); - }, + /** + * Fired when the target is updated. + * With detached mode the component will be always empty as its value + * so we gonna check all props and fine if there is some differences. + * */ + targetUpdated: function(){ + if(!this.model.get('detached')) + PropertyCompositeView.prototype.targetUpdated.apply(this, arguments); + else { + this.checkVisibility(); + this.refreshLayers(); + } + }, - /** - * Returns the collection of layers - * @return {Collection} - */ - getLayers: function(){ - return this.model.get('layers'); - }, + /** + * Returns the collection of layers + * @return {Collection} + */ + getLayers: function(){ + return this.model.get('layers'); + }, - /** - * Triggered when another layer has been selected. - * This allow to move all rendered properties to a new - * selected layer - * @param {Event} - * - * @return {Object} - * */ - indexChanged: function(e){ - var layer = this.getLayers().at(this.model.get('stackIndex')); - layer.set('props', this.$props); - this.model.get('properties').each(function(prop){ - prop.trigger('targetUpdated'); - }); - }, + /** + * Triggered when another layer has been selected. + * This allow to move all rendered properties to a new + * selected layer + * @param {Event} + * + * @return {Object} + * */ + indexChanged: function(e){ + var layer = this.getLayers().at(this.model.get('stackIndex')); + layer.set('props', this.$props); + this.model.get('properties').each(function(prop){ + prop.trigger('targetUpdated'); + }); + }, - /** - * Get array of values from layers - * @return Array - * */ - getStackValues: function(){ - return this.getLayers().pluck('value'); - }, + /** + * Get array of values from layers + * @return Array + * */ + getStackValues: function(){ + return this.getLayers().pluck('value'); + }, - /** @inheritDoc */ - getPropsConfig: function(opts){ - var that = this; - var result = PropertyCompositeView.prototype.getPropsConfig.apply(this, arguments); + /** @inheritDoc */ + getPropsConfig: function(opts){ + var that = this; + var result = PropertyCompositeView.prototype.getPropsConfig.apply(this, arguments); - result.onChange = function(el, view, opt){ - var model = view.model; - var result = that.build(); + result.onChange = function(el, view, opt){ + var model = view.model; + var result = that.build(); - if(that.model.get('detached')){ - var propVal = ''; - var index = model.collection.indexOf(model); + if(that.model.get('detached')){ + var propVal = ''; + var index = model.collection.indexOf(model); - that.getLayers().each(function(layer){ - var val = layer.get('values')[model.get('property')]; - if(val) - propVal += (propVal ? ',' : '') + val; - }); + that.getLayers().each(function(layer){ + var val = layer.get('values')[model.get('property')]; + if(val) + propVal += (propVal ? ',' : '') + val; + }); - view.updateTargetStyle(propVal, null, opt); - }else - that.model.set('value', result, opt); - }; + view.updateTargetStyle(propVal, null, opt); + }else + that.model.set('value', result, opt); + }; - return result; - }, + return result; + }, - /** - * Extract string from composite value - * @param integer Index - * @param View propView Property view - * @return string - * */ - valueOnIndex: function(index, propView){ - var result = null; - // If detached the value in this case is stacked, eg. substack-prop: 1px, 2px, 3px... - if(this.model.get('detached')){ - var valist = propView.componentValue.split(','); - result = valist[this.model.get('stackIndex')]; - result = result ? result.trim() : result; - }else{ - var aStack = this.getStackValues(); - var strVar = aStack[this.model.get('stackIndex')]; - if(!strVar) - return; - var a = strVar.split(' '); - if(a.length && a[index]){ - result = a[index]; - } - } - return result; - }, + /** + * Extract string from composite value + * @param integer Index + * @param View propView Property view + * @return string + * */ + valueOnIndex: function(index, propView){ + var result = null; + // If detached the value in this case is stacked, eg. substack-prop: 1px, 2px, 3px... + if(this.model.get('detached')){ + var valist = propView.componentValue.split(','); + result = valist[this.model.get('stackIndex')]; + result = result ? result.trim() : result; + }else{ + var aStack = this.getStackValues(); + var strVar = aStack[this.model.get('stackIndex')]; + if(!strVar) + return; + var a = strVar.split(' '); + if(a.length && a[index]){ + result = a[index]; + } + } + return result; + }, - /** @inheritdoc */ - build: function(){ - var stackIndex = this.model.get('stackIndex'); - if(stackIndex === null) - return; - var result = PropertyCompositeView.prototype.build.apply(this, arguments); - var model = this.getLayers().at(stackIndex); - if(!model) - return; + /** @inheritdoc */ + build: function(){ + var stackIndex = this.model.get('stackIndex'); + if(stackIndex === null) + return; + var result = PropertyCompositeView.prototype.build.apply(this, arguments); + var model = this.getLayers().at(stackIndex); + if(!model) + return; - // Store properties values inside layer, in this way it's more reliable - // to fetch them later - var valObj = {}; - this.model.get('properties').each(function(prop){ - var v = prop.getValue(), - func = prop.get('functionName'); - if(func) - v = func + '(' + v + ')'; - valObj[prop.get('property')] = v; - }); - model.set('values', valObj); + // Store properties values inside layer, in this way it's more reliable + // to fetch them later + var valObj = {}; + this.model.get('properties').each(function(prop){ + var v = prop.getValue(), + func = prop.get('functionName'); + if(func) + v = func + '(' + v + ')'; + valObj[prop.get('property')] = v; + }); + model.set('values', valObj); - model.set('value', result); - return this.createValue(); - }, + model.set('value', result); + return this.createValue(); + }, - /** - * Add layer - * @param Event - * - * @return Object - * */ - addLayer: function(e){ - if(this.getTarget()){ - var layers = this.getLayers(); - var layer = layers.add({ name : 'test' }); - var index = layers.indexOf(layer); - layer.set('value', this.getDefaultValue()); - // In detached mode valueUpdated will add new 'layer value' - // to all subprops - this.valueUpdated(); - // This will set subprops with a new default values - this.model.set('stackIndex', index); - return layer; - } - }, + /** + * Add layer + * @param Event + * + * @return Object + * */ + addLayer: function(e){ + if(this.getTarget()){ + var layers = this.getLayers(); + var layer = layers.add({ name : 'test' }); + var index = layers.indexOf(layer); + layer.set('value', this.getDefaultValue()); + // In detached mode valueUpdated will add new 'layer value' + // to all subprops + this.valueUpdated(); + // This will set subprops with a new default values + this.model.set('stackIndex', index); + return layer; + } + }, - /** - * Fired when the input value is updated - */ - valueUpdated: function(){ - if(!this.model.get('detached')) - this.model.set('value', this.createValue()); - else{ - this.model.get('properties').each(function(prop){ - prop.trigger('change:value'); - }); - } - }, + /** + * Fired when the input value is updated + */ + valueUpdated: function(){ + if(!this.model.get('detached')) + this.model.set('value', this.createValue()); + else{ + this.model.get('properties').each(function(prop){ + prop.trigger('change:value'); + }); + } + }, - /** - * Create value by layers - * @return string - * */ - createValue: function(){ - return this.getStackValues().join(', '); - }, + /** + * Create value by layers + * @return string + * */ + createValue: function(){ + return this.getStackValues().join(', '); + }, - /** - * Render layers - * @return self - * */ - renderLayers: function() { - if(!this.$field) - this.$field = this.$el.find('> .' + this.pfx + 'field'); + /** + * Render layers + * @return self + * */ + renderLayers: function() { + if(!this.$field) + this.$field = this.$el.find('> .' + this.pfx + 'field'); - if(!this.$layers) - this.$layers = new LayersView({ - collection: this.getLayers(), - stackModel: this.model, - preview: this.model.get('preview'), - config: this.config - }); + if(!this.$layers) + this.$layers = new LayersView({ + collection: this.getLayers(), + stackModel: this.model, + preview: this.model.get('preview'), + config: this.config + }); - this.$field.append(this.$layers.render().el); - this.$props.hide(); - return this; - }, + this.$field.append(this.$layers.render().el); + this.$props.hide(); + return this; + }, - /** @inheritdoc */ - renderInput: function() { - PropertyCompositeView.prototype.renderInput.apply(this, arguments); - this.refreshLayers(); - }, + /** @inheritdoc */ + renderInput: function() { + PropertyCompositeView.prototype.renderInput.apply(this, arguments); + this.refreshLayers(); + }, - /** - * Returns array suitale for layers from target style - * Only for detached stacks - * @return {Array} - */ - getLayersFromTarget: function(){ - var arr = []; - var target = this.getTarget(); - if(!target) - return arr; - var trgStyle = target.get('style'); - this.model.get('properties').each(function(prop){ - var style = trgStyle[prop.get('property')]; - if(style){ - var list = style.split(','); - for(var i = 0, len = list.length; i < len; i++){ - var val = list[i].trim(); + /** + * Returns array suitale for layers from target style + * Only for detached stacks + * @return {Array} + */ + getLayersFromTarget: function(){ + var arr = []; + var target = this.getTarget(); + if(!target) + return arr; + var trgStyle = target.get('style'); + this.model.get('properties').each(function(prop){ + var style = trgStyle[prop.get('property')]; + if(style){ + var list = style.split(','); + for(var i = 0, len = list.length; i < len; i++){ + var val = list[i].trim(); - if(arr[i]){ - arr[i][prop.get('property')] = val; - }else{ - var vals = {}; - vals[prop.get('property')] = val; - arr[i] = vals; - } - } - } - }); - return arr; - }, + if(arr[i]){ + arr[i][prop.get('property')] = val; + }else{ + var vals = {}; + vals[prop.get('property')] = val; + arr[i] = vals; + } + } + } + }); + return arr; + }, - /** - * Refresh layers - * */ - refreshLayers: function(){ - var n = []; - var a = []; - var fieldName = 'value'; - if(this.model.get('detached')){ - fieldName = 'values'; - a = this.getLayersFromTarget(); - }else{ - var v = this.getComponentValue(); - if(v){ - // Remove spaces inside functions: - // eg: - // From: 1px 1px rgba(2px, 2px, 2px), 2px 2px rgba(3px, 3px, 3px) - // To: 1px 1px rgba(2px,2px,2px), 2px 2px rgba(3px,3px,3px) - v.replace(/\(([\w\s,.]*)\)/g, function(match){ - var cleaned = match.replace(/,\s*/g, ','); - v = v.replace(match, cleaned); - }); - a = v.split(', '); - } - } - _.each(a, function(e){ - var o = {}; - o[fieldName] = e; - n.push(o); - },this); - this.$props.detach(); - var layers = this.getLayers(); - layers.reset(); - layers.add(n); - if(!this.model.get('detached')) - this.valueUpdated(); - this.model.set({stackIndex: null}, {silent: true}); - }, + /** + * Refresh layers + * */ + refreshLayers: function(){ + var n = []; + var a = []; + var fieldName = 'value'; + if(this.model.get('detached')){ + fieldName = 'values'; + a = this.getLayersFromTarget(); + }else{ + var v = this.getComponentValue(); + if(v){ + // Remove spaces inside functions: + // eg: + // From: 1px 1px rgba(2px, 2px, 2px), 2px 2px rgba(3px, 3px, 3px) + // To: 1px 1px rgba(2px,2px,2px), 2px 2px rgba(3px,3px,3px) + v.replace(/\(([\w\s,.]*)\)/g, function(match){ + var cleaned = match.replace(/,\s*/g, ','); + v = v.replace(match, cleaned); + }); + a = v.split(', '); + } + } + _.each(a, function(e){ + var o = {}; + o[fieldName] = e; + n.push(o); + },this); + this.$props.detach(); + var layers = this.getLayers(); + layers.reset(); + layers.add(n); + if(!this.model.get('detached')) + this.valueUpdated(); + this.model.set({stackIndex: null}, {silent: true}); + }, - render : function(){ - this.renderLabel(); - this.renderField(); - this.renderLayers(); - this.$el.attr('class', this.className); - return this; - }, + render : function(){ + this.renderLabel(); + this.renderField(); + this.renderLayers(); + this.$el.attr('class', this.className); + return this; + }, - }); + }); }); diff --git a/src/style_manager/view/PropertyView.js b/src/style_manager/view/PropertyView.js index a9d0da684..3f928dda7 100644 --- a/src/style_manager/view/PropertyView.js +++ b/src/style_manager/view/PropertyView.js @@ -32,9 +32,13 @@ define(['backbone', 'text!./../templates/propertyLabel.html', 'text!./../templat this.listenTo(this.propTarget, 'update', this.targetUpdated); this.listenTo(this.model, 'destroy remove', this.remove); - this.listenTo(this.model,'change:value', this.valueChanged); - this.listenTo(this.model,'targetUpdated', this.targetUpdated); - this.listenTo(this.model,'change:visible', this.updateVisibility); + this.listenTo(this.model, 'change:value', this.valueChanged); + this.listenTo(this.model, 'targetUpdated', this.targetUpdated); + this.listenTo(this.model, 'change:visible', this.updateVisibility); + + if (this.sector && this.sector.get('name') == 'Decorations') { + console.log(this.sector.get('name')+':', this.property, this.model.get('type')); + } }, /** @@ -61,7 +65,16 @@ define(['backbone', 'text!./../templates/propertyLabel.html', 'text!./../templat targetUpdated: function() { this.selectedComponent = this.propTarget.model; this.helperComponent = this.propTarget.helper; + this.checkVisibility(); + if(this.getTarget()) { + if(!this.sameValue()){ + this.renderInputRequest(); + } + } + }, + + checkVisibility: function () { // Check if need to hide the property if (this.config.hideNotStylable) { if (!this.isTargetStylable() || !this.isComponentStylable()) { @@ -74,12 +87,6 @@ define(['backbone', 'text!./../templates/propertyLabel.html', 'text!./../templat this.sector.trigger('updateVisibility'); } } - - if(this.getTarget()){ - if(!this.sameValue()){ - this.renderInputRequest(); - } - } }, /** diff --git a/src/style_manager/view/SectorView.js b/src/style_manager/view/SectorView.js index 0121ee85f..4722e2509 100644 --- a/src/style_manager/view/SectorView.js +++ b/src/style_manager/view/SectorView.js @@ -29,8 +29,9 @@ define(['backbone', './PropertiesView', 'text!./../templates/sector.html'], updateVisibility: function () { var show; this.model.get('properties').each(function(prop) { - if (prop.get('visible')) + if (prop.get('visible')) { show = 1; + } }); this.el.style.display = show ? 'block' : 'none'; },