Construire un plugin qui applique un effet CSS,
au choix de l'utilisateur, pendant une durée indéterminée

Index

On utilise les méthodes setInterval() et toggleClass() pour appliquer, alternativement, l'effet CSS sur un élément du DOM. L'effet CSS et sa durée d'application (voir les options "class" et "speed") sont au choix de l'utilisateur. L'utilisateur peut stopper le plugin Blinker en déclenchant l'événement "stopBlinker".

Exemple

Code CSS : 

.foo { -moz-transform: scale(2.50) rotate(11deg) translate(59px, 74px) skew(11deg, 0deg); -0-transform: scale(2.50) rotate(11deg) translate(59px, 74px) skew(11deg, 0deg); 
    -webkit-transform: scale(2.50) rotate(11deg) translate(59px, 74px) skew(11deg, 0deg); -ms-transform: scale(2.50) rotate(11deg) translate(59px, 74px) skew(11deg, 0deg); 
    transform: scale(2.50) rotate(11deg) translate(59px, 74px) skew(11deg, 0deg); }
.bar { background-color: rgba(170, 255, 255, 0.25); color: #000000; zoom: 2; }
#stopfoo, #stopbar { display: none; ]
Code HTML : 

<input id="launchfoo" type="button" value="appliquer le plugin sur foo" />
<input id="stopfoo" type="button" value="stopper le plugin sur foo" />
<input id="foo" value="id=foo" type="text" />
<input id="launchbar" type="button" value="appliquer le plugin sur bar" />
<input id="stopbar" type="button" value="stopper le plugin sur bar" />
<input id="bar" value="id=bar" type="text" />
Code JS : 

    ( function( $, W ){
        /*
         * Blinker : un plugin qui applique un effet CSS, au choix de l'utilisateur, pendant 
         * une durée indéterminée.
         * 
         * On utilise les méthodes setInterval() et toggleClass() pour appliquer alternativement 
         * l'effet CSS sur un élément du DOM.
         * 
         * L'effet CSS et sa durée d'application (voir les options "class" et "speed") sont au 
         * choix de l'utilisateur.
         * 
         * L'utilisateur peut stopper le plugin Blinker en déclenchant l'événement "stopBlinker".
         * 
         * Chaque sélecteur (item) utilise la méthode data() pour conserver en mémoire la référence 
         * retournée par setInterval() et la méthode bind() pour intercepter l'événement demandant 
         * l'application de clearInterval()
         */
        $.fn.Blinker = function( options ){
            // options et méthode d'arrêt du plugin
            var opts = $.extend( true, {}, $.fn.Blinker.defaults, options ),
                stop = function( self ){
                    clearInterval( $( self ).data( "objInterval" ) );
                    $( self ).removeClass( opts[ "class" ] );
                    $( self ).data( "objInterval", "" );
                };
     
            // si la classe par défaut n'existe pas dans la feuille de style, on la crée
            if ( $( "style" ).text().match( "." + opts[ "class" ] ) === null ){
                $( "style" ).append( "." + opts[ "class" ] + " { background-color : red; color : white; )" );
            }
     
            /*
             * Pour chaque élément contenu dans le sélecteur, on toggle la classe opts[ "class" ] pendant opts.speed 
             * millisecondes jusqu'à ce que l'utilisateur stoppe le plugin par un $(...).trigger(opts.stop).
             */
            return this.each( function( i, item ){
                $( item ).data( "objInterval", 
                    setInterval( function(){
                        $( item ).toggleClass( opts[ "class" ] );
                    }, opts.speed )
                );
     
                /*
                 * off() indispensable pour ne pas intercepter le même événement plusieurs fois
                 */
                $( item )
                    .off( opts.stop )
                    .on( opts.stop, function(){
                        if ( $( this ).data( "objInterval" ) ){
                            stop( this );
                        }
                    });
            });
        };
        
        $.fn.Blinker.defaults = {
            "class" : "blinker", // classe par défaut
            "speed" : 500, // vitesse d'application de toggleClass
            "stop" : "stopBlinker" // non de l'événement déclenchant l'arrêt du plugin
        };
        
    })( jQuery, window );
    
    $("#launchfoo").on( "click", function(){
        $( this ).css( "display", "none" );
        $( "#stopfoo" ).css( "display", "block" );
        
        // déclenchement du plugin Blinker
        $( "#foo" ).Blinker({
            "class": "foo",
            "speed": 2500
        });
    });
 
    $( '#stopfoo' ).on( "click", function(){
        $( this ).css( "display", "none" );
        $( "#launchfoo" ).css( "display", "block" );
        
        // arrêt du plugin Blinker
        $( "#foo" ).trigger( "stopBlinker" );
    });
 
    $( "#launchbar" ).on( "click", function(){
        $( this ).css( "display", "none" );
        $( "#stopbar" ).css( "display", "block" );
 
        $( "#bar" ).Blinker({
            "class": "bar",
            "speed": 1000
        });
    });
 
    $( '#stopbar' ).on( "click", function(){
        $( this ).css( "display", "none" );
        $( "#launchbar" ).css( "display", "block" );
 
        $( "#bar" ).trigger( "stopBlinker" );
    });

Tests unitaires avec QUnit.