Using jQuery To Show A Form Over A Reduced-Opacity Image

It’s an awful thing, waiting for a question at Yahoo! Answers that would be fun to discuss as a blog entry. There is an awful lot of chaff to be sorted before one finds such wheat, and even then, sometimes the supposed grains turn out to be mouse turds.

Consider the following:

How would this be done? Java, flash, php, etc?
Okay, for my site.. on the main page, i have four main pictures lined next to eachother..

each one is linked.

The site can be logged into, logged out, you can create an account on it, etc.

What i want to do though, is when a member clicks on one of the pictures, per se if one picture was a large rectangle and it was linked to the login deal,
i would want the picture to fade out, as then the login deal would appear within the rectangle of the picture.

for example:

|“““““““`|
|““`pic“““|
|“““““““`|
—————-

user clicks on pic:

_________ ““““““`_________
|—————|““““““`|-user[ ]-|
|-fade out–|““—>““|-pass[ ]–|
|—————|““““““`|-submit…
—————-““““““`———…

how would i do this?

i’m thinkin Java.. but does anyone know of any tutorials on how to do this or anything?

thanks

hope the diagram makes sense. ha

Hoo, boy. A compelling problem, wrapped in a complete abortion of a question. What should I do?

I want to solve this, especially since it gives me my first chance to discuss jQuery, with which I have fallen completely in love. But I don’t want to reward the total disregard for common sense, the English language and basic programming terminology exhibited in this question, either.

  • “Per se” is Latin for “by itself.” It is most commonly used by lawyers as a synonym for “inherently,” as in, “A slippery floor is hazardous per se, but a sign that warns the floor is wet helps mitigate the floor owner’s liability.” “Per se” is not used to introduce an example. “Say” is used for that purpose. It might seem like picking nits, but it is absolutely impossible to take people seriously if they so blatantly misuse words.
  • “Java” is not shorthand for “JavaScript” (a fact the questioner later realized). Java and JavaScript are completely different things, the way crack cocaine and Cracker Jack are completely different things. It is impossible to take a Web designer seriously if he doesn’t understand that Java and JavaScript aren’t the same thing, or at best, that he cannot use the terms interchangeably, the same way no one asks for an eight ball of candy-coated popcorn and peanuts.
  • At least, the questioner figured out that the ASCII drawing ought to be replaced by an actual drawing. The amusing thing is, neither was needed; his text description was fine.

OK, my spleen is vented. Let’s do this thing.

The Basic Approach: jQuery Does The Dirty Work

With all this question’s failings, its aim is clear:

  • There’s a full-opacity image.
  • User clicks on that image.
  • Image fades down to limited opacity.
  • Form fades up to full opacity over image.

This is easy as pie to do, and thanks to jQuery, we don’t even need to code much. The nice thing about jQuery is that it works as a cross-browser implementation of certain DOM manipulation effects; among those stock effects is fading elements up and down. So we’ll use this version of the wheel to achieve our desired effect.

So our first task is to download jQuery’s current release.

A quick aside on minimized / packed / uncompressed script: It doesn’t really matter which jQuery source file you download (minimized / packed / uncompressed). You only need to download one, and which one is up to you.

The only difference between the three is how long it takes each to download to the client browser, and in this cheap, high-bandwidth world, the difference in download times between a 31 kb (packed) file and a 94 kb (uncompressed) file is nothing. Heck, it’s nothing in the dial-up world. But since it doesn’t matter, use the packed version; elegance alone suggests that’s best.

To use the library, we simply post it on our site and make it the source of a script tag in the header of our Web page.

<script type="text/javascript" src="jquery-1.2.6.pack.js"></script>

Now, for the work we need to put into this: Some images, some HTML and a tiny bit of JavaScript to invoke jQuery methods that otherwise would have taken hours to write.

The HTML and CSS

We’re going to display our four-across layout as div elements. More specifically, we’ll fix the size of four divs, then lay them side by side. And each will contain the image we want to show.

We’ve got a trick up our sleeve, however. Each of these divs is also going to have a background image version — which is a 30% opacity version of the original.

For example, if div no. 1 initially contains an image named 1.jpg, then it also has a background image named 1.30.jpg. This background image is the 30% opacity version of 1.jpg.

We do this because we want a faded version of the image to be the background for our form. So, we go ahead and make that faded image the background.

When the 100% opacity image is showing, it hides the background version; as it fades out, the background image appears, and as the opacity of the original image gets less than the 30 percent of the background image, the naked eye doesn’t notice this; it appears that the fading stopped at 30 percent. When we fade the image back up, it will appear to the naked eye that the 30% opacity image has faded up.

Let’s start with the CSS we’ll apply to our page:

  • Create a containing div; fixed at 1250px, with auto left and right margins.
  • Create a common class, called panel, which sets the width and height of each div to be that of the images to be used, floats them all left and gives them all a right margin of 10 px, among other styles;
  • Specify the background images for each of these divs;
  • Apply a padding to the login form, and initially set its display to none, so that the image is shown instead of the form.
div#container {
	width: 1250px;
	margin: 10px auto;
}

div.panel {
	width: 300px;
	height: 195px;
	float: left;
	margin-right: 10px;
	border: 1px solid #000;
	cursor: pointer;
}

div#panel1 {
	background-image: url(1.30.jpg);
}

div#panel2 {
	background-image: url(2.jpg);
}

div#panel3 {
	background-image: url(3.jpg);
}

div#panel4 {
	background-image: url(4.jpg);
}

#loginform {
	padding: 5px;
	display: none;
}

With the CSS out of the way, we can build the basic HTML of the page. I’m being lazy here; I’m only going to make one of these divs interactive. The principles I am applying to the first div will work on all four.

<div id="container">
    <div id="panel1" class="panel">
        <img id="img1" src="1.jpg" alt="Click Here To Log In" title="Click Here To Log In" onclick="toggleLoginForm()" />
        <form id="loginform" action="" method="post">
            <label>User ID: <input type="text" id="tbUser" name="tbUser"/></label>
            <br />
            <label>Password: <input type="password" id="tbPass" name="tbPass" /></label>
            <br />
            <input type="submit" id="btnSubmit" name="btnSubmit" value="Log In" onclick="toggleLoginForm()" />
        </form>
    </div>
    <div id="panel2" class="panel"></div>
    <div id="panel3" class="panel"></div>
    <div id="panel4" class="panel"></div>
</div>

Note that both img#img1 and input#btnSubmit have the as-yet-undefined JavaScript function toggleLoginForm() assigned to their onclick events. Let’s get to describing that function.

The JavaScript

Thanks to jQuery, fading DOM elements in and out is as simple as calling the methods fadeIn and fadeOut.

In jQuery, you can address elements in a number of ways. When you want to address an element by its ID attribute, you do that the same way you do in CSS: apply a hash mark, followed by the ID value. For example, if I want to address the div with ID of panel1: $(‘#panel1’) gets me a reference to that element.

The fadeIn and fadeOut effects in jQuery take two arguments: speed and, optionally, a callback function.

A callback function is a function that a function will call after it is done. This is of great use to us, because it makes the fading effect much smoother. For example, we could do this:

$('#img1').fadeOut("slow");
$('#loginform').fadeIn("slow");

But if we do that, the fading out of the image and the fading in of the form take place nearly simultaneously, and this creates a very rough transition in the middle of the effect, where both elements are about half visible.

For a smoother transition, we completely fade out the currently visible element — either the image or the form — then “call back” the fade in effect on the invisible element. We determine which element fades in or out by asking JavaScript if the form is currently visible (more accurately, if its CSS display property is set to none). When the form is not showing, we need to fade the image out and fade the form in; vice-versa when the form is visible.

function toggleLoginForm() {
	if($('#loginform').css('display') == "none") {
		$('#img1').fadeOut("slow", function() { $('#loginform').fadeIn("slow"); });
	}
	else {
		$('#loginform').fadeOut("slow", function() { $('#img1').fadeIn("slow"); });
	}
}

You can see the script in action here:

http://demo.dougv.com/jquery_fade/

Just click on the image of the lady holding the cat to see the effect; download the page to your computer to get all the code. I distribute all code under the GNU GPL version 3.

2 Comments

  1. hey, i really havn’t looked so much into javascript ever, when i really need to.
    for the last part of this tutorial though: with ‘function toggleLoginForm()’

    i see that this works for the first image.
    Though i’ve tried multiple things to get each image to work with this, such as:

    $('#img1').fadeOut("slow", function() { $('#loginform').fadeIn("slow"); });
    $('#img2').fadeOut("slow", function() { $('#loginform').fadeIn("slow"); });
    $('#img3').fadeOut("slow", function() { $('#loginform').fadeIn("slow"); });}
    else {
    $('#loginform').fadeOut("slow", function() { $('#img1').fadeIn("slow"); });
    $('#loginform').fadeOut("slow", function() { $('#img2').fadeIn("slow"); });
    $('#loginform').fadeOut("slow", function() { $('#img3').fadeIn("slow"); });
    

    and

    $('#img1').fadeOut("slow", function() { $('#loginform').fadeIn("slow"); });
    }else {
    $('#loginform').fadeOut("slow", function() { $('#img1').fadeIn("slow"); });
    }
    
    {
    $('#img2').fadeOut("slow", function() { $('#loginform').fadeIn("slow"); });
    }else {
    $('#loginform').fadeOut("slow", function() { $('#img2').fadeIn("slow"); });
    }
    
    {
    $('#img3').fadeOut("slow", function() { $('#loginform').fadeIn("slow"); });
    }else {
    $('#loginform').fadeOut("slow", function() { $('#img3').fadeIn("slow"); });
    }
    

    yet, each image i click on.. only the first image fades out and works well.

    What am I messing up?

    Thanks

  2. One element, one ID. That’s what you’re doing wrong.

    In other words, suppose you wanted a second form, id of searchform, in the second image’s box.

    * Give the second image an ID of img2
    * Give the second form an ID of searchform
    * Create a new JavaScript function called toggleSearchForm()
    * Assign that event handler to the onclick event for img2 and the submit button for searchform

    <div id="panel2" class="panel">
    	<img id="img2" src="2.jpg" alt="Search" title="Search" onclick="toggleSearchForm()" />
    	<form id="searchform" action="search.php" method="post">
    		<label>Search term: <input type="text" id="term" name="term" onclick="toggleSearchForm()" /></label>
    		<br />
    		<input type="submit" id="btnSearch" name="btnSearch" value="Search" />
    	</form>
    </div>
    
    div#panel2 {
    	background-image: url(2.30.jpg);
    }
    form#searchform {
    	padding: 5px;
    	display: none;
    }
    
    function toggleSearchForm() {
    	if($('#searchform').css('display') == "none") {
    		$('#img2').fadeOut("slow", function() { $('#searchform').fadeIn("slow"); });
    	}
    	else {
    		$('#searchform').fadeOut("slow", function() { $('#img2').fadeIn("slow"); });
    	}
    }
    

    By the way, your attempt to justify your misuse of “per se” is sophomoric. “Per se” simply does not mean “for example,” and no stretch of logic can make it mean that. Continued misuse might eventually make “per se” a synonym of “for example,” but I wouldn’t think it much of a bragging point to be the guy who forced the OED to make that call.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!