Created
October 23, 2014 04:04
-
-
Save huafu/7de66f0b6ee4d1788af7 to your computer and use it in GitHub Desktop.
Add a `styleBindings` property to views which can be used like `attributeBindings`. Support units as well.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
/** | |
* @mixin WithStyleMixin | |
*/ | |
var WithStyleMixin = Ember.Mixin.create({ | |
concatenatedProperties: ['styleBindings'], | |
attributeBindings: ['style'], | |
/** | |
* Define each style binding as you'd do with `attributeBindings` with one added feature: the units | |
* If no unit is defined, the value of the property is used as the style if it is not null or undefined | |
* If a unit is defined it is appended to the style value only if the value is recognized as a number | |
* and if this number is not 0. | |
* To define the unit, append it to the style binding around brackets. | |
* | |
* @example | |
* ```javascript | |
* styleBindings: [ | |
* // use the `display` property as the `display` style value: | |
* 'display', | |
* | |
* // use the `width` property as the `width` style value using `px` as the unit: | |
* 'width[px]', | |
* | |
* // use the `myHeightProperty` as the `height` style value using `%` as the unit: | |
* 'myHeightProperty:height[%]' | |
* ] | |
* ``` | |
* | |
* @property styleBindings | |
* @type Array<String> | |
*/ | |
styleBindings: Ember.required(), | |
/** | |
* @property styleBindingsMap | |
* @type Object<Object> | |
*/ | |
styleBindingsMap: function () { | |
var res = {}, match, cssProp, emberProp, unit, | |
bindings = this.get('styleBindings'); | |
for (var i = 0; i < bindings.length; i++) { | |
if ((match = bindings[i].match(/^(([^:]+):)?([a-z0-9_\.-]+)(\[([a-z%]+)\])?$/i))) { | |
cssProp = match[3]; | |
emberProp = match[2] || cssProp; | |
unit = match[5]; | |
res[cssProp] = { property: emberProp, unit: unit }; | |
} | |
} | |
return res; | |
}.property('styleBindings.@each').readOnly(), | |
/** | |
* @property style | |
* @type String | |
*/ | |
style: function () { | |
var map = this.get('styleBindingsMap'); | |
var props = [], cssVal, unit; | |
for (var cssProp in map) { | |
cssVal = this.get(map[cssProp].property); | |
if (cssVal !== undefined && cssVal !== null) { | |
unit = map[cssProp].unit; | |
cssVal = '' + cssVal; | |
unit = unit && cssVal !== '0' && /^[0-9\.]+$/.test(cssVal) ? unit : ''; | |
props.push(cssProp + ': ' + cssVal + unit); | |
} | |
} | |
return props.join('; '); | |
}.property().readOnly(), | |
/** | |
* Schedule the notification of the change of the style property | |
* @method _notifyStyleChange | |
* @private | |
*/ | |
_notifyStyleChange: function () { | |
Ember.run.once(this, 'notifyPropertyChange', 'style'); | |
}, | |
/** | |
* Start listening for any style related property change | |
* @method _initWithStyleMixin | |
* @private | |
*/ | |
_initWithStyleMixin: function () { | |
var map = this.get('styleBindingsMap'); | |
for (var k in map) { | |
this.addObserver(map[k].property, this, '_notifyStyleChange'); | |
} | |
}.observes('styleBindings.@each').on('init'), | |
/** | |
* Stop listening for any style related property change | |
* @method _destroyWithStyleMixin | |
* @private | |
*/ | |
_destroyWithStyleMixin: function () { | |
var map = this.get('styleBindingsMap'); | |
for (var k in map) { | |
this.removeObserver(map[k].property, this, '_notifyStyleChange'); | |
} | |
}.observesBefore('styleBindings.@each').on('destroy') | |
}); | |
export default WithStyleMixin; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example use-case: