HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

jQuery 'flip' plugin

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
pluginjqueryflip

Problem

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:

Solution

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:


  I'm in front!
  I'm in back!


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!

Code Snippets

<div id="flipper">
  <div data-face="front">I'm in front!</div>
  <div data-face="back">I'm in back!</div>
</div><!-- end #flipper -->
$('#flipper').jFlip();
...
return this.each(function() {
 ...
 $flipper = $(this);
 $front = $flipper.find('[data-face=front]:first');
 $back = $flipper.find('[data-face=back]:first');
 ...
});

Context

StackExchange Code Review Q#11502, answer score: 6

Revisions (0)

No revisions yet.