var W3CDOM = ( document.createElement && document.getElementsByTagName );

addEvent( window, 'load', initCollapsingRows );

var pathToImages = "/images/";
var expandGif = pathToImages + "btnPlus2.gif";
var collapseGif = pathToImages + "btnMinus2.gif";

function addEvent ( obj, eventType, fn, useCapture )
{

   if( obj.addEventListener )
   {
      obj.addEventListener( eventType, fn, useCapture );
      return true;
   }
   else if( obj.attachEvent )
   {
      var r = obj.attachEvent( "on" + eventType, fn );
      return r;
   }

}

function getAttribute ( tag, attributeName )
{

   // make sure tag is an "Element" node
   if( tag.nodeType != 1 )
      return null;

   if( tag.getAttributeNode( attributeName ) != null )
      return tag.getAttributeNode( attributeName ).value;
   return null;

}

function getClasses ( tag )
{

   var classValue = getAttribute( tag, 'class' );
   var classes = new Array();
   if( ( classValue != null ) && ( classValue.length > 0 ) )
      classes = classValue.split( ' ' );
   return classes;

}

function swapClass( tag, oldClass, newClass )
{

   var oldClasses = getClasses( tag );
   var newClasses = new Array();
   while( oldClasses.length > 0 )
   {
      var className = oldClasses.shift();
      if( className != oldClass )
         newClasses.push( className );
   }
   newClasses.push( newClass );
   setAttribute( tag, 'class', newClasses.join( ' ' ) );

}

// set must be an array
function contains( set, regex )
{

   for( var i = 0; i < set.length; ++i )
   {
      if( set[ i ].match( regex ) )
         return true;
   }
   return false;

}

function toggleVisibility ()
{

   var idPrefix = this.id + '_event_';
   var records = document.getElementsByTagName( 'tr' );

   // sanity check
   if( records.length == 0 )
      return;

   var classes = getClasses( this );
   var printable = contains( classes, '^printable$' );

   // sanity check
   if( ! ( printable || contains( classes, '^unprintable$' ) ) )
      return;

   var printableClass;
   var oldPrintableClass;
   var newDisplayStyle;
   var newImageSource;
   if( printable )
   {
      printableClass = 'unprintable';
      oldPrintableClass = 'printable';
      newDisplayStyle = "none";
      newImageSource = expandGif;
   }
   else
   {
      printableClass = 'printable';
      oldPrintableClass = 'unprintable';
      newDisplayStyle = "";
      newImageSource = collapseGif;
   }

   swapClass( this, oldPrintableClass, printableClass );
   var image = document.getElementById( this.id + '_image' );
   image.src = newImageSource;

   for( var i = 0; i < records.length; ++i )
   {

      var record = records[i];
      // if the record has an id
      var id = getAttribute( record, 'id' );
      if( ( id != null ) && ( id.indexOf( idPrefix ) != -1 ) )
      {
         swapClass( record, oldPrintableClass, printableClass );
         record.style.display = newDisplayStyle;
      }

   }

}

// requires a <tr> element
function insertExtraCells ( record )
{

    // get reference to all of the cells
    var cells = record.getElementsByTagName( 'th' );
    if( cells.length == 0 )
        cells = record.getElementsByTagName( 'td' );

    // create a new cell
    var newCell = document.createElement( 'td' );

    // insert the new cell before the first cell
    record.insertBefore( newCell, cells[0] );

}

// requires a <tr> element
function expandFirstCell( record )
{

    var cells = record.getElementsByTagName( 'th' );
    if( cells.length == 0 )
        cells = record.getElementsByTagName( 'td' );

    // nothing to do if we have no cells
    if( cells.length == 0 )
        return;

    setAttribute( cells[0], 'colspan', '2' );

}

// requires any html tag, an attribute to set, and a value to set
function setAttribute ( tag, attributeName, attributeValue )
{

   var attribute = document.createAttribute( attributeName );
   attribute.value = attributeValue;
   tag.setAttributeNode( attribute );

}

function initCollapsingRows ()
{

   if( !W3CDOM )
      return;

    // get a list of all the records
   var records = document.getElementsByTagName( 'tr' );

   // if there aren't any records exit
   if( records.length == 0 )
      return;

   var lastHeaderName = null;
   for( var k = 0; k < records.length; ++k )
   {

      var record = records[ k ];
      var classes = getClasses( record, 'class' )

      // in case we already initilized the record
      if( ! contains( classes, 'printable' ) )
      {

         // if that class is a "header"
         if( contains( classes, '^EventList_header$' ) )
         {
            swapClass( record, null, 'printable' );
         }
         else if( contains( classes, '_emptyHeader$' ) )
         {

            // since we are adding a graphic for expanding and collapsing
            // the rows in the first column of the record, we need to add
            // an extra column everywhere
            insertExtraCells( record );

            // Get a reference to the TH's
            var cells = record.getElementsByTagName( 'td' );
            cells[0].style.width = "1%"
            // Append " (No reports)" to the empty records...
            cells[1].innerHTML = cells[1].innerHTML + " (No reports)";

            // Add "onclick" event to the record that expands and collapses the next row
            lastHeaderName = "emptyHeader_" + k;
            record.id = lastHeaderName;

            // The record is not printable
            swapClass( record, 'printable', 'unprintable' );
            swapClass( record, null, 'emptyEventHeader' );

         }
         else if( contains( classes, '_header$' ) )
         {

            // since we are adding a graphic for expanding and collapsing
            // the rows in the first column of the record, we need to add
            // an extra column everywhere
            insertExtraCells( record );

            // Get a reference to the TH's
            var firstCell = record.getElementsByTagName( 'td' )[0];

            // Add "onclick" event to the record that expands and collapses the next row
            lastHeaderName = "header_" + k;
            record.id = lastHeaderName;
            record.onclick = toggleVisibility;

            // The unopened record is not printable
            swapClass( record, 'printable', 'unprintable' );
            swapClass( record, null, 'eventHeader' );

            // Create the new image object
            var image = document.createElement( 'img' );
            image.src = expandGif;
            image.id = lastHeaderName + "_image";
            image.width = 13;
            image.height = 13;
            image.style.margin = "5px";
            image.style.cursor = "pointer";

            // Insert an image into the document tree inside the first TD
            firstCell.appendChild( image );
            firstCell.style.width = "1%"

         }
         // hide all "event", "spacer" and "label" records until selected
         else if( contains( classes, '^event$' )
               || contains( classes, '^label$' )
               || contains( classes, '^spacer$' ) )
         {
            expandFirstCell( record );

            // Assign a unique ID to the this row
            // This is the row that will be expanded and collapsed
            record.id = lastHeaderName + "_event_" + k;
            record.style.display = "none";
         }

      }

   } // End for loop

}

function expandAllEvents ()
{

   var records = document.getElementsByTagName( 'tr' );
   for( var i in records )
   {

      // if the record has an id
      var currentRecordID = getAttribute( records[i], 'id' );
      if( currentRecordID != null )
      {

         if( currentRecordID.match( '_event_' ) )
         {
            swapClass( records[i], 'unprintable', 'printable' );
            records[i].style.display = "";
         }
         else if( currentRecordID.match( '^header_' ) )
         {
            swapClass( records[i], 'unprintable', 'printable' );
            var image = document.getElementById( currentRecordID + '_image' );
            image.src = collapseGif;
         }

      }

   }

}

function printerFriendlyEventList ()
{

   var docTitle = "Printer Friendly Event Listing";
   var headerText = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
                  + '<html><head><title>' + docTitle + '</title></head><body>';
   var footerText = '</body></html>';

   var eventList = document.getElementById( "EventListTable" ).cloneNode( true );
   hideNonPrintableElements( eventList );

   // allow the toolbar and menubar (for the print menu/buttons)
   // shrink the page to good printable settings (with decent margins)
   var settings = "toolbar=1, menubar=1, scrollbars=1, resizeable=1, "
                + "width=650, left=100, top=25, right=100, bottom=25";
   var printWindow = window.open( "", "", settings );
   printWindow.document.write( headerText );
   printWindow.document.write( eventList.innerHTML );
   printWindow.document.write( footerText );
   printWindow.document.close();
   printWindow.focus();

}

function hideNonPrintableElements ( element )
{

   var childNode = getFirstChildNode( element );
   while( childNode != null )
   {

      // elements are nodes of type 1
      if( ( childNode.nodeType == 1 ) && childNode.hasChildNodes() )
         hideNonPrintableElements( childNode );

      // must get the next childNode before we delete this one
      var nextNode = getNextSibling( childNode );
      if( childNode.style && ( childNode.style.display == 'none' ) )
      {
         element.removeChild( childNode );
      }
      else if( contains( getClasses( childNode ), '^unprintable$' ) )
      {
         element.removeChild( childNode );
      }

      childNode = nextNode;

   }

}

function getFirstChildNode ( element )
{

   if( element == null )
      return null;
   return element.firstChild;

}

function getNextSibling ( node )
{

   if( node == null )
      return null;
   return node.nextSibling;

}
