CSS Animations Via Mootools

Separate your presentation and layer. Move your effects from your scripts to CSS. This script degrades for every non-Javascript browser.

// a cow makes moo, this script too. requires mootools 1.2b or compatible.

// MIT-style licence

var CssEffects = {

prefix: "%prefix%",

initialValues: {

duration: "%initialDuration%",

property: "%initialProperty%",

transition: "%initialTransition%"

},

timeUnit: "%timeUnit%"

};

CssEffects.deprecates = (Browser.Engine.trident4) ? true : false;

CssEffects.$regexps = {

parserA: new RegExp('(?:s)*([^{}]+?)s*{([^}]*' + CssEffects.prefix + "[^}]*)}", "gi"),

parserB: new RegExp(CssEffects.prefix + "(?:-?([a-z-]+))?s*:s*([^;]+?)s*(!important)?s*;", "gi"),

time: new RegExp('d+' + CssEffects.timeUnit)

};

CssEffects.Durations = new Hash();

CssEffects.Properties = new Hash();

CssEffects.Transitions = new Hash();

CssEffects.Element = new Class({

initialize: function(element){

this.element = element;

element.store('CssEffects', this);

this.previous = {};

this.dynamicPseudos = [];

this.rules = [];

this.styleAttribute = '';

this.saveStyleAttribute();

this.effect = new Fx.Morph(this.element,{

onCancel: function(){

this.previous = this.getStyles(this.dynamicPseudos);

}.bind(this),

onComplete: this.element.setStyles.bind(this.element, this.previous)

});

(function(){

this.previous = this.getStyles();

element.setStyles(this.previous);

}).delay(1, this);

CssEffects.DynamicPseudos.each(function(obj, pseudo){

['begin', "end"].each(function(when){

$splat(obj[when]).each(function(event){

element.addEvent(event, this.change.bind(this, [when, pseudo]));

}, this);

}, this);

}, this);

},

change: function(when, pseudo){

pseudo = pseudo || '';

(function(){

if (pseudo.length > 0){

if (when == "end" && !this.dynamicPseudos.contains(pseudo)) return;

this.dynamicPseudos[(when == "begin") ? "push" : "remove"](pseudo);

}

this.effect.cancel();

this.restoreStyleAttribute();

var now = this.getStyles(this.dynamicPseudos);

this.element.setStyles(this.previous);

var to = Hash.filter(now, function(v, p){

return (!$defined(this.previous[p]) || this.previous[p] != v);

}, this);

var duration = this.getOwnStyle('duration', this.dynamicPseudos);

var transition = this.getOwnStyle('transition', this.dynamicPseudos);

this.effect.options.duration = duration.match(CssEffects.$regexps.time) ? duration.toInt()

: CssEffects.Durations.get(duration);

this.effect.options.transition = CssEffects.Transitions.get(transition);

this.effect.start(to);

this.previous = now;

}).delay(1, this)

return this;

},

addRule: function(rule){

this.rules.include(rule);

return this;

},

hasRule: function(rule){

return this.rules.contains(rule);

},

removeRule: function(rule){

this.rules.erase(rule);

return this;

},

getOwnStyle: function(property, dynamicPseudos){

dynamicPseudos = dynamicPseudos || [];

var pseudoStr = dynamicPseudos.sort().join('$');

var rules = this.rules.filter(function(rule){

var rulePseudoStr = rule.dynamicPseudos.sort().join('$');

return (!rulePseudoStr || rule.values.has(property) && pseudoStr == rulePseudoStr);

});

var value = CssEffects.initialValues[property];

var importance = 0, specificity = 0;

rules.each(function(rule){

var mImportance = rule.importances.get(property);

if (mImportance > importance || (mImportance == importance && rule.specificity >= specificity)){

importance = mImportance;

specificity = rule.specificity;

value = rule.values.get(property);

}

});

return value;

},

getStyles: function (dynamicPseudos){

var property = this.getOwnStyle('property', dynamicPseudos);

if (property == "none") return {};

property = (property == "all") ? CssEffects.Properties : $splat(property);

return this.element.getStyles.apply(this.element, property);

},

saveStyleAttribute: function(){

this.styleAttribute = this.element.get('style') || '';

return this;

},

restoreStyleAttribute: function(){

return this.element.set('style', this.styleAttribute);

}

});

CssEffects.Element.getInstance = function(element){

return element.retrieve('CssEffects') || new CssEffects.Element(element);

};

CssEffects.Parser = {

addCss: function(text){

while (a = CssEffects.$regexps.parserA.exec(text)){

var selectors = a[1].split(/s*,s*/);

rules = selectors.map(function(selector){

return new CssEffects.Rule(selector);

});

while (b = CssEffects.$regexps.parserB.exec(a[2])){

var importance = (b[3] == "!important") ? 2 : 1;

rules.each(function(rule){

rule.addDeclaration(b[1], b[2], importance);

});

}

}

return this;

},

addStylesheet: function(element){

switch (element.get('tag')){

case "style":

this.addCss(element.get('html'));

break;

case "link":

new Request({

onSuccess: function(text){

this.addCss(text);

}.bind(this),

url: element.href,

method: "get"

}).send();

}

return this;

},

processDocument: function(){

$each(document.styleSheets, function(styleSheet){

var element = $(styleSheet[styleSheet.ownerNode ? "ownerNode" : "owningElement"]);

this.addStylesheet(element);

}, this);

return this;

}

};

CssEffects.Rule = new Class({

initialize: function(selector){

this.importances = new Hash();

this.values = new Hash();

this.selector = selector.replace(/:active|:focus|:hover/ig, '');

this.dynamicPseudos = selector.match(/(:active|:focus|:hover)/ig) || [];

this.specificity = (function(){

var str = selector.replace(/:(before|after|first-letter|first-line)/, '');

var a = str.match(/#/g); a = a ? a.length : 0;

var b = str.match(/[|:|./g); b = b ? b.length : 0;

var c = str.match(/( |+|>)[a-z]+/ig); c = c ? c.length : 0;

if (str.match(/^[a-z]+/i)) c++;

return 100 * a + 10 * b + c;

})();

this.use();

},

addDeclaration: function(property, value, importance){

if (!property) return this.addShortHand(value, importance);

if (!this.importances.has(property) || this.importances.get(property) <= importance) {

if (value.contains(',')) value = value.split(/s*,s*/);

this.values.set(property, value);

this.importances.set(property, importance);

}

return this;

},

addShortHand: function(shortHand, importance){

shortHand.match(/([^s,]+s*,s*)+[^s,]+|[^s,]+/gi).each(function(value){

var property = (value.match(CssEffects.$regexps.time) || CssEffects.Durations.has(value)) ? "duration"

: (CssEffects.Transitions.has(value)) ? "transition"

: "property";

this.addDeclaration(property, value, importance);

}, this);

return this;

},

use: function(){

$$(this.selector).each(function(element){

CssEffects.Element.getInstance(element).addRule(this);

}, this);

}

});

CssEffects.DynamicPseudos = new Hash({

":active": {

begin: "mousedown",

end: ['mouseup', "mouseout"]

},

":focus": {

begin: "focus",

end: "blur"

},

":hover": {

begin: "mouseenter",

end: "mouseleave"

}

});

// normal:

CssEffects.prefix = "-moofx";

initialValues: {

duration: "0ms",

property: "all",

transition: "sine-in-out"

},

aliases

};

CssEffects.Durations = new Hash({

"short": 250,

"normal": 500,

"long": 750

});

CssEffects.Properties = ['backgroundColor', "backgroundPosition", "borderBottomColor",

"borderBottomStyle", "borderBottomWidth", "borderLeftColor", "borderLeftStyle",

"borderLeftWidth", "borderRightColor", "borderRightStyle", "borderRightWidth",

"borderTopColor", "borderTopStyle", "borderTopWidth", "bottom",

"color", "fontSize", "fontWeight", "height", "left", "letterSpacing", "lineHeight",

"marginBottom", "marginLeft", "marginRight", "marginTop", "maxHeight", "maxWidth",

"opacity", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "right",

"textIndent", "top", "width", "zIndex", "zoom"];

CssEffects.DynamicPseudos = new Hash({

":active": {

begin: "mousedown",

end: ['mouseup', "mouseout"]

},

":focus": {

begin: "focus",

end: "blur"

},

":hover": {

begin: "mouseenter",

end: "mouseleave"

}

});

CssEffects.Transitions = new Hash({

linear: Fx.Transitions.linear

});

['Quad', "Cubic", "Quart", "Quint", "Expo", "Circ",

"Sine", "Back", "Bounce", "Elastic"].each(function (transition){

['In', "Out", "InOut"].each(function (ease){

var alias = transition.toLowerCase() + ease.hyphenate().toLowerCase();

CssEffects.Transitions.set(alias, Fx.Transitions[transition]['ease' + ease]);

});

});

window.addEvent('domready', CssEffects.Parser.processDocument.bind(CssEffects.Parser));

})();

Leave Your Response