views:

474

answers:

2

I'm using jQuery to build simple animations for a login form in my CMS. The jQuery toggles the visibility of two forms, a login form, and a reset password form.

The script works perfectly fine, but I seem to figure out how to shorten it up, since most of the code is redundant.

Note: The .click function is called twice in each case to force the animations to take place concurrently.

The JS:

$(function() {
    var recover_text = "Password Recovery";
    var login_text = "Login to CMS";
    $("input").labelify({ text: "label", labelledClass: "inside" });
    $("#forgot").click(function() {
     $("#cms_login").fadeOut("fast", function() { 
      $("#pw_recover").fadeIn();
     });
    });
    $("#forgot").click(function() {  
     $("#dialog h2").fadeOut("fast", function() {
      $(this).html("" + recover_text + "").fadeIn();
     });
     document.title = '' +  recover_text + ''; 
    });  
    $("#login").click(function() {
     $("#pw_recover").fadeOut("fast", function() { 
      $("#cms_login").fadeIn();
     });
    });
    $("#login").click(function() {  
     $("#dialog h2").fadeOut("fast", function() {
      $(this).html("" + login_text + "").fadeIn();
     });
     document.title = '' + login_text + '';
    });
});

And the (abridged) HTML:

<div id="form-wrap">
    <form id="cms_login">
     ...login fields...
     <a id="forgot" href="#">Forgot password?</a>
    </form>
    <form id="pw_recover">
     ...reset password fields...
     <a id="login" href="#">⇐ Back to login</a>
    </form>
</div>

#pw_recover { display: none; }

How can I optimize/retool this script? Any thoughts?

+2  A: 

something like this?

$(function() {
    function switch_boxes(out, in_str)
    {
        return function() {
            $(out).fadeOut("fast", function() {
                    $(in_str).fadeIn();
                });
        };
    }
    function switch_text(out, text)
    {
        return function() {
            $(out).fadeOut("fast", function() {
                    $(this).html(text).fadeIn();
                });
            document.title = '' + text + '';
        };
    }

    var recover_text = "Password Recovery";
    var login_text = "Login to CMS";
    $("input").labelify({ text: "label", labelledClass: "inside" });
    $("#forgot").click( switch_boxes("#cms_login", "#pw_recover") );
    $("#forgot").click( switch_text("#dialog h2", recover_text) );
    $("#login").click( switch_boxes("#pw_recover", "#cms_login") );
    $("#login").click( switch_text("#dialog h2", login_text) );
});
Stobor
Brilliant! Now where would one insert `return false` to prevent the page from jumping to the top?
peehskcalba
+2  A: 

You can force animations to take place concurrently by calling dequeue() after an the animate command (animate(), fadeIn(), etc).

Working Demo - Code at the bottom

Of course, this demo is somewhat contrived as we could have animated both height and width in the one animate command :)

EDIT:

You should need only one click() command for each of '#login' and '#forgot' for the animations to work concurrently as the following demo shows-

Working Demo

Thus, you can refactor your code to the following to start

$("#forgot").click(function() {
    $("#cms_login").fadeOut("fast", function() { 
        $("#pw_recover").fadeIn();
    });
    $("#dialog h2").fadeOut("fast", function() {
        $(this).html("" + recover_text + "").fadeIn();
    });
    document.title = '' +  recover_text + ''; 
});
$("#forgot").click(function() {             
}); 

$("#login").click(function() {
    $("#pw_recover").fadeOut("fast", function() { 
        $("#cms_login").fadeIn();
    });
    $("#dialog h2").fadeOut("fast", function() {
        $(this).html("" + login_text + "").fadeIn();
    });
    document.title = '' + login_text + '';
});

You could then look at refactoring what you are doing in each click event handler i.e. there is a pattern to the code that could be abstracted. There are a number of ways that this could be done, two of which are

  1. in a fashion as suggested in Stobor's answer

  2. write a jQuery plugin for it

jQuery code for demo

$(function() {
  $('#dequeue').click(function() {
    $('#div')
        .animate({ height: 200}, "slow" )
        .dequeue()
        .animate({ width: 200}, "slow" );
  });   
  $('#queue').click(function() {
    $('#div')
        .animate({ height: 100}, "slow" )
        .animate({ width: 100}, "slow" );
  });

});

HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&gt;&lt;/script&gt;
<title>Sandbox</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen">
#div { background-color: red; height: 100px; width: 100px; }
</style>
</head>
<body>
  <div id="div">
    This is the animated div
  </div>
  <br/>
  <input type="button" id="dequeue" value="Click Me to expand (dequeued)" />
  <br/>
  <input type="button" id="queue" value="Click Me to contract (queued)" />
</body>
</html>
Russ Cam
Thank you also for your input. That `.dequeue()` tip is one I'll remember!
peehskcalba