/** * @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 }, lengthUnitRegex: /([a-z%]*)$/, 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, 'important'); } } } } 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, 'important'); } } } } } 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, lengthUnit = this.DEFAULT_UNIT_LENGTH, isCustom = this.customProperties[name], transformMethods, method, i, ln, transformValues, values, unit; if (value === null) { return ''; } if (type === 'string') { if (this.lengthProperties[name]) { unit = value.match(this.lengthUnitRegex)[1]; if (unit.length > 0) { //<debug> if (unit !== lengthUnit) { Ext.Logger.error("Length unit: '" + unit + "' in value: '" + value + "' of property: '" + name + "' is not " + "valid for animation. Only 'px' is allowed"); } //</debug> } else { value = value + lengthUnit; if (isCustom) { value = this.getCustomValue(value, name); } return value; } } return value; } else if (type === 'number') { if (value == 0) { return '0'; } if (this.lengthProperties[name]) { value = value + lengthUnit; 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), unit = value.match(this.lengthUnitRegex)[1]; if (name === 'x') { value = el.translateXY(parseInt(value, 10)).x; } else if (name === 'y') { value = el.translateXY(null, parseInt(value, 10)).y; } return value + unit; }});