diff --git a/src/demo.js b/src/demo.js index abe7cfd45..1f27c3181 100644 --- a/src/demo.js +++ b/src/demo.js @@ -619,7 +619,7 @@ require(['config/require-config'], function() { name : 'Text shadow', property : 'text-shadow', type : 'stack', - detached : true, + detached: true, preview : true, properties : [{ name: 'X position', diff --git a/src/style_manager/view/LayerView.js b/src/style_manager/view/LayerView.js index a082cd1dd..c3b716e20 100644 --- a/src/style_manager/view/LayerView.js +++ b/src/style_manager/view/LayerView.js @@ -98,7 +98,7 @@ define(['backbone', 'text!./../templates/layer.html'], if(this.stackModel.get){ var property = this.stackModel.get('property'); if(property) - this.$preview.get(0).style[property] = nV; //css(property, this.model.get('valuePreview')); + this.$preview.get(0).style[property] = nV; } }, diff --git a/src/style_manager/view/PropertyCompositeView.js b/src/style_manager/view/PropertyCompositeView.js index 048b30d18..11c1999fd 100644 --- a/src/style_manager/view/PropertyCompositeView.js +++ b/src/style_manager/view/PropertyCompositeView.js @@ -76,7 +76,7 @@ define(['backbone','./PropertyView', 'text!./../templates/propertyComposite.html // Each child property will receive a full composite string, eg. '0px 0px 10px 0px' // I need to extract from that string the corresponding one to that property. customValue: function(property, mIndex){ - return that.valueOnIndex(mIndex, property.model); + return that.valueOnIndex(mIndex, property); }, }; @@ -102,15 +102,15 @@ define(['backbone','./PropertyView', 'text!./../templates/propertyComposite.html /** * Extract string from composite value * @param {number} index Index - * @param {Object} model Property model + * @param {Object} view Property view * @return {string} * */ - valueOnIndex: function(index, model){ + valueOnIndex: function(index, view){ var result = null; var a = this.getComponentValue().split(' '); if(a.length && a[index]){ result = a[index]; - if(model && model.get('functionName')){ + if(view && view.model && view.model.get('functionName')){ var v = this.fetchFromFunction(result); if(v) result = v; diff --git a/src/style_manager/view/PropertyStackView.js b/src/style_manager/view/PropertyStackView.js index c439d402a..2d7b82b54 100644 --- a/src/style_manager/view/PropertyStackView.js +++ b/src/style_manager/view/PropertyStackView.js @@ -10,14 +10,25 @@ define(['backbone','./PropertyCompositeView', 'text!./../templates/propertyStack initialize: function(o) { PropertyCompositeView.prototype.initialize.apply(this, arguments); this.model.set('stackIndex', null); - this.listenTo( this.model ,'change:stackIndex', this.indexChanged); - this.listenTo( this.model ,'updateValue', this.valueUpdated); 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(); + }, + /** * Returns the collection of layers * @return {Collection} @@ -37,6 +48,9 @@ define(['backbone','./PropertyCompositeView', 'text!./../templates/propertyStack 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'); + }); }, /** @@ -51,10 +65,10 @@ define(['backbone','./PropertyCompositeView', 'text!./../templates/propertyStack getPropsConfig: function(opts){ var that = this; var result = PropertyCompositeView.prototype.getPropsConfig.apply(this, arguments); + result.onChange = function(el, view, opt){ var model = view.model; - // This will update the layer value - var result = that.build(el, model); + var result = that.build(); if(that.model.get('detached')){ var propVal = ''; @@ -68,24 +82,41 @@ define(['backbone','./PropertyCompositeView', 'text!./../templates/propertyStack }else that.model.set('value', result); }; + return result; }, /** * Extract string from composite value * @param integer Index + * @param View propView Property view * @return string * */ - valueOnIndex: function(index){ + valueOnIndex: function(index, propView){ var result = null; - 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]; + // If detached the value in this case is stacked, eg. substack-prop: 1px, 2px, 3px... + if(this.model.get('detached')){ + //var aStackDet = this.getStackValues(); + //console.log('Stack values'); + //console.log(aStackDet); + var valist = propView.componentValue.split(','); + result = valist[this.model.get('stackIndex')]; + // In detached mode the value of the property never changed + // so I need some how to update + if(result !== propView.getValueForTarget()){ + //UPDATE?!? + //this.refreshLayers(); NO!! + } + //console.log(propView.property + ' model: ' + propView.getValueForTarget() + ' found on comp: ' + 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; }, @@ -99,7 +130,7 @@ define(['backbone','./PropertyCompositeView', 'text!./../templates/propertyStack var model = this.getLayers().at(stackIndex); if(!model) return; - model.set('value',result); + model.set('value', result); return this.createValue(); }, @@ -115,7 +146,10 @@ define(['backbone','./PropertyCompositeView', 'text!./../templates/propertyStack 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; } @@ -169,28 +203,52 @@ define(['backbone','./PropertyCompositeView', 'text!./../templates/propertyStack this.refreshLayers(); }, + /** + * Returns array suitale for layers from target style + * @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] += ' ' + val; + else + arr[i] = val; + } + } + }); + return arr; + }, + /** * Refresh layers * */ refreshLayers: function(){ - var v = this.getComponentValue(); var n = []; - if(v){ - var a = v.split(', '); - _.each(a,function(e){ - n.push({ - value: e, - valuePreview: e, - propertyPreview: this.property, - patternPreview: this.props - }); - },this); + var a = []; + if(this.model.get('detached')){ + a = this.getLayersFromTarget(); + }else{ + var v = this.getComponentValue(); + if(v) + a = v.split(', '); } + _.each(a,function(e){ n.push({ value: e});},this); this.$props.detach(); var layers = this.getLayers(); layers.reset(); layers.add(n); - this.valueUpdated(); + if(!this.model.get('detached')) + this.valueUpdated(); this.model.set({stackIndex: null}, {silent: true}); }, diff --git a/src/style_manager/view/PropertyView.js b/src/style_manager/view/PropertyView.js index 3435ff358..e2e618a7e 100644 --- a/src/style_manager/view/PropertyView.js +++ b/src/style_manager/view/PropertyView.js @@ -29,6 +29,7 @@ define(['backbone', 'text!./../templates/propertyLabel.html', 'text!./../templat this.listenTo( this.propTarget, 'update', this.targetUpdated); this.listenTo( this.model ,'change:value', this.valueChanged); + this.listenTo( this.model ,'targetUpdated', this.targetUpdated); }, /** diff --git a/test/specs/style_manager/view/PropertyStackView.js b/test/specs/style_manager/view/PropertyStackView.js index 9d9573f56..1f2c34fff 100644 --- a/test/specs/style_manager/view/PropertyStackView.js +++ b/test/specs/style_manager/view/PropertyStackView.js @@ -169,6 +169,7 @@ define([path + 'PropertyStackView', 'StyleManager/model/Property', 'DomComponent prop2Val = properties[1].defaults; prop2Unit = properties[1].units[0]; finalResult = propValue + ' ' + prop2Val + prop2Unit +' ' + prop3Val; + view.addLayer(); $prop1 = view.$props.find('#' + properties[0].property + ' input'); $prop2 = view.$props.find('#' + properties[1].property + ' input'); $prop3 = view.$props.find('#' + properties[2].property + ' select'); @@ -194,55 +195,40 @@ define([path + 'PropertyStackView', 'StyleManager/model/Property', 'DomComponent compStyle.should.deep.equal(assertStyle); }); - it('Update target on detached value change', function() { - model = new Property({ - type: 'stack', - property: propName, - properties: properties, - detached: true, - }); - view = new PropertyStackView({ - model: model, - propTarget: target - }); - $fixture.html(view.render().el); - $prop1 = view.$props.find('#' + properties[0].property + ' input'); - $prop1.val(propValue).trigger('change'); - var compStyle = view.getTarget().get('style'); - var assertStyle = {}; - assertStyle[properties[0].property] = $prop1.val(); - compStyle.should.deep.equal(assertStyle); - }); - it('Update value and input on target swap', function() { var style = {}; - style[propName] = finalResult; + var finalResult2 = 'A B C'; + style[propName] = finalResult + ', ' + finalResult2; component.set('style', style); view.propTarget.trigger('update'); - $prop1.val().should.equal(propValue); - $prop3.val().should.equal(prop3Val); + var layers = view.getLayers(); + layers.at(0).get('value').should.equal(finalResult); + layers.at(1).get('value').should.equal(finalResult2); }); it('Update value after multiple swaps', function() { var style = {}; + var finalResult2 = 'A2 B2 C2'; style[propName] = finalResult; component.set('style', style); view.propTarget.trigger('update'); - style[propName] = propValue + '2 ' + prop2Val + '2' + prop2Unit + ' ' + 'val1'; + style[propName] = finalResult + ', ' + finalResult2; component.set('style', style); view.propTarget.trigger('update'); - $prop1.val().should.equal(propValue + '2'); - $prop2.val().should.equal('2'); - $prop3.val().should.equal('val1'); + var layers = view.getLayers(); + layers.at(0).get('value').should.equal(finalResult); + layers.at(1).get('value').should.equal(finalResult2); }); it('The value is correctly extracted from the composite string', function() { var style = {}; - style[propName] = 'value1 value2 value3 value4'; + style[propName] = 'value1 value2, value3 value4'; component.set('style', style); - view.valueOnIndex(2).should.equal('value3'); - view.valueOnIndex(0).should.equal('value1'); - (view.valueOnIndex(4) === null).should.equal(true); + view.propTarget.trigger('update'); + view.model.set('stackIndex', 1); + view.valueOnIndex(0).should.equal('value3'); + view.valueOnIndex(1).should.equal('value4'); + (view.valueOnIndex(2) === null).should.equal(true); }); it('Build value from properties', function() { @@ -251,26 +237,71 @@ define([path + 'PropertyStackView', 'StyleManager/model/Property', 'DomComponent view.build().should.equal(finalResult); }); - }) + }); + + describe('Detached with target setted', function() { - describe('Init property', function() { + var prop2Val; + var prop3Val; + var prop2Unit; + var finalResult; + var $prop1; + var $prop2; + var $prop3; + var compStyle = { + subprop1: '1px, 20px, 30px', + subprop2: 'A, B, C', + subprop3: 'W, X, Y', + subprop555: 'T, T, T', + }; beforeEach(function () { model = new Property({ type: 'stack', property: propName, properties: properties, - defaults: defValue, + detached: true, }); view = new PropertyStackView({ - model: model + model: model, + propTarget: target }); - $fixture.empty().appendTo($fixtures); $fixture.html(view.render().el); + prop3Val = properties[2].list[2].value; + prop2Val = properties[1].defaults; + prop2Unit = properties[1].units[0]; + finalResult = propValue + ' ' + prop2Val + prop2Unit +' ' + prop3Val; + view.addLayer(); + $prop1 = view.$props.find('#' + properties[0].property + ' input'); + $prop2 = view.$props.find('#' + properties[1].property + ' input'); + $prop3 = view.$props.find('#' + properties[2].property + ' select'); + }); + + it('Returns correctly layers array from target', function() { + component.set('style', compStyle); + var result = ['1px A W', '20px B X', '30px C Y']; + view.getLayersFromTarget().should.have.same.members(result); + }); + + it('Update target on detached value change', function() { + $prop1.val(propValue).trigger('change'); + var compStyle = view.getTarget().get('style'); + var assertStyle = {}; + assertStyle[properties[0].property] = $prop1.val(); + assertStyle[properties[1].property] = '0%'; + assertStyle[properties[2].property] = properties[2].defaults; + compStyle.should.deep.equal(assertStyle); }); - it('Value as default', function() { - view.model.get('value').should.equal(defValue); + it('Update value and input on target swap', function() { + var style = {}; + component.set('style', compStyle); + view.propTarget.trigger('update'); + var layers = view.getLayers(); + layers.length.should.equal(3); + layers.at(0).get('value').should.equal('1px A W'); + layers.at(1).get('value').should.equal('20px B X'); + layers.at(2).get('value').should.equal('30px C Y'); }); });