We have learned before how to create a slide up toggle with jquery to mimic facebook chat panel where it slides vertically bottom up. Another common variant is blind toggle, or slide down.

Now we are going to try different approach to how slide method works in jquery. To have a better idea on how it works, you may check it here.

We are trying to slide a whole login block horizontally.

To accomplish this, we need CSS help a lot. I assume we are dealing with drupal 6. So without further ado, here are the steps I have tried so far.

Prepare a block

1. Open your themename.info in your theme directory

2. We are going to position this block on the top right corner. Insert a block named, says, right_ear. Who knows some day you need another ear for another form:

regions[right_ear]          = right ear

3. Go to page.tpl, call the block anywhere near the header region:

<?php if (!$logged_in && $right_ear):
  print
'<div id="right-ear"><div id="right-ear-inner">'. $right_ear .'</div><a class="login-toggle" href="">Log in</a></div>';
endif;
?>

First we check if user is logged in or not, and then check if block name right_ear is already registered into drupal. If both return TRUE, then present the login block. Otherwise do not print anything, even the CSS code. We added necessary CSS wrapper as well to allow advanced theming.

Right after that we insert a custom login button that will toggle the login block and given a class "login-toggle" or whatever the name is as long as meaningful enough to recognize.

Prepare a javascript file

1. Create a javascript file that will hold all your custom jquery scripts, says script.js. You should also register the file into your themename.info, see step #2 above.

2. Now that we also have an empty script.js, open up. Insert a check if javascript is enabled on the client side, and then prepare a custom function.

if (Drupal.jsEnabled) {

//Prepare a reusable function, who knows someday a left_ear region is needed with the same method  
  jQuery.fn.slideFadeToggle = function(speed, easing, callback) {
    return this.animate({opacity: 'toggle', width: 'toggle'}, speed, easing, callback);
  };

  $( function()  {
     // we'll add later the magic code here

  }); // function closed I missed. Thanks to Chris.

}

I grabbed the code from learningjquery site. You may need to go there to have a better explanation. It basically creates a custom animation method to toggle a fade and a slide at the same time. We then need a parameter "width" to have it slide horizontally as opposite to regular slide up and down. Jquery itself can't do its magic with that code. That's why we need a help of CSS.

3. Now that the custom function is set, we need to actually do the magic part:

  // Toggle login block horizontally.
  $(".login-toggle").click(function () {
    $("#right-ear-inner").slideFadeToggle("slow");
    $(this).toggleClass("login-toggle-close");
    return false;
  });

We have a CSS id #right-ear-inner that will actually contain our login block, and will toggle it whenever our button .login-toggle is clicked. We also add another class login-toggle-close dynamically to have a logical button, kind of on and off button.

So place this code, see step #2 under Prepare a javascript file that says we'll add later the magic code here. Place the code there.

Prepare a CSS helper

Create the login block container:

/**
* Inline user login bar inside fixed position login block
*/
/*Login scroll on the right*/
#right-ear {
  z-index:12000; /*Place above anything else in the layout*/
  position:fixed; /*Nail it on the top right*/
  right:0;
  top:40px
  /*Dont go below this to spare header top region*/
}

#right-ear-inner {
  display:none;
  min-height: 60px;
  padding: 10px 0 10px 20px;
  background-color: #000;
  float: left;
  border: 1px solid #fff;
  border-right: 0;
}

Now that the ear is created, we go ahead into the most fun of all: theming the login block. It's worth another post, but for completion, we'll add it here now.

So we must target our login block into this specific region, #right-ear, so that it doesn't affect other region unintentionally. See all comments on the code for explanation :)


/*block-user-0 contains all graphics, login, join, lost?*/
#right-ear .block-user-0 {
  float: left;/*Make it float so the input forms can stay inline*/
  min-width: 290px;
}

/*Hide the form label to not destroy the layout*/
#right-ear .form-item label {
  display: none;
}

/*Reset all elements to avoid problem*/
#right-ear #user-login-form ul,#right-ear .form-button,.form-submit,#user-login-form,#right-ear #user-login-form ul li,#right-ear #user-login-form {
  padding: 0;
  margin: 0;
}

/*Make each input form stays inline*/
#right-ear #user-login-form ul li {
  background: none;
  float: left;
}

/* We need to add a CSS sprite to have a fast rendering as one image*/
#right-ear #user-login-form .form-text,#right-ear .block-user .form-submit,#right-ear .block-user .item-list ul li.first a,#right-ear .block-user .item-list ul li.last a {
  display: block;
  float: left;
  cursor: pointer;
  background: transparent url(images/sprites.png) no-repeat;
  text-indent: -5000px;/*Hide any text, let the image alone*/
  border: 0;
  height: 21px;
  margin-right: 5px
}

/*The sprite is set, now we only need to set each position of the elements*/
#right-ear .block-user .form-submit {
  background-position: left top;
  width: 51px
}

/*We don't have long space, we split the inline login forms into two chunks here*/
#right-ear .block-user .item-list {
  margin-top: 10px;
  clear: both
}

/*This part is an override to create an account*/
#right-ear .block-user .item-list ul li.first a {
  background-position: 0 -22px;
  width: 43px
}

/*Request password overriden*/
#right-ear .block-user .item-list ul li.last a {
  background-position: 0 -46px;
  width: 51px;
  margin-left: 69px
}

/*Background image is also given to text input*/
#right-ear #user-login-form .form-text {
  background-position: 0 -69px;
  width: 102px;
  cursor: text;
  text-indent: 0;
  padding: 3px 5px 0;
  height: 19px;
  color: #ccc
}

So the login form has been overriden by a sprite now.

We just need to add a button to actually toggle the visibility of our beautiful login block. Still the same sprite image, we go on:

/* Our on-off button is given the same image*/
a.login-toggle,a.login-toggle-close {
  background: transparent url(images/sprites.png) no-repeat;
  text-indent: -8000px;
  position: absolute;
  right: 0;
  top: 0;
  height: 80px;
  overflow: hidden
}

/*Now place each to match the actual image position*/
a.login-toggle {
  background-position: -280px top;
  width: 40px
}

a.login-toggle-close {
  right: 298px;
  background-position: -185px top;
  width: 26px
}

/*if you have trouble with your theme, you may also need to reset system.css since we have narrow space*/
#right-ear .form-item,#right-ear .block {
  margin-bottom: 0;
  margin-top: 0;
  padding-bottom: 0
}

So, it's a very long and winding tutorial here:)

I think I need a deep breath a little while...

Register everything

  1. Now all is set, it's high time to register them once and for all so that drupal knows you have done something incredible with its login block. Go to admin/build/themes, hit Save.
  2. Go to admin/build/block, find your theme, configure it to not show the block title, and make it available only to anonymous. Check Show on every page except the listed pages and leave the input box empty. Hit save.
  3. Assign this User login block into your right_ear region.
  4. Switch into another browser, or log off. And voilla!

You now have a very sexy, hot collapsible login block on earth. Toggle it, see if everything goes well as you expected.

You may need to download the sample sprite, see attachment below. Feel free to modify it to suit your design!

Well, you need to change the background color into red to make it actually hot though :)

And see here for the demo again.

Now that you have a cool collapsible login block, you may explore it to turn other possible simple forms into something fancy. We already have a jquery generic function, slideFadeToggle, to do other similar tasks easier. Perhaps a feedback or contact form? What do you think?

This tutorial is not yet tested with openID. So you may need a little tweak to make it work. You can disable it first to see how it works, then refine your login block when openID enabled. It won't be too difficult to spot the right CSS if you have firebug installed. This is simply beyond this tutorial for now.

If you have a better idea or implementation on collapsible login block in drupal, I'll be happy to see to it.

As always I am all ears for suggestions and corrections. Ok, have a nice login block and happy toggling:)

sexy collapsible login block