Element.Behaviors experimental example

Uses JSON to parse the options

by rpflorence

HTML

<div 
    id=fixture 
    data-filter="pulse pulse:pulse-two gray"
    data-pulse='{
        "duration":2000,
        "property":"opacity",
        "from":0,
        "to":1}'
    data-pulse-two='{
        "duration":415,
        "property":"color",
        "from":"#f00",
        "to":"#32c"}'
>
    I should pulse my opacity, and my color on different intervals, and have a gray background
</div>

<p>It first looks for options that are specified in the filter declaration, so the filter `pulse:pulse-two` found `data-pulse-two` and used it.  If that isn't found, it looks for `data-filter-name`, like `data-pulse`.  If that's not found, it just sends along an empty object.
</p>

CSS

[data-pulse]{
    width: 70%;
    padding: 20px;
    text-align: center;
    font-size: 20px;
    border: solid 1px;
    margin: auto;
    margin-bottom: 20px;
}

JavaScript

Element.behaviors = {};
Element.behaviors.filterNow = function(){
    $$('[data-filter]').each(function(element){
        element.get('data-filter').split(/ +|\t+|\n+/).each(function(raw){
            var split = raw.split(':'),
                filter = split[0],
                options = JSON.parse((element.get('data-' + (split[1] || filter))) || '{}');
            if (raw == '' || element.retrieve('behavior-' + raw)) return;
            if (!Element.behaviors[filter]) throw new Error('Filter `' + filter + '` is undefined');
            element.store('behavior-' + raw, Element.behaviors[filter].apply(element, [options]) || true);
        });
    });
};

Object.append(Element.behaviors, {

    pulse: function(options){
        var periodical, 
            tween = new Fx.Tween(this, {
                property: options.property,
                link: 'chain',
                duration: options.duration / 2
            });
            
        function pulse(){ tween.start(options.from).start(options.to) }
        function start(){ pulse(); periodical = pulse.periodical(options.duration) }
        function stop(){ tween.cancel(); clearInterval(periodical) }

        start();
        return { tween: tween, start: start, stop: stop };
    },

    gray: function(){
        this.setStyle('background', '#cccccc');
    }

});

document.addEvent('domready', Element.behaviors.filterNow);