Multiple Display Divisions.

Introduction.

I came up with a fairly interesting piece of Javascript today, as an unintended consequence of investigating some aspect of Javascript and jQuery syntax. Javascript seems to be one of those languages where there's always something new to discover, and there are many ways to skin the proverbial cat.

To give a context, suppose you have a web page that displays a number of screens. Each of these comprises a div, which may or may not be displayed - only one at a time - and a set of buttons, or other clickable elements, that choose the div to be displayed. You can get an idea of the circumstances I'm talking about from this demo.

Such things are quite simple to code in a rather literal way, but get verbose and tedious to maintain as you add screens.

HTML

This is very straightforward. The only thing I'll mention is that I use the HTML5 style of naming additional attributes of elements "data-...".

<!doctype html>
<html>
<head>
<style>
.container {
   position:relative;
   width:350px;
   margin:0 auto;
}
.hdiv {
   display:none;
   width:100%;
   height:2000px;
}
</style>
<title>Javascript teaser.</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"/></script>
<script type="text/javascript">
<!-- Script here - see below -->
</script>
</head>
<body>
<div class="container">
<h2 id="h2">Various Display Divisions.</h2>
<!-- Any kind of element can act as a trigger to show a particular div.
     Here two buttons duplicate the same functionality. -->
<button class="trigger" data-assocdiv="feed">B1</button>
<span class="trigger" data-assocdiv="members" style="cursor:pointer;">Span</span>
<a href="javascript:return false;" class="trigger" data-assocdiv="settings">Link</a>
<label for="cb">Checkbox </label><input type="checkbox" class="trigger" id="cb" data-assocdiv="messages">
<button class="trigger" data-assocdiv="feed">B1-Dup</button>
<p>
<!-- These are the divisions  - only one of these is to show at any time. -->
<div class="hdiv" id="feed" style="background-color:#aaf;"><h3>News Feed</h3></div>
<div class="hdiv" id="members" style="background-color:#afa;"><h3>Member List</h3></div>
<div class="hdiv" id="settings" style="background-color:#faa;"><h3>Settings</h3></div>
<div class="hdiv" id="messages" style="background-color:#aff;"><h3>Your Messages</h3></div>
</div>
</body>
</html>
You've already seen what that looks like from the demo.

Script

The click handler for the various trigger elements is eventually set using jQuery's $('#divid').click(someFunction). In this case, the some function is a nested one to allow it to have context without polluting the global namespace.

// Arguments here are a class name used to identify trigger elements, and
// the ID of the div that will initially be shown.
function fixClix(triggerclass, defdiv)
{
   var current = "";  // Which div is showing

   // There may be things we need to do before the page element is shown
   function preShow(divid)
   {
      var s = "showed<br>";
      $('#'+divid).append(s);
   }

   // Similarly, we may need to clean up. For both of these the demo just
   // adds a line of text to the div.
   function postHide(divid)
   {
      var s = "hidden<br>";
      $('#'+divid).append(s);
   }

   // This is the function we feed to the jQuery click method.
   function switchState(target)
   {
      $('#'+current).hide();
      postHide(current);
      preShow(target);
      $('#'+target).show();
      current = target;
   }

   // and this is where we set the clicks up at initialization time.
   function setclick()
   {
      var trigger = $(this);
      var id = trigger.attr("data-assocdiv");
      trigger.click(function() { switchState(id); });
   }

   // The very useful each() function applies setclick to each trigger element. 
   $('.'+triggerclass).each(setclick);
   
   // Finally show the default div
   current = defdiv;
   preShow(current);
   $('#'+current).show();
}

$(function() {
   // Page is loaded - initialize the triggers and show the default div.
   fixClix("trigger", "feed");
});
That's it. In the script, the only changes you need to make are to preShow() and postHide() - those can of course just contain calls to other global functions in your overall script - and at the call to fixClix().