September 12th, 2005

Blog Customizations

Heath Stewart
Principal Software Engineer

In my seemingly never-ending quest to provide a simple, compact, yet stylish design for this blog I have recently made a customization based on what Josh Ledgard did sometime back to make collapsible panels, though I wanted something more easily reusable. I whipped together an ECMAScript — that is, ECMA-compliant JScript and JavaScript — class as you can see below:

function CollapsiblePanel(elem) {
  if (!elem) {
    return null;
  }
  // Close 'this'.
  var self = this;
  this.toggle = function() {
    if (self.sibling.style.display == "none") {
      self.elem.innerHTML = self.collapseHTML + self.title;
      self.sibling.style.display = "block";
    } else {
      self.elem.innerHTML = self.expandHTML + self.title;
      self.sibling.style.display = "none";
    }
  }
  this.elem = elem;
  this.title = elem.innerHTML;
  this.expandHTML = '<img src="expand.gif" width="9" height="9">&nbsp;';
  this.collapseHTML = '<img src="collapse.gif" width="9" height="9">&nbsp;';
  this.elem.style.cursor = "pointer";
  this.sibling = elem.nextSibling;
  if (this.sibling.nodeType == 3) {
    // Get second sibling if text node is next.
    this.sibling = this.sibling.nextSibling;
  }
  elem.onclick = this.toggle;
  this.toggle();
}

Since I’m defining an event handler to handle toggling the CSS display attribute, I need to create a closure around the class instance, which is why the private variable self is defined. Had I used this in the event handler, when the onclick event was fired this would refer to the item that was clicked – the H3 element.

To create the CollapsiblePanel instances, I needed to handle the window.onload event. Since the only place .Text or Community Server lets us add our own script is in the News section, several headers are not parsed and displayed until after the script is processed synchronously:

window.onload = function() {
  // Enumerate headers after document is loaded.
  var i, h3s = document.body.getElementsByTagName("h3");
  for (i = 0; i < h3s.length; i++) {
    var elem = h3s.item(i);
    if (elem.innerHTML == "Archives" ||
        elem.innerHTML == "Common Tasks" ||
        elem.innerHTML == "Navigation") {
      new CollapsiblePanel(elem);
    }
  }
}

Since Josh’s blog gave me the idea to collapse a few of the longer or less interesting panels, I shared the code with him that you can find on his blog now, too. Feel free to use it yourself. You can easily customize the view by changing the expandHTML and collapseHTML public fields, though you’re free to change anything. Please keep in mind that this is not Microsoft-supported code, but if you have questions feel free to ask on this particular blog.

When a get I little time I will create a cookie collection class to hold state for each individual CollapsiblePanel so that your preference for what is and is not displayed is persisted across pages.

Author

Heath Stewart
Principal Software Engineer

Heath is an application architect and developer, looking to help educate others to learn professional development. Besides designing and developing applications he enjoys writing about intermediate and advanced topics. Heath also consults for deployment packages and scenarios within Microsoft and for external customers.

0 comments

Discussion are closed.