jQuery 'flip' plugin A little while ago I wrote some jQuery code to make a div flip (similar to the Apple Dashboard). I know there is already code that has this idea from Jon Raasch, but this code positioned divs absolutely, which I did not need for my cause.

I just wondered if anyone could give me some advice as to how to tidy this up and make it cleaner.

(function ($) {
  $.fn.extend({
    jFlip: function (options) {
        var defaults = {
            trigF: '.flipDiv',
            trigB: '.flipDivBack'
        };
        var o = $.extend({}, defaults, options);
        return this.each(function () {
            var f = $('.front');
                b = $('.back');

            margin = f.width() / 2;
            width = f.width();
            height = f.height();
            b.hide().css({
                width: '0px',
                height: '' + height + 'px',
                marginLeft: '' + margin + 'px',
                opacity: '0'
            });

            $(o.trigF).on('click', function () {
                var $this = $(this);

                $this.parents().closest(f).animate({
                    width: '0px',
                    height: '' + height + 'px',
                    marginLeft: '' + margin + 'px',
                    opacity: '0'
                }, {
                    duration: 500
                });

                window.setTimeout(function () {
                    $this.parents().next(b).animate({
                        width: '' + width + 'px',
                        height: '' + height + 'px',
                        marginLeft: '0px',
                        opacity: '1'
                    }, {
                        duration: 500
                    });
                }, 500);
            });

            $(o.trigB).on('click', function () {                            
                $(this).parents().closest(b).animate({
                    width: '0px',
                    height: '' + height + 'px',
                    marginLeft: '' +margin + 'px',
                    opacity: '0',
                    display: 'none'
                }, {
                    duration: 500
                });
                var $this = $(this).parents().siblings(f);
                window.setTimeout(function () {
                    $this.stop().animate({
                        width: '' + width + 'px',
                        height: '' + height + 'px',
                        marginLeft: '0px',
                        opacity: '1'
                    }, {
                        duration: 500
                    });
                }, 500);
            });
        });
    }
  });
})(jQuery);


The div structure is this:

&lt;div class="widgetBox"&gt;
     &lt;div class="front"&gt;
        &lt;p&gt;Front of the div&lt;/p&gt;
        &lt;button class="flipDiv"&gt;Flip&lt;/button&gt;
     &lt;/div&gt;
     &lt;div class="back"&gt;
        &lt;p&gt;Back of the div&lt;/p&gt;
        &lt;button class="flipDivBack"&gt;Flip Back&lt;/button&gt;
     &lt;/div&gt;
  &lt;/div&gt;


And this is the initiation:

&lt;script&gt;
     $(document).ready(function() {
         $('.widgetBox').jFlip();
     });
&lt;/script&gt;


The only options as of yet however are trigF and trigB, which allows you to specify the name of your buttons which will flip the div.

You can see a jsFiddle of this in action here.
Looks cool, nice job!

One this I would say is that the plugin makes too many assumptions about the client's DOM structure. Having fixed selectors like $('.front') and $('.back') within your plugin script is dangerous -- what if I'm working in a page that has a 'front' class on the body?

It's best to let the client pass in exactly what DOM elements they want to manipulate. You could, for example, do something like this:

The html:

&lt;div id="flipper"&gt;
  &lt;div data-face="front"&gt;I'm in front!&lt;/div&gt;
  &lt;div data-face="back"&gt;I'm in back!&lt;/div&gt;
&lt;/div&gt;&lt;!-- end #flipper --&gt;


The initialization:

$('#flipper').jFlip();


In your plugin script, you now know exactly which elements the client wants to work with:

...
return this.each(function() {
 ...
 $flipper = $(this);
 $front = $flipper.find('[data-face=front]:first');
 $back = $flipper.find('[data-face=back]:first');
 ...
});


Now you don't have to deal with any pesky DOM tree traversal, which carries a risk of finding the wrong element.

A couple other notes:


When you're specifying css attrs with jquery, height:
someNumberVariable works just fine. You don't need to wrap it with
'' + someNumberVar + 'px'
Why not set the duration as an optional param?
It would be nice to have a $('#myEl').jsFlip('flip') method. Adding methods like this will add some complexity to your code, but the good news is there are some good plugin patterns out there that you can work off of. IMO, this is the prettiest one I've seen.
Once you've figured out how to add methods to your plugin, it's fairly simple (and best practice) to add a 'destroy' method, that would unbind all of your event handlers. To do this, you need to namespace your events. 


For example:

to bind: $flipBtn.on('click.jFlip', function() { ... })

to destroy: $flipBtn.off('.jFlip');   // unbind all events in .jFlip namespace

One other thing: this plugin replicates the functionality of existing CSS3 animations, which will always be faster. This plugin is still useful as a fallback for browsers that are not up to speed on CSS3, but it would be best to check for that capability first, and implement with CSS3 if available.

I hope this is helpful. Keep on rocking the plugins!