1 goog.provide('lime.style');
  2 goog.provide('lime.style.Transform');
  3 
  4 goog.require('goog.dom');
  5 goog.require('goog.style');
  6 goog.require('lime.userAgent');
  7 
  8 (function() {
  9 
 10 var prefix = goog.userAgent.WEBKIT ? 'Webkit' :
 11              goog.userAgent.GECKO ? 'Moz' :
 12              goog.userAgent.OPERA ? 'O' :
 13              goog.userAgent.IE ? 'ms' : '';
 14 
 15 var testDivStyle = goog.dom.createDom('div').style;
 16 
 17 lime.style.transformProperty = '-' + prefix.toLowerCase() + '-transform';
 18 
 19 /**
 20  * Try if a CSS style property with given name exists
 21  * @param {string} name Property name.
 22  * @return {boolean|string} If property exists.
 23  */
 24 lime.style.tryProperty = function(name) {
 25     return testDivStyle[name] !== undefined ? name : false;
 26 };
 27 
 28 /**
 29  * Get the name of actual CSS property from general(unprefixed) name
 30  * @param {string} name Unprefixed name.
 31  * @return {string} Actual valid property name.
 32  */
 33 lime.style.getCSSproperty = function(name) {
 34     var name_lower = name.charAt(0).toLowerCase() + name.substr(1),
 35         prefix_name = prefix + name;
 36     return lime.style.tryProperty(name) ?
 37         name : (lime.style.tryProperty(name_lower)  ?
 38                 name_lower : lime.style.tryProperty(prefix_name) ?
 39                 prefix_name : undefined );
 40 };
 41 
 42 /**
 43  * Set border radisu of a DOM element
 44  * @param {Element} el Element to change.
 45  * @param {Array.<number>} values Radius values.
 46  * @param {Array.<number>=} opt_vertical Vertical radius values.
 47  * @param {boolean=} opt_isPerc If values are given in percentages.
 48  */
 49 lime.style.setBorderRadius = (function() {
 50     var stylename = lime.style.getCSSproperty('BorderRadius');
 51     var out = function(values, unit) {
 52         return (goog.isArray(values) ? values.join(unit + ' ') : values) + unit;
 53     };
 54     return function(el, values, opt_vertical, opt_isPerc) {
 55         var unit = opt_isPerc ? '%' : 'px';
 56         var vertical = goog.isDef(opt_vertical) ? opt_vertical : values;
 57         var value = out(values, unit) + '/' + out(vertical, unit);
 58         if (value != el.border_radius_cache_) {
 59             el.style[stylename] = el.border_radius_cache_ = value;
 60         }
 61     };
 62 })();
 63 
 64 // There are classes like CSSMatrix in some browsers.
 65 // Maybe this would make more sense.
 66 
 67 (function(){
 68 
 69 /**
 70  * Object representing CSS Transform.
 71  * @constructor
 72  * @param {number=} opt_precision Default precision.
 73  */
 74 lime.style.Transform = function(opt_precision) {
 75     this.values = [];
 76     this.precision = 1;
 77     if (this.opt_precision) {
 78         this.setPrecision(/** @type {number} */ (opt_precision));
 79     }
 80 };
 81 
 82 /**
 83  * Scale current transform object
 84  * @param {number} sx X-axis scale factor.
 85  * @param {number} sy y-axis scale factor.
 86  * @return {lime.style.Transform} obejct itself.
 87  */
 88 lime.style.Transform.prototype.scale = function(sx, sy) {
 89     //if(sx!=1 && sy!=1)
 90     this.values.push('scale(' + sx + ',' + sy + ')');
 91     return this;
 92 };
 93 
 94 /**
 95  * Rotate current transform object
 96  * @param {number} angle Angle to rotate.
 97  * @param {string=} opt_unit Units.
 98  * @return {lime.style.Transform} obejct itself.
 99  */
100 lime.style.Transform.prototype.rotate = function(angle, opt_unit) {
101     var rot_str = 'rotate(' + angle + (opt_unit ? opt_unit : 'deg') + ')';
102     if (angle != 0)
103         this.values.push(rot_str);
104 
105     return this;
106 };
107 
108 /**
109  * Translate(move) current transform object
110  * @param {number} tx Offset in x-axis.
111  * @param {number} ty Offset in y-axis.
112  * @param {number=} opt_tz Offset in z-axis.
113  * @return {lime.style.Transform} obejct itself.
114  */
115 lime.style.Transform.prototype.translate = function(tx, ty, opt_tz) {
116 
117     var p = 1 / this.precision;
118     var val = 'translate';
119     if (lime.userAgent.IOS) val += '3d';
120     val += '(' + (tx * p) + 'px,' + (ty * p) + 'px';
121     if (lime.userAgent.IOS) val += ',' + ((opt_tz ? opt_tz : 0) * p) + 'px';
122     this.values.push(val + ')');
123     
124     return this;
125 };
126 
127 /**
128  * Set the current precision of transform. This is handled as a
129  * state machine so its added when called not when done.
130  * @param {number} p Precision(Lowest value to make a difference).
131  * @return {lime.style.Transform} obejct itself.
132  */
133 lime.style.Transform.prototype.setPrecision = function(p) {
134     if (this.precision != 1) {
135         var opposite = 1 / this.precision;
136         this.scale(opposite, opposite);
137         this.precision = 1;
138     }
139     if (p != 1) {
140         this.scale(p, p);
141         this.precision = p;
142     }
143     return this;
144 };
145 
146 /**
147  * Return CSS transform string from the obejct
148  * @return {string} CSS value string.
149  */
150 lime.style.Transform.prototype.toString = function() {
151     if (this.precision != 1) {
152         this.setPrecision(1);
153     }
154     return this.values.join(' ');
155 };
156 
157 /**
158  * Set transform to a DOM element.
159  * @param {Element} el Element to change.
160  * @param {lime.style.Transform} transform Transform.
161  */
162 lime.style.setTransform = (function() {
163     var stylename = lime.style.getCSSproperty('Transform');
164     return function(el, transform) {
165         var value = transform.toString();
166         
167         if (value != el.transform_cache_) {
168             el.style[stylename] = el.transform_cache_ = value;
169         }
170         lime.transformSet_=1;
171         
172     };
173 })();
174 
175 })();
176 
177 /**
178  * Set transform origin point for a DOM element.
179  * @param {Element} el Element to change.
180  * @param {number} ox X Offset.
181  * @param {number} oy Y Offset.
182  * @param {boolean=} opt_isPerc If unit is percentage.
183  */
184 lime.style.setTransformOrigin = (function() {
185     var stylename = lime.style.getCSSproperty('TransformOrigin');
186     return function(el, ox, oy, opt_isPerc) {
187         var unit = opt_isPerc ? '%' : 'px';
188         var value = ox + unit + ' ' + oy + unit;
189         if (value != el.transform_origin_cache_) {
190             el.style[stylename] = el.transform_origin_cache_ = value;
191         }
192     };
193 })();
194 
195 
196 var stylename = lime.style.getCSSproperty('Transition');
197 lime.style.isTransitionsSupported = !!stylename && !goog.userAgent.OPERA;
198 // Opera's CSS3 transitions seem to be unstable atm. No shorthand plus
199 // doesn't work if the duration property has not been previously set inside
200 // CSS style sheet @tonis
201 
202 var clearProp = function(str, prop) {
203     if (!str.length) return str;
204     var proplist = str.split('),');
205     for (var i = 0; i < proplist.length - 1; i++) {
206         proplist[i] += ')';
207     }
208 
209     proplist = goog.array.filter(proplist, function(part) {
210                return part.indexOf(prop) == -1;
211    });
212     return proplist.join(',');
213 };
214 
215 /**
216  * Activate transition rule for a property
217  * @param {Element} el Element to change.
218  * @param {string} property Transition property name.
219  * @param {number} time Transition duration.
220  * @param {lime.animation.EasingFunction} ease Easing function.
221  */
222 lime.style.setTransition = function(el, property, time, ease) {
223     if (!stylename) return;
224     var curvalue = clearProp(el.style[stylename], property);
225     if (curvalue.length) curvalue += ', ';
226     //console.log(time+'s cubic-bezier('+ease[1]+',
227     //'+ease[2]+','+ease[3]+','+ease[4]+')');
228     curvalue += property + ' ' + time + 's cubic-bezier(' + ease[1] +
229         ',' + ease[2] + ',' + ease[3] + ',' + ease[4] + ')';
230     el.style[stylename] = curvalue;
231 };
232 
233 /**
234  * Clear previously set transition rule.
235  * @param {Element} el Element to change.
236  * @param {string} property Transition property name.
237  */
238 lime.style.clearTransition = function(el, property) {
239     if (!stylename || !el) return;
240     el.style[stylename] = clearProp(el.style[stylename], property);
241 
242    // console.log('clear',el.style[stylename],property);
243 };
244 
245 /**
246  * Change size of a DOM element. Has cache built in for speed boost.
247  * @param {Element} el Element to change.
248  * @param {number} w New width.
249  * @param {number} h New height.
250  */
251 lime.style.setSize = function(el, w, h) {
252     if (el.width_cache_ != w || el.height_cache_ != h) {
253         el.width_cache_ = w;
254         el.height_cache_ = h;
255         return goog.style.setSize(el, w, h);
256     }
257 }
258 
259 })();
260