No JS Animation

by steveukx

HTML

<textarea id="from" placeholder="from">{"color": "red"}</textarea>
<textarea id="to" placeholder="to">{"color": "green"}</textarea>
<input id="duration" type="number" placeholder="duration" value="1000" />
<input id="name" placeholder="rule name" value="blah" />
<input id="animate" type="button" value="animate!" />

<div contenteditable="true" id="">
    Type content here
</div>

CSS

textarea, input {
    font-family: verdana;
    font-size: 0.8em;
    display: block;
    width: 200px;
    margin: 0.2em;
    border: 1px solid black;
}
input[type=button] {margin-top: 10px; border: auto;}

JavaScript

window.animation = (function() {
    
    document.addEventListener('webkitAnimationEnd', function(e) {
        //debugger;
        e.target.classList.remove(e.animationName + '-animation');
    }, false);

    var rules = {};

    var prefix = '-webkit-'; // TODO: detect
    if(navigator.userAgent.indexOf('mozilla')>=0) {
        prefix = '-moz-';
    }
    
    function isNodeList(itm) {
        return Object.prototype.toString.call(itm).indexOf('NodeList')>0;
    }

    function isArray(itm) {
        return Array.isArray(itm);
    }

    function animate(element, fromprops, toprops, duration, ruleName) {
        if(!rules[ruleName]) {
            animate.createRule(ruleName, duration, fromprops, toprops);
        }
        animate.run(element, ruleName);
    }
    
    animate.run = function(elements, ruleName) {
        if(!(isArray(elements) || isNodeList(elements))) {
           elements = [elements];
        }
        Array.prototype.forEach.call(elements, function(el) {
            el.classList.add(ruleName);
            el.classList.add(ruleName + '-animation');
        });
    }
    
    animate.createRule = function(ruleName, duration, fromprops, toprops) {
        var styleProps = '';
        for(var el in toprops) {
            styleProps += el + ': ' + toprops[el] + '; ';
        }
        
        var styleText = '';
        styleText += '.$0-animation { ' +
               '$1animation-name: $0; ' +
               '$1animation-timing-function: linear; ' +
               '$1animation-duration: $2ms; ' +
            '} ' +
            '.$0 { ' + styleProps + '} ' +
            '@$1keyframes $0{ from{';
        for(var el in fromprops) {
            styleText += el + ': ' + fromprops[el] + '; ';
        }
        styleText += '} to{' + styleProps + '} };'

        var replacements = [
            ruleName, prefix, duration
        ];
        styleText = styleText.replace(/\$(\d+)/g, function(a,b,c) {
            return replacements[+b];
        });

...