UNPKG

can

Version:

MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.

178 lines (145 loc) 4.73 kB
/* --- name: Fx.CSS description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. license: MIT-style license. requires: [Fx, Element.Style] provides: Fx.CSS ... */ Fx.CSS = new Class({ Extends: Fx, //prepares the base from/to object prepare: function(element, property, values){ values = Array.from(values); var from = values[0], to = values[1]; if (to == null){ to = from; from = element.getStyle(property); var unit = this.options.unit; // adapted from: https://github.com/ryanmorr/fx/blob/master/fx.js#L299 if (unit && from && typeof from == 'string' && from.slice(-unit.length) != unit && parseFloat(from) != 0){ element.setStyle(property, to + unit); var value = element.getComputedStyle(property); // IE and Opera support pixelLeft or pixelWidth if (!(/px$/.test(value))){ value = element.style[('pixel-' + property).camelCase()]; if (value == null){ // adapted from Dean Edwards' http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 var left = element.style.left; element.style.left = to + unit; value = element.style.pixelLeft; element.style.left = left; } } from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0); element.setStyle(property, from + unit); } } return {from: this.parse(from), to: this.parse(to)}; }, //parses a value into an array parse: function(value){ value = Function.from(value)(); value = (typeof value == 'string') ? value.split(' ') : Array.from(value); return value.map(function(val){ val = String(val); var found = false; Object.each(Fx.CSS.Parsers, function(parser, key){ if (found) return; var parsed = parser.parse(val); if (parsed || parsed === 0) found = {value: parsed, parser: parser}; }); found = found || {value: val, parser: Fx.CSS.Parsers.String}; return found; }); }, //computes by a from and to prepared objects, using their parsers. compute: function(from, to, delta){ var computed = []; (Math.min(from.length, to.length)).times(function(i){ computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); }); computed.$family = Function.from('fx:css:value'); return computed; }, //serves the value as settable serve: function(value, unit){ if (typeOf(value) != 'fx:css:value') value = this.parse(value); var returned = []; value.each(function(bit){ returned = returned.concat(bit.parser.serve(bit.value, unit)); }); return returned; }, //renders the change to an element render: function(element, property, value, unit){ element.setStyle(property, this.serve(value, unit)); }, //searches inside the page css to find the values for a selector search: function(selector){ if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$'); var searchStyles = function(rules){ Array.each(rules, function(rule, i){ if (rule.media){ searchStyles(rule.rules || rule.cssRules); return; } if (!rule.style) return; var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ return m.toLowerCase(); }) : null; if (!selectorText || !selectorTest.test(selectorText)) return; Object.each(Element.Styles, function(value, style){ if (!rule.style[style] || Element.ShortStyles[style]) return; value = String(rule.style[style]); to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value; }); }); }; Array.each(document.styleSheets, function(sheet, j){ var href = sheet.href; if (href && href.indexOf('://') > -1 && href.indexOf(document.domain) == -1) return; var rules = sheet.rules || sheet.cssRules; searchStyles(rules); }); return Fx.CSS.Cache[selector] = to; } }); Fx.CSS.Cache = {}; Fx.CSS.Parsers = { Color: { parse: function(value){ if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; }, compute: function(from, to, delta){ return from.map(function(value, i){ return Math.round(Fx.compute(from[i], to[i], delta)); }); }, serve: function(value){ return value.map(Number); } }, Number: { parse: parseFloat, compute: Fx.compute, serve: function(value, unit){ return (unit) ? value + unit : value; } }, String: { parse: Function.from(false), compute: function(zero, one){ return one; }, serve: function(zero){ return zero; } } }; //<1.2compat> Fx.CSS.Parsers = new Hash(Fx.CSS.Parsers); //</1.2compat>