Programming the Extras tab

A reader asked me how the Extras tab on my blog was made. It’s a bit of CSS and a bit of JavaScript, so let’s describe it all.

Hand with wrenchThe first thing to note is that I wanted to clean up the way my blog looks so that – first – it’s simpler, and – second – to make the blog look good on a mobile device. To that end, as I mentioned before, I converted the CSS to LESS so that the whole experience of writing the styling was made easier.

With regard to the tab, it’s still hard to get CSS to display text vertically in every browser. So, stuff it, I decided to just create an image in Adobe Illustrator that had the text rotated. (Right click on the tab and select View Image to see what it looks like.) I decided to go for green to make it stand out in my blog’s highly monochrome look-and-feel. Being differentiated like that gives the impression of something happening over there and I wonder what happens if I go click on it…

Well, the first thing that happens is that the tab slides out a little bit (“hey, I’m active!”) when the mouse moves over it. This is purely a CSS effect: the tab is marked up as an anchor link:

<a id="hidesidebar"><img src="/files/themes/castleriggnew/images/extras.png" alt="extras" title="extras" width="56" height="128" /></a>

(Ignore the silly id: it should be something like “showextras”, if anything. This is a work in progress.) The CSS for it (in LESS format, as is all CSS code here) is this:

.sidebarRoundedCorners {
    border-top: 2px solid @sidebarBorder;
    border-left: 2px solid @sidebarBorder;
    border-bottom: 2px solid @sidebarBorder;
    -moz-border-radius-topleft: 10px;
    -webkit-border-top-left-radius: 10px;
    border-top-left-radius: 10px;
    -moz-border-radius-bottomleft: 10px;
    -webkit-border-bottom-left-radius: 10px;
    border-bottom-left-radius: 10px;
}

a#hidesidebar {
    position: fixed;
    top: 60px;
    right: 0px;
    background: @sidebarHeadBackground;
    padding: 5px;
    .sidebarRoundedCorners;
    &:hover {
        padding: 5px 8px 5px 5px;
    }
    img {
        border: 0 none;
    }
}

First up, I declare a fake class – sidebarRoundedCorners – that defines the rounded corners for both the tab and for the sidebar that slides in. The “@” identifiers are LESS identifiers for colors. The anchor tag itself is “fixed” positioned (that is, it is fixed in the browser window, not to the underlying page, and so won’t scroll with the page). I incorporate the fake class to provide the colored rounded corners, and then define a hover value for the anchor link. All that hover pseudo-class does is to modify the padding by a couple of pixels: if you look carefully it’s the left padding that increases by 3 pixels. So, when the mouse moves over the styled anchor link, the hover class gets activated and the tab slides out a little bit; 3 pixels’ worth. No JavaScript to be seen.

(Aside: In CSS3, the hover pseudo-class is supposed to work with any element, not just anchor elements. That’s all fine for the latest browsers, but for earlier ones, confusion is bound to ensue, so I just took the easy route of using an <a> tag and didn’t try for a <div>.)

Now the fun JavaScript stuff. If you click on the tab, it disappears, and the sidebar slides out, also themed in green. Nothing for this but some jQuery-ed JavaScript.

$(function() {
 
  var enableSidebarHiding = function () {
    var link,
        sidebarDiv,
        saveVisibility,
        isVisible,
        makeLinkHide,
        makeLinkShow,
        hideSidebar,
        showSidebar,
        cookieName = "sidebarvisibility";

    var mouseInside = false;

    saveVisibility = function (value) {
      $.cookie(cookieName, value, {expires: 30});
    };
    
    isVisible = function() {
      var isVisible = $.cookie(cookieName);
      return (isVisible && isVisible === "Y");
    };
  
    makeLinkHide = function() {
      link.unbind('click');
      link.hide();
    };
  
    makeLinkShow = function() {
      link.unbind('click');
      link.click(showSidebar);
      link.show();
    };

    hideSidebar = function() {
      sidebarDiv.hide("fast");
      makeLinkShow();
      saveVisibility("N");
      sidebarDiv.unbind("hover");
      $("body").unbind("mouseup");
    };

    showSidebar = function() {
      sidebarDiv.show("fast");
      makeLinkHide();
      saveVisibility("Y");

      sidebarDiv.hover(function () {
          mouseInside = true;
      }, function () {
          mouseInside = false;
      });
      $("body").mouseup(function () {
        if (!mouseInside) {
          hideSidebar();
        }
      });

    };

    link = $("#hidesidebar");
    sidebarDiv = $("#sidebarbox");

    if (!isVisible()) {
      hideSidebar();
    }
    else {
      showSidebar();
    }
  };

  enableSidebarHiding();
});

It’s a standard document.ready jQuery function. Reading from the bottom (where all the interesting stuff happens), we enable the hiding of the sidebar (which is the rest of the code). First up is to get the tab (link) and the div containing the actual sidebar (sidebarDiv). In the CSS, this latter div is marked as display:none so it won’t show when the page is initially rendered. I make a note of these elements at the start because it’s a little faster later on and I’m not modifying the structure of the DOM at all.

I then check the cookie to see if the user is currently showing the sidebar or not and call the relevant routine to make sure. hideSidebar() not only makes sure the tab is shown, the sidebar div is hidden, but also that the tab has a click event handler attached so we can trap a click event. showSidebar() does something similar: it forces the tab to hide, the sidebar div to show, and attaches mouse event handlers to both the sidebar div and the body of the page.

Let’s go through the event handlers. When the sidebar is hidden, the only active piece on the page is the green tab. I attach a click event (in makeLinkShow()) so that I can catch the user clicking on the tab. When the user does, the showSideBar() event handler gets triggered. This does the right stuff visually and then adds a hover event handler to the sidebar div. It also adds a mouseup event handler to the body element. What’s all this about?

The hover handler just tracks whether the mouse cursor is over the sidebar or not. It sets a boolean mouseInside variable to true (“inside the sidebar”) or false (“outside”). When the mouseup event handler gets triggered, the user has clicked somewhere in the body of the page (which includes the sidebar, by the way). The event handler checks our mouseInside variable. If true, the event handler does nothing. If false, the mouse cursor is outside the sidebar, and the handler hides it (and removes those two event handlers again).

So, as far as the user is concerned, they click outside the sidebar and that action hides it with a swoosh and redisplays the green tab. He clicks the green tab again and the sidebar shows with a swoosh, hiding the tab in the process. All JavaScript.

Now playing:
Pet Shop Boys - London (Genuine piano mix)
(from London)

Loading similar posts...   Loading links to posts on similar topics...

3 Responses

#1 Michael Proctor said...
21-Feb-12 9:42 PM

Hey Julian,

Like the concept of the tab, except your color scheme is a problem for the DX logo ;) apparently you work for&1

julian m bucknall avatar
#2 julian m bucknall said...
22-Feb-12 9:03 AM

Michael: Dayum. Thanks for the warning. I've flipped the background for now, until I have more time to play around with the best combination. It and the swirls at the end of the columns are throwbacks to the old look for now.

Cheers, Julian

 avatar
#3 Chua Chee Wee said...
27-Feb-12 7:58 PM

Thanks for responding to my request, Julian!

Much appreciated! ;o)

Cheers,

Chee Wee

Leave a response

Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.

  •  Emphasize with italics: surround word with underscores _emphasis_
  •  Emphasize strongly: surround word with double-asterisks **strong**
  •  Link: surround text with square brackets, url with parentheses [text](url)
  •  Inline code: surround text with backticks `IEnumerable`
  •  Unordered list: start each line with an asterisk, space * an item
  •  Ordered list: start each line with a digit, period, space 1. an item
  •  Insert code block: start each line with four spaces
  •  Insert blockquote: start each line with right-angle-bracket, space > Now is the time...
Preview of response