/**
* @private
*/
Ext.define('Ext.fx.runner.Css', {
extend: 'Ext.Evented',
requires: [
'Ext.fx.Animation'
],
prefixedProperties: {
'transform': true,
'transform-origin': true,
'perspective': true,
'transform-style': true,
'transition': true,
'transition-property': true,
'transition-duration': true,
'transition-timing-function': true,
'transition-delay': true,
'animation': true,
'animation-name': true,
'animation-duration': true,
'animation-iteration-count': true,
'animation-direction': true,
'animation-timing-function': true,
'animation-delay': true
},
lengthProperties: {
'top': true,
'right': true,
'bottom': true,
'left': true,
'width': true,
'height': true,
'max-height': true,
'max-width': true,
'min-height': true,
'min-width': true,
'margin-bottom': true,
'margin-left': true,
'margin-right': true,
'margin-top': true,
'padding-bottom': true,
'padding-left': true,
'padding-right': true,
'padding-top': true,
'border-bottom-width': true,
'border-left-width': true,
'border-right-width': true,
'border-spacing': true,
'border-top-width': true,
'border-width': true,
'outline-width': true,
'letter-spacing': true,
'line-height': true,
'text-indent': true,
'word-spacing': true,
'font-size': true,
'translate': true,
'translateX': true,
'translateY': true,
'translateZ': true,
'translate3d': true,
'x': true,
'y': true
},
durationProperties: {
'transition-duration': true,
'transition-delay': true,
'animation-duration': true,
'animation-delay': true
},
angleProperties: {
rotate: true,
rotateX: true,
rotateY: true,
rotateZ: true,
skew: true,
skewX: true,
skewY: true
},
DEFAULT_UNIT_LENGTH: 'px',
DEFAULT_UNIT_ANGLE: 'deg',
DEFAULT_UNIT_DURATION: 'ms',
customProperties: {
x: true,
y: true
},
formattedNameCache: {
'x': 'left',
'y': 'top'
},
transformMethods3d: [
'translateX',
'translateY',
'translateZ',
'rotate',
'rotateX',
'rotateY',
'rotateZ',
'skewX',
'skewY',
'scaleX',
'scaleY',
'scaleZ'
],
transformMethodsNo3d: [
'translateX',
'translateY',
'rotate',
'skewX',
'skewY',
'scaleX',
'scaleY'
],
constructor: function() {
var me = this;
me.transformMethods = Ext.feature.has.Css3dTransforms
? me.transformMethods3d
: me.transformMethodsNo3d;
me.vendorPrefix = Ext.browser.getStyleDashPrefix();
me.ruleStylesCache = {};
me.callParent();
},
getStyleSheet: function() {
var styleSheet = this.styleSheet,
styleElement, styleSheets;
if (!styleSheet) {
styleElement = document.createElement('style');
styleElement.type = 'text/css';
(document.head || document.getElementsByTagName('head')[0]).appendChild(styleElement);
styleSheets = document.styleSheets;
this.styleSheet = styleSheet = styleSheets[styleSheets.length - 1];
}
return styleSheet;
},
applyRules: function(selectors) {
var styleSheet = this.getStyleSheet(),
ruleStylesCache = this.ruleStylesCache,
rules = styleSheet.cssRules,
selector, properties, ruleStyle,
ruleStyleCache, rulesLength, name, value;
for (selector in selectors) {
properties = selectors[selector];
ruleStyle = ruleStylesCache[selector];
if (ruleStyle === undefined) {
rulesLength = rules.length;
styleSheet.insertRule(selector + '{}', rulesLength);
ruleStyle = ruleStylesCache[selector] = rules.item(rulesLength).style;
}
ruleStyleCache = ruleStyle.$cache;
if (!ruleStyleCache) {
ruleStyleCache = ruleStyle.$cache = {};
}
for (name in properties) {
value = this.formatValue(properties[name], name);
name = this.formatName(name);
if (ruleStyleCache[name] !== value) {
ruleStyleCache[name] = value;
if (value === null) {
ruleStyle.removeProperty(name);
}
else {
ruleStyle.setProperty(name, value);
}
}
}
}
return this;
},
applyStyles: function(styles) {
var id, element, elementStyle, properties, name, value;
for (id in styles) {
if (styles.hasOwnProperty(id)) {
this.activeElement = element = document.getElementById(id);
if (!element) {
continue;
}
elementStyle = element.style;
properties = styles[id];
for (name in properties) {
if (properties.hasOwnProperty(name)) {
value = this.formatValue(properties[name], name);
name = this.formatName(name);
if (value === null) {
elementStyle.removeProperty(name);
}
else {
elementStyle.setProperty(name, value);
}
}
}
}
}
this.activeElement = null;
return this;
},
formatName: function(name) {
var cache = this.formattedNameCache,
formattedName = cache[name];
if (!formattedName) {
if ((Ext.os.is.Tizen || !Ext.feature.has.CssTransformNoPrefix) &&
this.prefixedProperties[name]) {
formattedName = this.vendorPrefix + name;
}
else {
formattedName = name;
}
cache[name] = formattedName;
}
return formattedName;
},
formatValue: function(value, name) {
var type = typeof value,
defaultLengthUnit = this.DEFAULT_UNIT_LENGTH,
isCustom = this.customProperties[name],
transformMethods,
method, i, ln,
transformValues, values;
if (value === null) {
return '';
}
if (type === 'string') {
if (this.lengthProperties[name]) {
if (!Ext.dom.Element.hasUnit(value)) {
value = value + defaultLengthUnit;
if (isCustom) {
value = this.getCustomValue(value, name);
}
}
}
return value;
}
else if (type === 'number') {
if (value === 0) {
return '0';
}
if (this.lengthProperties[name]) {
value = value + defaultLengthUnit;
if (isCustom) {
value = this.getCustomValue(value, name);
}
return value;
}
if (this.angleProperties[name]) {
return value + this.DEFAULT_UNIT_ANGLE;
}
if (this.durationProperties[name]) {
return value + this.DEFAULT_UNIT_DURATION;
}
}
else if (name === 'transform') {
transformMethods = this.transformMethods;
transformValues = [];
for (i = 0, ln = transformMethods.length; i < ln; i++) {
method = transformMethods[i];
transformValues.push(method + '(' + this.formatValue(value[method], method) + ')');
}
return transformValues.join(' ');
}
else if (Ext.isArray(value)) {
values = [];
for (i = 0, ln = value.length; i < ln; i++) {
values.push(this.formatValue(value[i], name));
}
return (values.length > 0) ? values.join(', ') : 'none';
}
return value;
},
getCustomValue: function(value, name) {
var el = Ext.fly(this.activeElement);
if (name === 'x') {
value = el.translateXY(parseInt(value, 10)).x;
}
else if (name === 'y') {
value = el.translateXY(null, parseInt(value, 10)).y;
}
return value + this.DEFAULT_UNIT_LENGTH;
}
});