Skip to Main Content

Apr 6, 2010 | 8 minute read

User Forms and Tabs that Play Hide-And-Seek

written by Armando

JavaScript makes an online retail site interactive, and when combined with an attractive site design and good functionality, well executed JavaScript can positively affect how shoppers feel about a merchant.

Online shoppers often use site aesthetics and perceived web development expertise to judge a retailer's professionalism and trustworthiness.

Put another way, a good-looking, fast-loading, and interactive online store can affect how a potential shopper feels about the store's credibility. This is extremely important for stores that don't have million-dollar brands.

A blasé or dysfunctional site just won't do.

The Nineteen '47 Website is a Positive Example

Conversely, when an online retailer's site is attractive, professional, and interactive, consumers are more likely to feel comfortable making a purchase.

Recently, I came across  a very well done site, Nineteen 47. And in this post, I am going to demonstrate  how you can imitate one aspect of its interactivity, and with a little luck show customers that yours is a professional site.

Screen capture from the Nineteen 47 website

Visually the Nineteen 47 site, which was developed at One Pica, is on-brand, complex (in a good way), and detailed. The level of skill required to develop the site is clear and customers will pick up on that expertise.

Screen capture of a product category page from the Nineteen 47 site

The site's designers clearly paid attention to details. For example, many of the tabs on the site, including the search form, slide down when a user hovers over them, and hide—sort of—when a user focuses attention elsewhere.

Screen capture shows an example of an interactive tab

An Interactive Search Form

In my opinion, the best example of these interactive tabs is the aforementioned search form.

When a page loads, the site visitor sees a smallish tab emblazoned with the word "Search" at the lower right of the page's main navigation.

Screan capture shows the closed search form on the Nineteen 47 site

Hovering over the word "Search" exposes the HTML form as it smoothly slides into place.

Screen capture shows the open search form on the Nineteen 47 site

It is this effect—tabs that play hide-and-seek—which I want to emulate.  The folks at One Pica used the Prototype JavaScript library to create this effect, but for my demonstration, I am going to write some JavaScript from scratch.

Start with the HTML and CSS

To begin with, I need some basic HTML mark up. For our purposes, I will have three divs on the page. The first of these is simply a wrapper, but the next two will represent the main navigation and form respectively. Also, I decided to create a log in form rather than a search form.

<!doctype html>

<html lang="en">

<link rel="stylesheet" href="style.css">

<body>

<div>

<div>Wide</div>

<div>

<form id="login" method="get" action="" style="display: block;">

<div id="login-slide">

<input id="login-box" value="" name="login=box"></input>

<button type="submit">Log In</button>

</div>

</form>

</div>

</div><!--end wrapper-->

<script src="js2.js"></script>

</body>

</html>

With my HTML composed and saved as index.html, I quickly put together an external style sheet.

body {margin: 4em auto; color: #fff;}

#wrapper {margin: 0 auto; width: 75%;}

/* Wide Div Stuff */

#wide {position: relative; background: #222; height: 3em; z-index: 10;}

/* Narrow Div Stuff*/

#narrow { position: absolute; top: 7em; background:#888; width: 20%; padding: 1em .5em; z-index:3;}

#narrow form{height: 5em;}

It is important to notice the z-index of each element. I could have used 1 and 2 rather than 3 and 10, just so long as the "narrow" div is below the "wide" div. Also the "wide" div has a relative position and the "narrow" div is positioned absolutely. It is possible to get the effect we are aiming for with other positioning combinations, so feel free to experiment.

Using the top attribute, I have positioned the "narrow", gray div just at the bottom edge of the "wide", dark gray div. In this position, the form is completely exposed.

Screen capture shows the demonstration page with the log in form open

Hide the Form

I want the form's start position to be open. This way, if a shopper should visit the site without JavaScript enabled, that shopper could still use the log in form.  If I had done things the other way around—starting with the form hidden—some visitors might not be able to access it.

Since I foresaw this potential problem and started with the form showing, my first bit of JavaScript needs to hide it.

var idT= document.getElementById('narrow');

//Hide the div from the users

function loginHide(){

idT.style.top = "4em";

up();

}

loginHide();

This JavaScript does three things for us. First, it creates a variable that retrieves the "narrow" div. Next, it changes the div's top attribute value to 4em, effectively hiding the div under the "wide" div. Finally, this code also evokes the function up(). While up() doesn't exist yet, I know that I am going to need a function to push the div back up when a user moves his mouse away. I want to run that function when the page loads to avoid a JavaScript error later.

Screen capture shows the demonstration site with the log in form closed

Add Event Listeners

With the div or tab, if you will, hidden, I want to start on the code that will open the tab when a user hovers over it. To accomplish this, I am going to add an event listener. This listener will react whenever a user initiates the target event.

//Set Listener on the div

idT.addEventListener('mouseover', loginSlide, false);

idT.addEventListener('mouseout', up, false);

This is the standard way to add an event listener to a web page. Notice that I use our variable idT to identify the "narrow" tab. The events this code will watch for are "mouseover" and "mouseout." When one of these mouse events takes place, the listener will fire the function loginSlide() or the function up(). The "false" in each listener indicates that we are listening when the event bubbles. Event bubbling may be new to you, but is beyond what we need to worry about here, so just leave this set to "false."

I need to mention that this code will not work in some versions of Microsoft's Internet Explorer (IE) web browser. I will replace it before we're done, but when I am composing in JavaScript, I always use the standard and make adjustments for poor browser consistency at the end.

Repositioning the Div

I could write a function that reset the form tab's top attribute value to 7em. In fact, that code would be very similar to the loginHide() function I introduced above. But this would not really give me the effect I want since the tab would fly to its new position in less than a millisecond, popping out in almost cartoon-like fashion.

The Nineteen 47 search tab slides smoothly into place. It glides out from under the main navigation rather than popping out. To get this effect, I am going to use a timer that incrementally changes the tab's position.

function loginSlide()

{

if(hei < 7)

{

idT.style.top = (hei + .025) + "em";

setTimeout(loginSlide,5);

}

}

The loginSlide() function first creates the variable hei, which is set to the numerical value of the "narrow" div's top attribute. When the page loads and loginHide() runs, that value will be set to 4em, so to begin with, hei will be set to 4. Notice that the "em" has been removed with parseFloat().

Next the function tests to see if the value of hei is less than 7. Remember at 7em the tab is completely open. If the test comes back positive, the function adds .025 to the numerical value of hei and then adds the string "em." After the function has run once, hei will be equal to 4.25em.

The function setTimeout() waits five milliseconds and then restarts the loginSlide() function. With this timer (setTimeout()) running, the value of hei, which is the value for the top attribute of our div, will increase by .025 every 5 milliseconds until it is set to 7em.

Effectively, the "narrow" tab will glide down the page and into position in a smooth even fashion.

Hiding the Div Again

Of course, now the tab is stuck completely open. I want to write some JavaScript that will close it with the same smooth motion we used to open it.

function slideUp()

{

var hei = parseFloat(idT.style.top);

if(hei > 4)

{

idT.style.top = (hei - .025) + "em";

setTimeout(slideUp,5);

}

}

function up()

{

happiness = setTimeout(slideUp,1500);

}

To get the tab to go back into hiding, I wrote two more functions, slideUp() and up(). The slideUp() function is essentially the reverse of loginSlide(). It incrementally reduces the "narrow" div's top attribute value until that value is 4em.  The up() function sets a timer that fires slideUp() one and a half seconds after a user's mouse pointer moves away from the tab.

This is actually a little variation from the Nineteen 47 site. I wanted the log in form to stay open briefly after the mouse pointer moved away.

Timers in Conflict

Unfortunately, we have a problem. After a user has moused over and moused out once, both of the timers are active. Our tab could shutter and then open and close a few times in a fit of confusion.

We need to make sure that we don't have conflicting timers. To do this, I am going to add some code to loginSlide().

function loginSlide()

{

var hei = parseFloat(idT.style.top);

if(hei >4)

{

clearTimeout(happiness);

}

if(hei < 7)

{

idT.style.top = (hei + .025) + "em";

setTimeout(loginSlide,5);

}

}

This additional code stops the time established in the up() function, eliminating the timer conflicts. This is also why I invoked up() in slideHide().  Without calling it in the first time the user hovered over the tab the browser would not have known what happiness was, producing an error. The user probably would not have noticed the error, but I still hate errors.

Side by side screen captures of the finished demonstration page with the form closed then open

Compensate for IE

The JavaScript is basically done. It does what we want it to, and it will work in most good browsers like Firefox, Chrome, Opera, and Safari. But unfortunately, it won't work in some versions of IE. To compensate, I am going to use a very standard JavaScript hack that will attach an event listener no matter which JavaScript document object model is in view.

This is such a common task that almost everyone has a preferred way to do it and every popular JavaScript library has it built in. For our demonstration, I am going to use some code that I got from Stephen Chapman at About with a few minor modifications.

function addEvent(el, eType, fn, uC)

{

if (el.addEventListener)

{

el.addEventListener(eType, fn, uC);

return true;

} else if (el.attachEvent) {

return el.attachEvent('on' + eType, fn);

} else {

el['on' + eType] = fn;

}

}

addEvent(idT,'mouseover', loginSlide, false);

addEvent(idT,'mouseout', up, false);

This post was contributed by our guest columnist Armando Roggio. Armando is a journalist, web designer, technologist and the site director for Ecommerce Developer.