diff --git a/src/editor/main.js b/src/editor/main.js
index b6a754639..ea8821a33 100644
--- a/src/editor/main.js
+++ b/src/editor/main.js
@@ -30,14 +30,15 @@
* ```
*
* **Available events**
- * #component:add - Triggered when a new component is added to the editor, the model is passed as an argument to the callback
- * #component:update - Triggered when a component is, generally, updated (moved, styled, etc.)
- * #component:styleUpdate - Triggered when the style of the component is updated
- * #component:update:{propertyName} - Listen any property change
- * #canvasScroll - Triggered when the canvas is scrolled
- * #run:{commandName} - Triggered when some command is called to run (eg. editor.runCommand('preview'))
- * #stop:{commandName} - Triggered when some command is called to stop (eg. editor.stopCommand('preview'))
- * #load - When the editor is loaded
+ * component:add - Triggered when a new component is added to the editor, the model is passed as an argument to the callback
+ * component:update - Triggered when a component is, generally, updated (moved, styled, etc.)
+ * component:update:{propertyName} - Listen any property change
+ * component:styleUpdate - Triggered when the style of the component is updated
+ * component:styleUpdate:{propertyName} - Listen for a specific style property change
+ * canvasScroll - Triggered when the canvas is scrolled
+ * run:{commandName} - Triggered when some command is called to run (eg. editor.runCommand('preview'))
+ * stop:{commandName} - Triggered when some command is called to stop (eg. editor.stopCommand('preview'))
+ * load - When the editor is loaded
*
* @module Editor
* @param {Object} config Configurations
diff --git a/src/style_manager/config/config.js b/src/style_manager/config/config.js
index 95aa96aa4..0e8f6b7ec 100644
--- a/src/style_manager/config/config.js
+++ b/src/style_manager/config/config.js
@@ -1,13 +1,17 @@
define(function () {
- return {
+ return {
- stylePrefix: 'sm-',
+ stylePrefix: 'sm-',
- sectors: [],
+ sectors: [],
- // Text to show in case no element selected
- textNoElement: 'Select an element before using Style Manager',
-
- };
+ // Text to show in case no element selected
+ textNoElement: 'Select an element before using Style Manager',
+
+ // Hide the property in case it's not stylable for the
+ // selected component (each component has 'stylable' property)
+ hideNotStylable: true,
+
+ };
});
diff --git a/src/style_manager/view/PropertyView.js b/src/style_manager/view/PropertyView.js
index 93bc0820d..9fb8a0a70 100644
--- a/src/style_manager/view/PropertyView.js
+++ b/src/style_manager/view/PropertyView.js
@@ -1,308 +1,320 @@
define(['backbone', 'text!./../templates/propertyLabel.html', 'text!./../templates/propertyInput.html'],
- function (Backbone, propertyLabel, propertyTemplate) {
- /**
- * @class PropertyView
- * */
- return Backbone.View.extend({
-
- template: _.template(propertyTemplate),
- templateLabel: _.template(propertyLabel),
-
- events: {'change': 'valueUpdated'},
-
- initialize: function(o) {
- this.config = o.config || {};
- this.pfx = this.config.stylePrefix || '';
- this.ppfx = this.config.pStylePrefix || '';
- this.target = o.target || {};
- this.propTarget = o.propTarget || {};
- this.onChange = o.onChange || {};
- this.onInputRender = o.onInputRender || {};
- this.customValue = o.customValue || {};
- this.defaultValue = this.model.get('defaults');
- this.property = this.model.get('property');
- this.input = this.$input = null;
- this.className = this.pfx + 'property';
- this.inputHolderId = '#' + this.pfx + 'input-holder';
-
- if(!this.model.get('value'))
- this.model.set('value', this.model.get('defaults'));
-
- this.listenTo(this.model, 'destroy remove', this.remove);
- this.listenTo( this.propTarget, 'update', this.targetUpdated);
- this.listenTo( this.model ,'change:value', this.valueChanged);
- this.listenTo( this.model ,'targetUpdated', this.targetUpdated);
- },
-
- /**
- * Returns selected target which should have 'style' property
- * @return {Model|null}
- */
- getTarget: function(){
- if(this.selectedComponent)
- return this.selectedComponent;
- return this.propTarget ? this.propTarget.model : null;
- },
-
- /**
- * Fired when the input value is updated
- */
- valueUpdated: function(){
- if(this.$input)
- this.model.set('value', this.getInputValue());
- },
-
- /**
- * Fired when the target is updated
- * */
- targetUpdated: function(){
- this.selectedComponent = this.propTarget.model;
- this.helperComponent = this.propTarget.helper;
- if(this.getTarget()){
- if(!this.sameValue()){
- this.renderInputRequest();
- }
- }
- },
-
- /**
- * Checks if the value from selected component is the
- * same of the value of the model
- *
- * @return {Boolean}
- * */
- sameValue: function(){
- return this.getComponentValue() == (this.model.get('value') + this.model.get('unit'));
- },
-
-
- /**
- * Get the value from the selected component of this property
- *
- * @return {String}
- * */
- getComponentValue: function(){
- var target = this.getTarget();
-
- if(!target)
- return;
-
- var targetProp = target.get('style')[this.property];
- if(targetProp)
- this.componentValue = targetProp;
- else
- this.componentValue = this.defaultValue + (this.unit || ''); // todo model
-
- // Check if wrap inside function is required
- if(this.model.get('functionName')){
- var v = this.fetchFromFunction(this.componentValue);
- if(v)
- this.componentValue = v;
- }
-
- // This allow to ovveride the normal flow of selecting component value,
- // useful in composite properties
- if(this.customValue && typeof this.customValue === "function"){
- var index = this.model.collection.indexOf(this.model);
- var t = this.customValue(this, index);
- if(t)
- this.componentValue = t;
- }
-
- return this.componentValue;
- },
-
- /**
- * Fetch the string from function type value
- * @param {String} v Function type value
- *
- * @return {String}
- * */
- fetchFromFunction: function(v){
- return v.substring(v.indexOf("(") + 1, v.lastIndexOf(")"));
- },
-
- /**
- * Returns value from inputs
- * @return {string}
- */
- getValueForTarget: function(){
- return this.model.getValue();
- },
-
- /**
- * Returns value from input
- * @return {string}
- */
- getInputValue: function(){
- return this.$input ? this.$input.val() : '';
- },
-
- /**
- * Property was changed, so I need to update the component too
- * @param {Object} e Events
- * @param {Mixed} val Value
- * @param {Object} opt Options
- * */
- valueChanged: function(e, val, opt) {
- var mVal = this.getValueForTarget();
-
- if(this.$input)
- this.setValue(mVal);
-
- if(!this.getTarget())
- return;
-
- // Check if component is allowed to be styled
- if(!this.isTargetStylable())
- return;
-
- value = this.getValueForTarget();
-
- var func = this.model.get('functionName');
- if(func)
- value = func + '(' + value + ')';
-
- var target = this.getTarget();
- var onChange = this.onChange;
-
- if(onChange && typeof onChange === "function"){
- onChange(target, this, opt);
- }else
- this.updateTargetStyle(value, null, opt);
+ function (Backbone, propertyLabel, propertyTemplate) {
+ /**
+ * @class PropertyView
+ * */
+ return Backbone.View.extend({
+
+ template: _.template(propertyTemplate),
+ templateLabel: _.template(propertyLabel),
+
+ events: {'change': 'valueUpdated'},
+
+ initialize: function(o) {
+ this.config = o.config || {};
+ this.pfx = this.config.stylePrefix || '';
+ this.ppfx = this.config.pStylePrefix || '';
+ this.target = o.target || {};
+ this.propTarget = o.propTarget || {};
+ this.onChange = o.onChange || {};
+ this.onInputRender = o.onInputRender || {};
+ this.customValue = o.customValue || {};
+ this.defaultValue = this.model.get('defaults');
+ this.property = this.model.get('property');
+ this.input = this.$input = null;
+ this.className = this.pfx + 'property';
+ this.inputHolderId = '#' + this.pfx + 'input-holder';
+
+ if(!this.model.get('value'))
+ this.model.set('value', this.model.get('defaults'));
+
+ this.listenTo(this.model, 'destroy remove', this.remove);
+ this.listenTo( this.propTarget, 'update', this.targetUpdated);
+ this.listenTo( this.model ,'change:value', this.valueChanged);
+ this.listenTo( this.model ,'targetUpdated', this.targetUpdated);
+ },
+
+ /**
+ * Returns selected target which should have 'style' property
+ * @return {Model|null}
+ */
+ getTarget: function(){
+ if(this.selectedComponent)
+ return this.selectedComponent;
+ return this.propTarget ? this.propTarget.model : null;
+ },
+
+ /**
+ * Fired when the input value is updated
+ */
+ valueUpdated: function(){
+ if(this.$input)
+ this.model.set('value', this.getInputValue());
+ },
+
+ /**
+ * Fired when the target is updated
+ * */
+ targetUpdated: function(){
+ this.selectedComponent = this.propTarget.model;
+ this.helperComponent = this.propTarget.helper;
+ if(this.getTarget()){
+ if(!this.sameValue()){
+ this.renderInputRequest();
+ }
+ }
+ },
+
+ /**
+ * Checks if the value from selected component is the
+ * same of the value of the model
+ *
+ * @return {Boolean}
+ * */
+ sameValue: function(){
+ return this.getComponentValue() == (this.model.get('value') + this.model.get('unit'));
+ },
+
+
+ /**
+ * Get the value from the selected component of this property
+ *
+ * @return {String}
+ * */
+ getComponentValue: function(){
+ var target = this.getTarget();
+
+ if(!target)
+ return;
+
+ var targetProp = target.get('style')[this.property];
+ if(targetProp)
+ this.componentValue = targetProp;
+ else
+ this.componentValue = this.defaultValue + (this.unit || ''); // todo model
+
+ // Check if wrap inside function is required
+ if(this.model.get('functionName')){
+ var v = this.fetchFromFunction(this.componentValue);
+ if(v)
+ this.componentValue = v;
+ }
+
+ // This allow to ovveride the normal flow of selecting component value,
+ // useful in composite properties
+ if(this.customValue && typeof this.customValue === "function"){
+ var index = this.model.collection.indexOf(this.model);
+ var t = this.customValue(this, index);
+ if(t)
+ this.componentValue = t;
+ }
+ return this.componentValue;
+ },
+
+ /**
+ * Fetch the string from function type value
+ * @param {String} v Function type value
+ *
+ * @return {String}
+ * */
+ fetchFromFunction: function(v){
+ return v.substring(v.indexOf("(") + 1, v.lastIndexOf(")"));
+ },
+
+ /**
+ * Returns value from inputs
+ * @return {string}
+ */
+ getValueForTarget: function(){
+ return this.model.getValue();
+ },
+
+ /**
+ * Returns value from input
+ * @return {string}
+ */
+ getInputValue: function(){
+ return this.$input ? this.$input.val() : '';
+ },
+
+ /**
+ * Property was changed, so I need to update the component too
+ * @param {Object} e Events
+ * @param {Mixed} val Value
+ * @param {Object} opt Options
+ * */
+ valueChanged: function(e, val, opt) {
+ var mVal = this.getValueForTarget();
var em = this.config.em;
+ var model = this.model;
+
+ if(this.$input)
+ this.setValue(mVal);
+
+ if(!this.getTarget())
+ return;
+
+ // Check if component is allowed to be styled
+ var hideNoStyle = this.config.hideNotStylable;
+ if (!this.isTargetStylable()) {
+ if (hideNoStyle) {
+ this.hide();
+ }
+ return;
+ } else {
+ this.show();
+ }
+
+ value = this.getValueForTarget();
+
+ var func = model.get('functionName');
+ if(func)
+ value = func + '(' + value + ')';
+
+ var target = this.getTarget();
+ var onChange = this.onChange;
+
+ if(onChange && typeof onChange === "function"){
+ onChange(target, this, opt);
+ }else
+ this.updateTargetStyle(value, null, opt);
+
if(em){
- var model = this.model;
em.trigger('component:update', model);
em.trigger('component:styleUpdate', model);
em.trigger('component:styleUpdate:' + model.get('property'), model);
}
- },
-
- /**
- * Update target style
- * @param {string} propertyValue
- * @param {string} propertyName
- * @param {Object} opts
- */
- updateTargetStyle: function(propertyValue, propertyName, opts){
- var propName = propertyName || this.property;
- var value = propertyValue || '';
- var avSt = opts ? opts.avoidStore : 0;
- var target = this.getTarget();
- var targetStyle = _.clone(target.get('style'));
-
- if(value)
- targetStyle[propName] = value;
- else
- delete targetStyle[propName];
-
- target.set('style', targetStyle, { avoidStore : avSt});
-
- if(this.helperComponent)
- this.helperComponent.set('style', targetStyle, { avoidStore : avSt});
- },
-
- /**
- * Check if target is stylable with this property
- * @return {Boolean}
- */
- isTargetStylable: function(){
- var stylable = this.getTarget().get('stylable');
- // Stylable could also be an array indicating with which property
- // the target could be styled
- if(stylable instanceof Array)
- stylable = _.indexOf(stylable, this.property) >= 0;
- return stylable;
- },
-
- /**
- * Set value to the input
- * @param {String} value
- * @param {Boolean} force
- * */
- setValue: function(value, force){
- var f = force === 0 ? 0 : 1;
- var def = this.model.get('defaults');
- var v = this.model.get('value') || def;
- if(value || f){
- v = value;
- }
- if(this.$input)
- this.$input.val(v);
- this.model.set({value: v}, {silent: true});
- },
-
- /**
- * Render label
- * */
- renderLabel: function(){
- this.$el.html( this.templateLabel({
- pfx : this.pfx,
- ppfx : this.ppfx,
- icon : this.model.get('icon'),
- info : this.model.get('info'),
- label : this.model.get('name'),
- }));
- },
-
- /**
- * Render field property
- * */
- renderField : function() {
- this.renderTemplate();
- this.renderInput();
- delete this.componentValue;
- },
-
- /**
- * Render loaded template
- * */
- renderTemplate: function(){
- this.$el.append( this.template({
- pfx : this.pfx,
- ppfx : this.ppfx,
- icon : this.model.get('icon'),
- info : this.model.get('info'),
- label : this.model.get('name'),
- }));
- },
-
- /**
- * Renders input, to override
- * */
- renderInput: function(){
- if(!this.$input){
- this.$input = $('', {
- placeholder: this.model.get('defaults'),
- type: 'text'
- });
- this.$el.find(this.inputHolderId).html(this.$input);
- }
- this.setValue(this.componentValue, 0);
- },
-
- /**
- * Request to render input of the property
- * */
- renderInputRequest: function(){
- this.renderInput();
- },
-
- /**
- * Clean input
- * */
- cleanValue: function(){
- this.setValue('');
- },
-
- render : function(){
- this.renderLabel();
- this.renderField();
- this.$el.attr('class', this.className);
- return this;
- },
-
- });
+ },
+
+ /**
+ * Update target style
+ * @param {string} propertyValue
+ * @param {string} propertyName
+ * @param {Object} opts
+ */
+ updateTargetStyle: function(propertyValue, propertyName, opts){
+ var propName = propertyName || this.property;
+ var value = propertyValue || '';
+ var avSt = opts ? opts.avoidStore : 0;
+ var target = this.getTarget();
+ var targetStyle = _.clone(target.get('style'));
+
+ if(value)
+ targetStyle[propName] = value;
+ else
+ delete targetStyle[propName];
+
+ target.set('style', targetStyle, { avoidStore : avSt});
+
+ if(this.helperComponent)
+ this.helperComponent.set('style', targetStyle, { avoidStore : avSt});
+ },
+
+ /**
+ * Check if target is stylable with this property
+ * @return {Boolean}
+ */
+ isTargetStylable: function(){
+ var stylable = this.getTarget().get('stylable');
+ // Stylable could also be an array indicating with which property
+ // the target could be styled
+ if(stylable instanceof Array)
+ stylable = _.indexOf(stylable, this.property) >= 0;
+ return stylable;
+ },
+
+ /**
+ * Set value to the input
+ * @param {String} value
+ * @param {Boolean} force
+ * */
+ setValue: function(value, force){
+ var f = force === 0 ? 0 : 1;
+ var def = this.model.get('defaults');
+ var v = this.model.get('value') || def;
+ if(value || f){
+ v = value;
+ }
+ if(this.$input)
+ this.$input.val(v);
+ this.model.set({value: v}, {silent: true});
+ },
+
+ show: function () {
+ this.el.style.display = 'block';
+ },
+
+ hide: function () {
+ this.el.style.display = 'none';
+ },
+
+ renderLabel: function(){
+ this.$el.html( this.templateLabel({
+ pfx : this.pfx,
+ ppfx : this.ppfx,
+ icon : this.model.get('icon'),
+ info : this.model.get('info'),
+ label : this.model.get('name'),
+ }));
+ },
+
+ /**
+ * Render field property
+ * */
+ renderField : function() {
+ this.renderTemplate();
+ this.renderInput();
+ delete this.componentValue;
+ },
+
+ /**
+ * Render loaded template
+ * */
+ renderTemplate: function(){
+ this.$el.append( this.template({
+ pfx : this.pfx,
+ ppfx : this.ppfx,
+ icon : this.model.get('icon'),
+ info : this.model.get('info'),
+ label : this.model.get('name'),
+ }));
+ },
+
+ /**
+ * Renders input, to override
+ * */
+ renderInput: function(){
+ if(!this.$input){
+ this.$input = $('', {
+ placeholder: this.model.get('defaults'),
+ type: 'text'
+ });
+ this.$el.find(this.inputHolderId).html(this.$input);
+ }
+ this.setValue(this.componentValue, 0);
+ },
+
+ /**
+ * Request to render input of the property
+ * */
+ renderInputRequest: function(){
+ this.renderInput();
+ },
+
+ /**
+ * Clean input
+ * */
+ cleanValue: function(){
+ this.setValue('');
+ },
+
+ render : function(){
+ this.renderLabel();
+ this.renderField();
+ this.$el.attr('class', this.className);
+ return this;
+ },
+
+ });
});