Tuesday, December 25, 2012

Implementing my Useful Resources Page part 2

Introduction

This is the second part of my overview of how I implemented the Useful Resources page. This part focuses on the HTML and Javascript portions.

I'm using JQuery to animate the collapsible menus, as well as perform various selection and event handling tasks.

DOM Structure

The most important design criteria of the DOM structure is that it must be easily generatable from a script. After all the original goal for creating this tool was to make it easy modify the base structure without mucking with the look and feel of the page.

First is a system for assigning element ID's. Since I share different elements the individual identifiers I use in my XML structure can't be used directly. To solve this issue I decided to concatenate the ancestry ID's. For example, take the following XML structure:

<cat tag="doc">
 <cat tag="cs">
  <cat tag="c">
  </cat>
  <cat tag="java">
  </cat>
 </cat>
</cat>
<cat tag="user">
 <cat tag="cs">
  <cat tag="c">
  </cat>
  <cat tag="java">
  </cat>
 </cat>
</cat>

This would result in an html ID structure like this:

  • doc
  • doc_cs
  • doc_cs_c
  • doc_cs_java
  • users
  • users_cs
  • users_cs_c
  • users_cs_java

The Table of Contents Section

This is a fairly simple nested list structure. I don't use the default numbering system because I want a tree-like numbering system. I probably could have created the nested feel without using HTML lists, but whatever.

I also use an anchor element so that the user can click on the heading to collapse the table of contents. This is fairly standard practice for creating clickable portions in a webpage.

<h1 class ="h1"><a href="javascript:void(0)" class="toggle zippy" id="toc"><span>▼</span> <span style="color: #000">Table of Contents</span></a></h1>
<ul id="toc_section" style="list-style-type:none;">
 <li>
  <span>1. </span><a href="#doc" class="toc_item">Manuals & Documentation</a>
  <ul style="list-style-type:none;">
   <li>
    <span>1.2. </span><a href="#doc_cs" class="toc_item">Programming and Computer Science</a>
    <ul style="list-style-type:none;">
     <li>
      <span>1.2.1. </span><a href="#doc_cs_c" class="toc_item">C</a>
     </li>
     <li>
      <span>1.2.2. </span><a href="#doc_cs_java" class="toc_item">Java</a>
     </li>
    </ul>
   </li>
  </ul>
 </li>
</ul>

Category Section

Again, not a super complicated section. This time I uses div sections with margins to nest each section. I also use the same anchor element structures for each collapsable header.

<h1 class ="h1"><a href="javascript:void(0)" class="toggle zippy" id="doc"><span>▼</span> <span style="color: #000">1. Manuals &amp; Documentation</span></a></h1>
<div id="doc_section">
 <div style="margin: auto 8px auto 8px;">This is where you can find how to do something or what something does. This includes user manuals, API documentation, tutorials &amp; how-to's, etc.</div>
 <div>
  <h1 class ="h1"><a href="javascript:void(0)" class="toggle zippy" id="doc_cs"><span>▼</span> <span style="color: #000">1.2. Programming and Computer Science</span></a></h1>
  <div id="doc_cs_section">
   <div>
    <h1 class ="h1"><a href="javascript:void(0)" class="toggle zippy" id="doc_cs_c"><span>▼</span> <span style="color: #000">1.2.1. C</span></a></h1>
    <div id="doc_cs_c_section">
     <div style="margin: auto 8px auto 8px;">Items dealing with the C programming language.</div>
     <ul>
      <li><a href="http://cdecl.org/" target="_blank">cdecl</a>
       <div>Translates C code to and from english.</div>
      </li>
     </ul>
    </div>
   </div>
   <div>
    <h1 class ="h1"><a href="javascript:void(0)" class="toggle zippy" id="doc_cs_java"><span>▼</span> <span style="color: #000">1.2.2. Java</span></a></h1>
    <div id="doc_cs_java_section">
    <ul>
     <li><a href="http://docs.oracle.com/javase/7/docs/api/" target="_blank">Java 7 SE Javadoc</a>
      <div>Java 7 API Documentation.</div>
     </li>
     <li><a href="http://docs.oracle.com/javase/tutorial/" target="_blank">The Java Tutorials</a>
      <div>The Official tutorials for the Java language and library.</div>
     </li>
    </ul>
    </div>
   </div>
  </div>
 </div>
</div>

The Javascript

I use Javascript to make the menus collapsable. As with pretty much any Javascript-enabled webpage it's important to ensure that the DOM you're operating on is loaded. The easiest way is to this is to run your initialization code and stuff once the document is loaded.

I probably could have had my generation script hard-code the tags to fold, but I decided to use the JQuery selectors instead.

$(document).ready(function()
 {
  // table of content links: unfold all section
  $('.toc_item').click(function(){
   // extract the relative path
   var href = this.href;
   href = href.substring(href.indexOf('#') + 1, href.length);
   var items = href.split('_');
   var base = '';
   // get all items which need to be expanded
   var valid_items = $();
   for(var i = 0; i < items.length; ++i)
   {
    if(i > 0)
    {
     base += '_';
    }
    base += items[i];
    
    // find the base item and expand it
    var item = $('#' + base + '_section');
    if(item.length !== 0)
    {
     valid_items = valid_items.add(item);
    }
   }
   
   for(var i = 0; i < valid_items.length; ++i)
   {
    // valid section, try to expand it
    var item = $(valid_items[i]);
    if(item.hasClass('collapsed'))
    {
     item.slideToggle(0);
     item.removeClass('collapsed');
     $('#' + base).children().first().html('▼');
    }
   }
  });
  
  var items = $('div').filter(function() {
   if(this.id.match(/.*_section$/) === null)
   {
    return false;
   }
   return true;
  });
  items = items.add('#toc_section');
  
  var temp = items.parent();
  temp.css('border', 'solid 1px #808080');
  temp.css('margin', '4px');
  
  items.prev().children().click(function(){
   var toggle_item = $('#'+this.id);
   var item = $('#'+this.id+'_section');
   item.slideToggle(250);
   if(item.hasClass('collapsed'))
   {
    item.removeClass('collapsed');
    toggle_item.children().first().html('▼');
   }
   else
   {
    item.addClass('collapsed');
    toggle_item.children().first().html('►');
   }
  });
});

Generation script

I don't think I'll post the generation script here as it's a bit long. The basic idea is that it recursively traverses my DOM-like structure I created last time. The output is conditioned to be what I have above. I may upload the project to a code hosting site in the future.

No comments :

Post a Comment